The story
You are a platform engineer at a mid-sized bank. Compliance says any coding assistant your engineers use must:
- Run inside the bank's AWS accounts, not on a SaaS control plane.
- Route model traffic through a provider the bank has a contract and an audit trail with (Bedrock).
- Have a documented supply-chain posture (SLSA-3, SBOM, signature verification).
- Enforce approval policies with a machine-readable audit trail.
- 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
msgfield 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-buildjob that verifies bit-identical output on fresh checkouts. You can independently rebuild from a tagged source and compare SHA-256. - Dependency pinning.
go.modpins exact versions;go.sumis frozen. Dependabot opens updates as reviewable PRs, not silent bumps. govulncheckon 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
- Guides: Kubernetes deployment — the manifests.
- Guides: Audit + Approval Policies — the compliance story.
- Guides: Observability — the slog pipeline.
- Bedrock provider — credential chain and region behaviour.
- Security — trust model and supply-chain controls.