?

The story

You are a platform engineer at a mid-sized bank. Compliance says any coding assistant your engineers use must:

  1. Run inside the bank's AWS accounts, not on a SaaS control plane.
  2. Route model traffic through a provider the bank has a contract and an audit trail with (Bedrock).
  3. Have a documented supply-chain posture (SLSA-3, SBOM, signature verification).
  4. Enforce approval policies with a machine-readable audit trail.
  5. Not exfiltrate source code to a third party.

Rousseau's positioning maps onto every one of those requirements. You run it as a Kubernetes Deployment in the platform team's EKS cluster, driving a Slack Socket Mode transport into the engineering channel.

The engineering rollout is unremarkable — a Deployment, a Secret, a ConfigMap, a PersistentVolumeClaim. The story is what happens when the auditor arrives.

The audit

An external auditor asks four questions.

Q1: Where does model traffic go?

You point them at internal/llm/bedrock/. The provider uses the standard AWS credential chain (via IRSA on EKS), so credentials are short-lived STS tokens. The traffic never leaves your AWS account.

Q2: How do you verify the binary you're running?

You show them docker/Dockerfile — a multi-stage build with a pinned golang:1.26-alpine base — and the release-verify.sh script the SRE team runs during image promotion:

cosign verify-blob \
  --certificate-identity-regexp 'sebastienrousseau/rousseau-agent' \
  --certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
  --signature rousseau_${VERSION}_checksums.txt.sig \
  rousseau_${VERSION}_checksums.txt

sha256sum -c rousseau_${VERSION}_checksums.txt

You add: SLSA-3 provenance is attested through GitHub Actions OIDC. The Sigstore transparency log is a public trust anchor.

Q3: How do you prevent the model from mutating production?

You point them at the agent.approver config:

agent:
  approver:
    mode: pattern
    default: deny
    reason: "denied — this deployment does not permit destructive operations without operator confirmation"
    allow:
      - {tool: read, match: ".*"}
      - {tool: grep, match: ".*"}
      - {tool: edit, match: "\"path\":\"/workspace/[^\"]*\""}
      - {tool: write, match: "\"path\":\"/workspace/[^\"]*\""}
      - {tool: bash, match: "^\\s*\"command\":\\s*\"(ls|cat|grep|rg|find|git status|git diff|git log|go test|go build) "}
    deny:
      - {tool: bash, match: "rm -rf|sudo|curl|wget|chmod|chown"}
      - {tool: bash, match: "kubectl (delete|apply|edit|scale|exec)"}
      - {tool: bash, match: "aws (s3 rm|iam|kms delete)"}
      - {tool: write, match: "\"path\":\"/(etc|root|var|usr)/"}
      - {tool: edit,  match: "\"path\":\"/(etc|root|var|usr)/"}

Deny wins over allow. Unmatched → deny. Every decision is logged as a structured slog event (tool.execute, tool.denied) and forwarded to the bank's Datadog tenant via a Vector daemonset.

Q4: Where is the source code that a session references stored?

You explain: session state lives on a PVC backed by EBS with encryption at rest. Model context stays within the compressed session (see Compression + Recall). The FTS5 recall index runs on the same PVC. Nothing goes to agentskills.io or any external URL — Skills are loaded from a bind-mounted directory, not a hosted registry.

The auditor asks a follow-up: "What about the model itself?" You explain that Bedrock is the model boundary; anything Bedrock does with prompts is governed by the bank's existing contract with AWS.

What that requires

The manifest

See Guides: Kubernetes deployment for the full manifest. Key deviations for this use case:

  • Namespace pod-security.kubernetes.io/enforce: restricted.
  • IRSA for Bedrock credentials — no long-lived AWS keys in secrets.
  • NetworkPolicy allowing egress to Bedrock regional endpoints and Slack WSS only.
  • Vector daemonset shipping slog output to Datadog with the msg field parsed as a facet.

The config

provider: bedrock

bedrock:
  region: eu-west-1
  model: anthropic.claude-sonnet-4-6-20250101-v1:0
  max_tokens: 4096

log:
  level: info
  format: json

state:
  path: /var/lib/rousseau/sessions.db

agent:
  max_iterations: 32
  compression:
    enabled: true
    trigger_messages: 40
    keep_recent: 6
  approver:
    mode: pattern
    default: deny
    reason: "denied — this deployment does not permit destructive operations without operator confirmation"
    allow: [...as above...]
    deny:  [...as above...]

slack:
  app_token: xapp-<from-Secret>
  bot_token: xoxb-<from-Secret>
  allowlist:
    - U012ABC   # platform team on-call
    - U012DEF   # platform team lead

The audit story

Every tool call is one slog line. Every denial is another. Datadog's monitor on msg:tool.denied alerts the SOC. Weekly, the platform team pulls a report:

# LogQL / Datadog / whichever
sum by (name) (
  count_over_time({job="rousseau-agent"} |= "tool.denied" [1w])
)

The report goes to the compliance drive. Because the slog schema is stable (Observability), the parsing does not break across rousseau upgrades.

What the auditor might not ask but should

  • Reproducible builds. Rousseau's CI includes a reproducible-build job that verifies bit-identical output on fresh checkouts. You can independently rebuild from a tagged source and compare SHA-256.
  • Dependency pinning. go.mod pins exact versions; go.sum is frozen. Dependabot opens updates as reviewable PRs, not silent bumps.
  • govulncheck on every commit. Any known vulnerability that reaches an imported symbol fails CI.
  • CodeQL static analysis on every commit.

All of the above is in Security — the compliance file drawer already exists.

The out-of-tenant boundary

Bedrock is the boundary. Traffic to bedrock-runtime.eu-west-1.amazonaws.com leaves the pod but stays inside AWS. The bank's data-flow diagram shows one arrow from the pod to Bedrock; no other outbound arrows exist for this deployment (Slack Socket Mode is outbound WSS to wss-primary.slack.com, which is documented as a separate allowed egress).

Related pages

Type to search 150+ pages. Ranking: BM25 with title/description boost.