Skip to content

Agent runtime governance compliance (R1–R9): tracking + gap analysis #216

Description

@naveen-kurra

Tracking issue for aligning Forge with a 9-requirement agent-runtime governance framework (6 MUST + 3 SHOULD). Framework complete on main as of 2026-07-07.

Compliance matrix — post-merge state

# Requirement Status Landed via Where it lives
R1 Pre-execution interception ✅ pass baseline BeforeToolExec hook fires from Registry.Execute; every LLM-chosen action emits tool_exec phase=start from inside the hook chain
R2 Context accumulation ✅ pass baseline correlation_id + task_id on every audit event; monotone per-invocation seq; MemoryStore; task.History; workflow correlation headers
R3 Policy w/ intent alignment ✅ complete #245 (#208) forge-core/security/intent/; security.intent_alignment yaml block; real cosine similarity per tool call; fail-closed on embedder error
R4a MODIFY decision (general) ✅ complete #221 (#209) Generalized beyond cli_execute — every gate can return DecisionModify via Modify(newContent, reason)
R4b STEP_UP decision ✅ complete #247 (#210) forge-core/security/stepup/; security.step_up yaml block; missing/weak acr → HTTP 401 with RFC 9470 WWW-Authenticate challenge
R4c DEFER decision (resumable) ✅ complete #248 (#211) forge-core/security/deferpolicy/; security.defer yaml block; BeforeToolExec pauses the executor goroutine; POST /tasks/{id}/decisions approves/rejects; timeout auto-denies
R5 Tamper-evident receipts ✅ complete #237 (#212) prev_hash = sha256(previous raw JSON line); genesis = 64 zeros; forge audit verify detects byte-flips, order swaps, dropped events
R6 Cryptographic identity binding ✅ complete #237 (#213) Ed25519 signature per event over JCS canonical form (RFC 8785); sigp: "jcs-1" marker; GET /.well-known/forge-audit-keys serves JWKS
R7 Semantic distance ✅ complete #246 (#214) forge-core/security/intent/drift.go; security.intent_drift yaml block; rolling-window mean-below-threshold + monotone-decrease trip; state-transition dedup (no per-call flood)
R8 OpenTelemetry export ✅ pass baseline (#108) observability.tracing yaml block; OTLP HTTP/gRPC export; audit events carry trace_id + span_id — SIEM ↔ APM loop closed
R9 Least-privilege credentials ✅ complete #236 (#215) forge-core/credentials/; top-level credentials: yaml block; providers static + sts_assume_role; per-tool-call injection; credential_issued + credential_revoked audit; no material in audit payloads

Live verification

Every requirement has an end-to-end live test driven with a real OpenAI key against an actual forge run subprocess. 27 subtests, 0 failures.

ok  github.com/initializ/forge-compliance-suite/e2e/r1_intercept     3.7s   2/2
ok  github.com/initializ/forge-compliance-suite/e2e/r2_context       5.3s   2/2
ok  github.com/initializ/forge-compliance-suite/e2e/r3_intent        8.6s   3/3
ok  github.com/initializ/forge-compliance-suite/e2e/r4_decisions     9.4s   5/5
ok  github.com/initializ/forge-compliance-suite/e2e/r5_receipts      8.8s   5/5
ok  github.com/initializ/forge-compliance-suite/e2e/r6_identity      5.8s   5/5
ok  github.com/initializ/forge-compliance-suite/e2e/r7_drift        10.7s   1/1
ok  github.com/initializ/forge-compliance-suite/e2e/r8_telemetry     9.0s   2/2
ok  github.com/initializ/forge-compliance-suite/e2e/r9_leastpriv     6.1s   2/2

No mocks in the policy path. The LLM is real (OpenAI gpt-4o-mini). The embedder is real (OpenAI text-embedding-3-small). The forge binary is the same binary shipped to production. Attacker-side coverage on R5/R6 (byte-flip, order-swap, dropped-event, sig-tamper, wrong-JWKS all detected).

Documentation

Every governance feature has its own dedicated doc plus cross-links from the top-level references:

The event catalog in docs/security/audit-logging.md, the security: schema in docs/reference/forge-yaml-schema.md, the hook reference in docs/core-concepts/hooks.md, and .claude/skills/forge.md's § 12 + § 17 all list the full governance surface. Backfilled in #256.

Rollout guidance

Every governance block ships off by default — an absent block leaves the corresponding hook unregistered and the wire shape unchanged from a pre-governance deployment. Recommended sequence for turning them on:

  1. R5 + R6 first. Set FORGE_AUDIT_SIGNING_KEY_B64. Zero policy impact; you immediately get tamper-evident + signed receipts.
  2. R9 next. Add a credentials: block for the highest-privilege tool. STS provider for AWS scoping, static for header/env injection.
  3. R3 warn-only. Enable security.intent_alignment with hard_threshold: -1 for a sprint. Tail intent_alignment events, learn your embedder's distribution.
  4. R3 deny. Once you have a distribution, raise hard_threshold a bit below the observed floor of normal traffic.
  5. R7 on top of R3. Add security.intent_drift. Analyzer wires automatically; drift is telemetry-only (never changes the R3 decision).
  6. R4b step-up. Declare the tools that need higher assurance under security.step_up.tools. Requires the caller's auth chain to actually emit acr claims — coordinate with the IdP.
  7. R4c defer. Declare tools that need human approval under security.defer.tools. Use tasks/sendSubscribe (SSE) or async A2A for approval windows > a few seconds — synchronous tasks/send blocks the connection for the whole timeout.

Child issues

All closed:

Closing this umbrella — framework is complete. Follow-up governance work (R10+ if the framework extends, additional hardening of any specific R) will get its own tracking issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestforge-coreAffects the forge-core library (runtime, security, types, llm, mcp, auth)securitySecurity vulnerability fixes

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions