Continuum is a hackathon technology demonstration. All incident, alert, and remediation data is synthetic (ADR 005) — there is no real production system, customer data, or PII in this repository at any point, including in seed data, code comments, test fixtures, and captured evidence.
| Version | Supported |
|---|---|
main / latest release |
Yes — fixes land here |
| Older tags | No — pinned snapshots for judging reproducibility |
-
.envis gitignored; only.env.example(placeholder values) is committed. -
CockroachDB and AWS credentials are never hardcoded — loaded via environment variables only (
config.py).config.Settingsdeliberately tolerates unknown env vars (extra="ignore") so it coexists with the AWS SDK reading its own credentials from the environment. -
Deployment secrets live in the platform, not the repo:
COCKROACH_DATABASE_URLandCOCKROACH_MCP_API_KEYas Hugging Face Space repository secrets; SAM parameters (NoEcho: true) for the Lambda. -
The CI deploy holds two GitHub repository secrets (ADR 010):
AWS_DEPLOY_ROLE_ARNandCOCKROACH_DATABASE_URL. The second is a live cluster credential in a third party, on a public repository, and is stated here rather than left to be discovered. Repository secrets are encrypted and are never exposed to workflows triggered by forked pull requests, anddeploy.ymlruns only on tags, which only a maintainer can push. The cluster holds synthetic data only (ADR 005), so the credential is not a route to anything real. The honest alternative — resolving the DSN from an AWS-side secret store at runtime — is the right move if that ever stops being true. -
No long-lived AWS keys exist in GitHub. The deploy workflow assumes an IAM role through GitHub's OIDC provider, so credentials are minted per run and expire with it. The role's trust policy is scoped to this repository and to
refs/tags/*, so a branch push cannot assume it even if a future workflow tries. Its permissions are broader than ideal — SAM creates the function's execution role as part of the stack, soiam:*is currently attached; narrowing it to this stack's role paths is recorded as outstanding in ADR 010 rather than glossed over. -
CI runs on deliberately fake credentials — every outbound call in the unit suite is mocked at the import boundary, so a real key is never needed to make the suite pass.
-
Nor into a screenshot. Judge-facing evidence is full-window console captures, which carry browser chrome: the signed-in user's profile photograph, and on AWS pages the account id — in the top-right tooltip and inside any ARN the page prints. Neither is a credential, but a face is a real person and an account id is barred from submission material, so masking is declared as data in
scripts/redact_evidence.pywith a reason per region rather than done by hand and forgotten.make redact-evidence --checkfails on an unmasked declared region and on a screenshot with no declaration at all, so a new capture cannot ship because nobody looked at it. It must never touch a metric, timestamp, identifier or query text the surrounding prose cites — masking a number to make it agree with a document would turn evidence into decoration. -
Secrets must not reach a terminal either. Gitignoring
.envand keeping the DSN out ofsamconfig.tomlstops a credential reaching the repository; neither stops one reaching stdout, where it lands in scrollback and in any transcript later shared for help. The realistic failure is not printing a password deliberately but running a broad read of a store that contains one —aws lambda get-function-configuration --query "Environment.Variables"returns this function's whole environment, including the live database URL. Query the single field instead. The rule and its worked examples are inCLAUDE.mdunder Non-negotiable constraints, so agents working in this repo inherit it. -
The rule exists because the failure happened. On 2026-08-08 exactly that broad read printed the live CockroachDB DSN, password included, to a terminal. Nothing reached the repository. The SQL credential was rotated the same day across every consumer — the local
.env, the Hugging Face Space secret, the GitHub Actions secret, the machine-scope environment variable the deploy shell reads, and the deployed function's SAM parameter — and connectivity was re-verified against the cluster afterwards. Recorded here rather than quietly fixed: a rotation nobody can find the record of is indistinguishable from a rotation that never happened. -
The
.mcp.jsonMCP server config uses${COCKROACH_MCP_API_KEY}environment expansion, so no secret is committed even though the config is.
- The Managed MCP Server is used in read-only mode (ADR 003). No write-capable MCP credentials are used or stored.
agents/memory_agent.pyis the only module permitted to write incident or remediation state. A single write path is a security property as much as an architectural one — the blast radius of a bug in any other agent is bounded to reads.- The IAM credentials the application runs with are scoped to Bedrock model invocation only. They cannot list, create, or delete AWS resources; administrative work uses a separate profile.
- Cost guardrails are in place with a hard IAM deny-all action at the budget ceiling — see
submission/COSTS.md.
Database connections use sslmode=require, which encrypts without needing a CA file and works
unconditionally in Lambda's execution environment. This is an accepted trade-off for synthetic data
(ADR 005). sslmode=verify-full&sslrootcert=system is not a working substitute here — libpq's
system CA store is empty or unresolved on many platforms and fails with certificate verify failed. For real certificate verification, ship the cluster CA file and point &sslrootcert= at it.
Please open a private security advisory on GitHub rather than a public issue: Security → Advisories → Report a vulnerability.
This is a solo hackathon project without a dedicated security team — response is best-effort, but credential exposure or an injection vector in the demo API will be treated as urgent.
Please include: what you found, how to reproduce it, and the commit or release tag you observed it on.
Known limitations (by design — ADR 006)
These are deliberate scope decisions for a demonstration project, documented rather than hidden:
- No authentication on the demo API.
api/main.pyis intended for local and demo use, not hardened for public production traffic. It is not internet-exposed by the reference deployment. - No custom RBAC layer beyond the MCP Server's default read-only posture.
- No rate limiting on
POST /api/v1/alert. Load characterisation deliberately exercises the read path only — seetests/load/k6_smoke.js. - No audit trail of who triggered an incident — the system records what happened, not who asked for it. Real deployment would need actor attribution on every state transition.
- Prompt injection is not defended against. Alert text flows into the reasoning prompt
(
prompts/remediation_agent.txt). Since alerts are synthetic and operator-authored here, this is out of scope — but ingesting untrusted alert sources would make it a live concern, and the proposed action is not sandboxed before being recorded.