Each audit is a read-only Bedrock tool-use run over repo source + live platform state, on the shared
agent engine (shared/modules/agent/engine.js). Every tool is a READ
(list_tree, read_file, list_dir, platform_state) — the auditor
cannot change the platform it audits. The model is Sonnet 4.6 (the account has Bedrock access to it).
| jobId | Audit | Cadence (UTC) |
|---|---|---|
audit-discipline | Foundation & cartridge discipline drift vs. doctrine | daily 07:00 |
audit-soc2 | Security & SOC 2 compliance | weekly Mon 07:30 |
audit-cartridge | Cartridge quality & anti-patterns | weekly Mon 08:00 |
All three fire on their cron and on demand. The manual path sends { source:'manual-run', jobId };
the handler accepts it alongside the EventBridge { source:'eventbridge-scheduler', jobId }. Every fire writes
start + terminal run records into the shared agent-state table (agent_session_id='job-run'), which the obs
Schedules tab and the watchdog read (Step 6.k).
A scheduled run has no signed-in user, so the cartridge uses a dedicated system identity:
/forge/audit/github-token), set once by an operator — never Terraform, never code. This is
deliberately outside the per-user OAuth broker (Doctrine: per-user connections are for signed-in users).github-read-token-not-set and spends no Bedrock tokens — the operator sees the reason in obs, not a silent no-op.
A finished report is filed as a versioned document in the Foundation Audit Doc Vault project via the
system-publish path — a direct lambda:InvokeFunction carrying
{ source:'system-publish', … }, checked before Doc Vault's HTTP gates (the IAM invoke
permission is the authorization, exactly like the trash-sweep). It ensures a _system-owned project by fixed
projectId, optionally grants viewer to the configured reader, then runs the same commit invariants (discipline check +
append-only version). Publishing is best-effort: a publish problem never fails the audit (the report is already recorded).
audit_report_reader (tfvars) to your cognito:username, or reports publish but stay
system-owned (unreadable) until granted through the obs share picker. Same "operator supplies identity" pattern as the GitHub PAT.
The cartridge was backend-only; it now ships a small console the Console launcher iframes (its own S3+CloudFront
frontend and an API Gateway HTTP API behind the same X-Origin-Secret gate). The handler dispatches
on event shape — an HTTP request carries event.rawPath; the scheduled paths carry
event.source and never a rawPath — so an HTTP request still cannot spoof its way into a run.
| Route | Auth | Does |
|---|---|---|
GET /api/health | origin secret | liveness |
GET /api/config | + pool JWT | audit catalog + doc-vault project + flags |
GET /api/runs | + pool JWT | recent run history (Query on the agent-state table) |
POST /api/run | + admins / cart-foundation-audit | fire an audit now (async self-invoke = obs manual-run) |
The tile is gated to the cart-foundation-audit group (admins bypass). Run-now is an async self-invoke with a
deterministic-ARN IAM grant (avoids the role↔function cycle); the UI returns immediately and polls
/api/runs while a run is running.
The console edits this cartridge's CLAUDE.md / skills.md in place — the same versioned
Content CMS docs that steer the built-in audits and that an external evaluator pulls over the
Console MCP. The handler forces cartridge=foundation-audit, scope='_';
read is any signed-in user, write is admins / the cart group.
| Route | Does |
|---|---|
GET /api/grounding | active CLAUDE.md + skills.md bodies/versions |
PUT /api/grounding/{name} | save a new active version of claude/skills |
console-content had to be added to the agent-tier DDB gateway endpoint policy
(cartridge_table_patterns) for the reads/writes to reach it. That change also unblocked
squad-assess/workbench grounding reads, which were being silently denied at the endpoint before (best-effort masked it).
IAM still gates each role — foundation-audit gets read+write on that one table only.
Beyond the built-in audits, an operator can point their own scheduled Claude Code at this cartridge over the
Console MCP. The in-cart guide ("Connect a scheduled evaluator") walks it: mint a machine
token targeting foundation-audit with boundaries grounding + publish, set the machine up with
one paste, then a cron that pulls the current doctrine (grounding_manifest/grounding_get),
reviews the repo, and calls publish_evaluation into this cartridge's Doc Vault project. The reviews land
alongside the built-in audits, through the same discipline gate.
lambda/handler.js (dispatch + scheduled run + HTTP surface),
lambda/lib/{audits,github,report-doc,run-record,console-api}.jsbackend.tf (Lambda, API Gateway, IAM, staging), frontend.tf
(S3 + CloudFront), auth.tf (Cognito client), cloudfront/spa-router.jsfrontend/{index.html,app.js,styles.css,locales/en.js}module.foundation_audit + the console_app URL wiring in
substrate/environments/ai-sandbox/main.tf; scheduled via the platform/schedules module