Skip to content

Latest commit

 

History

History
216 lines (169 loc) · 9.53 KB

File metadata and controls

216 lines (169 loc) · 9.53 KB

AGENTS.md

Guidance for coding agents working in this repository.

Key Commands

just check # Run all local verification checks (CI parity)
just fmt # dprint check (TOML + Markdown + Rust)
just lint # cargo clippy --workspace -- -D warnings
just hawk # unnecessary public API visibility (macOS and Linux)
just test # cargo nextest run + cargo test --doc
just build # cargo build --workspace

Tests run via cargo nextest (process-per-test isolation); doctests run separately via cargo test --doc since nextest does not run them.

Requires protoc installed for protobuf compilation (firma-protobuf and firma-grpc-interceptor-proto both compile .proto files via tonic-prost-build against a system protoc).

Formatting

dprint is the single formatter for the repo. Run dprint fmt after modifying .toml, .md, or .rs files. just fmt runs dprint check in CI.

docs-site/ is excluded and uses its own toolchain.

Linting Rules

Workspace lints are strict and enforced in CI:

  • clippy::pedantic warn
  • clippy::unwrap_used deny
  • clippy::expect_used deny
  • clippy::panic deny
  • unsafe_code deny

Do not use .unwrap(), .expect(), panic!(), or unsafe. Prefer Result<T, E> with thiserror for error handling.

API Stability

Rust APIs in crates whose Cargo metadata resolves to publish = false are internal implementation details, even when their items are declared pub for workspace use. Do not report visibility reductions, removals, or signature changes in those crates as SemVer-breaking changes. Still update all workspace callers and verify the workspace.

Review user-facing compatibility separately. CLI behavior, configuration and file formats, network and wire protocols, and documented integration contracts may be stable boundaries regardless of a crate's publish setting.

Rust Tests

Before adding or moving Rust tests, load and follow the rust-tests-guidelines skill.

Before adding or changing CLI, deterministic E2E, live-agent, or VS Code coverage, load and follow the writing-black-box-tests skill.

Supported Platforms

OpenFirma supports only Unix and Windows targets. When implementing platform-specific behavior, use #[cfg(unix)] and #[cfg(windows)] code paths. Do not add fallback, no-op, passthrough, stub, or compile_error! code for unsupported targets. It is acceptable for unsupported targets to fail naturally due to missing platform-specific implementations.

Version Control

Some contributors use Git, some use Jujutsu.

  • Invoke jj from the working copy to determine whether the local clone uses Jujutsu; do not infer this by inspecting the filesystem for .jj/.
  • If the jj probe succeeds, prefer jj commands for history, diff, conflict resolution, and changeset manipulation.
  • If the jj probe fails because the clone is not a Jujutsu workspace, use Git.
  • Do not assume every clone uses jj; detect the active VCS before choosing commands.
  • When giving user-facing revision identifiers or instructions, match the VCS actually in use in that clone.

Atomic Revisions

Whenever the working copy is already dirty or you are about to touch revision history, use the repository skills instead of improvising:

  • commit-guidelines for dirty-worktree inspection, atomic checkpoint commits/changesets, and reviewed-history preservation
  • open-pr for opening GitHub pull requests
  • split-jj-changeset for splitting mixed Jujutsu changesets
  • verify for per-revision and final verification

Use commits or jj changesets as local checkpoints during substantial work. Prefer small atomic revisions that can stand on their own when feasible.

Planning and Review Routing

Before implementing any behavior or architecture change, load and follow the planning-changes skill. It determines whether formal planning applies and, when it does, selects a Full or Compact workflow and defines the evidence-backed design-plan artifact. Full triggers take precedence over both Compact planning and no-plan exemptions regardless of the expected size or locality. Accepted plans and findings must have a durable, team-accessible repository path or URL; do not rely on an agent or private conversation as the handoff.

Use adversarial-review to select an independent reviewer. It routes plan reviews to reviewing-plans and implemented changes to reviewing-changes, with review-rust-code added for Rust changes. Plan review does not replace post-implementation review.

Architecture

OpenFirma is an L7 policy enforcement sidecar for AI agents. Every outbound agent call passes through the Sidecar before reaching external systems.

Crates

  • firma-core — shared types and trait contracts such as Decision, ExecutionEnvelope, CapabilityClaims, TokenVerifier, TokenSigner, PolicyEvaluator, and RevocationStore. No dependencies on other crates.
  • firma-audit-schema — behavior-free Decision and ExecutionEvent types shared by audit producers, tests, and third-party JSONL consumers.
  • firma-protobuf — gRPC wire contract via protobuf, vendored in-tree at crates/firma-protobuf. build.rs compiles .proto files with tonic-prost-build. Owns the firma.v1.EnforcementDecision enum (AARM R4: ALLOW/DENY/ABORT/MODIFY/STEP_UP/DEFER).
  • firma-grpc-interceptor-proto — the agent↔sidecar interceptor hook proto, separate from firma-protobuf (Authority↔Sidecar contract).
  • firma-sidecar — enforcement proxy binary. Key top-level modules:
    • interceptor — captures outbound agent traffic.
    • normalizer — maps raw HTTP requests to canonical ExecutionEnvelope values with normalized action classes. Unclassifiable protected actions fail closed to DENY.
    • enforcement — two-stage engine: capability validation, then constraint enforcement.
    • pipeline — orchestrates normalizer and enforcement through a single enforce() entry point.
  • firma-authority — local/dev Authority reference implementation. Issues PASETO v4 tokens and streams policy bundles and revocations. Never on the hot path.
  • firma-config-loader — shared firma.toml discovery, schema loading, and agent profile parsing used by the CLI and runtime crates.
  • firma-secret-provider — secret-provider spec types (IntegrationSpec: Cli/Http variants), the built-in IntegrationRegistry of CLI vault specs, the extraction engine (CompiledMatcher, SecretPlaceholder), and the shared endpoint module: unix:///tcp:// ClientEndpoint / ServerEndpoint transport addresses used by the gateway and broker modules. The store module owns the run-scoped placeholder↔secret dictionary (SecretStore, moved here from firma-run). The gateway module holds the GatewayRequest wire types, the GatewayClient transport (resolve_batch/push_secret), and the GatewayListener server that serves the same protocol from the SecretStore, for the Sidecar↔broker secret-gateway protocol. The broker module holds the out-of-sandbox secret-shim transport: BrokerClient (shim-side) and BrokerListener (broker-side) speaking a newline-terminated JSON protocol over unix:// (Unix) or tcp:// loopback (Windows), plus the shared BrokerConfig. Shared by firma-run (CLI vault shims, via secret_providers config) and firma-sidecar (HTTP vault MITM interception, via the mirrored http_secret_providers config). Depends only on firma-core and firma-http among Firma crates.

Key Invariants

  • Fail closed: every error becomes a DENY decision.
  • No network on the hot path: enforcement is fully local.
  • Deterministic enforcement: same context plus same policy bundle yields the same decision.
  • Immutable execution envelopes: treat ExecutionEnvelope as immutable once created.

Mapping Rules Configuration

The normalizer's host/method/path to action-class mapping is loaded from TOML at startup by startup::pipeline::build_pipeline_runtime.

[enforcement.mapping] supports:

  • rules_path: String — primary mapping file, defaulting to mapping-rules.toml.
  • rules_paths: Vec<String> — additional mapping files merged on top.

Rules from rules_path and each entry in rules_paths are concatenated before passing to MappingTable::from_config. Duplicate (method, host, path) tuples across merged files fail at startup.

Shipped mapping files live under crates/firma-sidecar/config/mappings/:

  • github.toml
  • stripe.toml
  • gmail.toml
  • composio.toml

Documentation

After any major behavior, architecture, CLI, configuration, or public API change, update the docs site under docs-site/ in the same change set. If the change affects how people should discover or integrate OpenFirma, update docs-site/public/llms.txt as well.

Write docs for a human reader first:

  • Start from the user's task or question, not from internal implementation order.
  • Keep prose concise, concrete, and free of marketing filler.
  • Prefer small examples, commands, and links to related pages over long theory.
  • Name important invariants explicitly: fail closed, no network on the hot path, deterministic enforcement, and immutable execution envelopes.
  • Document sharp edges and operational gotchas when they affect real use.