Skip to content

Commit 92355a8

Browse files
committed
docs: consolidate cloud setup; trim stage7 + operator-runbook
The Stage 6 AWS runbook and the AWS-side half of the Stage 7 doc re-tangled themselves over time — every cross-link was "see also" rather than "the source is here". Operators ended up reading both, then the operator runbook, then both again to figure out which command to run. Restructure into three focused docs, all referenced by stage: • docs/cloud-setup.md (NEW, 548 lines) — every cloud-account resource in one file, split internally by concern (identities → DNS → inbound mail → IAM → OIDC federation → EC2 host → cleanup). Stage 6 vs Stage 7 vs federated-deployment is a *mode* of the same machinery, not three separate runbooks. Tencent Cloud SimpleDM + COS slots in at §2.2 with a 1:1 IAM→CAM mapping table — no new file when we add it. • docs/stage7-wip.md (-469 lines) — Phase 1 / Phase 2 bookkeeping dropped; Stage 7 is just "the broker that issues OIDC JWTs and AWS creds". AWS commands no longer embedded inline; the doc points at cloud-setup.md for provisioning. Smoke test now shows how to mint a session bearer end-to-end (the previous version left SESSION=<bearer-from-the-backend> as a dangling placeholder). • docs/operator-runbook.md (-86 lines) — concise. WIP/scratchpad header gone; Phase 1/Phase 2 framing gone; threat-model section points at the spec doc instead of duplicating it; rotation paths fold into one §5 table. • docs/stage6-aws-setup.md deleted; all referrers (dev-setup, stage8-wip, ses-email-architecture, development-stages, setup-dev-env.sh, setup-broker-host.sh) point at cloud-setup.md. Net: 813 insertions, 1264 deletions across 10 files. Stage 7 gate still passes (STAGE 7 phase 1 + phase 2 PASSED).
1 parent 44a41e5 commit 92355a8

10 files changed

Lines changed: 813 additions & 1264 deletions

docs/cloud-setup.md

Lines changed: 548 additions & 0 deletions
Large diffs are not rendered by default.

docs/dev-setup.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -137,15 +137,15 @@ You operate the AgentKeys infrastructure for a team. You hold the long-lived `ag
137137

138138
### 5.1 One-time: AWS setup
139139

140-
Run through [`stage6-aws-setup.md`](./stage6-aws-setup.md) through §7 once per AWS account. Afterwards you'll have:
140+
Run through [`cloud-setup.md`](./cloud-setup.md) §1–§3 once per AWS account. Afterwards you'll have:
141141

142142
- SES domain identity verified on `bots.litentry.org` (or your substitute via `AGENTKEYS_EMAIL_DOMAIN`)
143143
- `agentkeys-daemon` IAM user with `sts:AssumeRole` only
144144
- `agentkeys-data-role` role with SES + S3 permissions
145145
- S3 bucket `agentkeys-mail-<ACCOUNT_ID>` with receipt rule writing inbound to `inbound/`
146146
- Route 53 records: three DKIM CNAMEs, MX, SPF, DMARC
147147

148-
Manage the daemon user's long-lived AWS keys via a **named profile** in `~/.aws/credentials` (mode 0600). The broker uses the AWS SDK's default credential chain — `AWS_PROFILE` (set by `awsp` or your shell), the shared credentials file, or an EC2 instance profile via IMDS. **No long-lived AWS keys live in env vars.** See [`operator-runbook.md` §3.1](./operator-runbook.md) for the full credential story.
148+
Manage the daemon user's long-lived AWS keys via a **named profile** in `~/.aws/credentials` (mode 0600). The broker uses the AWS SDK's default credential chain — `AWS_PROFILE` (set by `awsp` or your shell), the shared credentials file, or an EC2 instance profile via IMDS. **No long-lived AWS keys live in env vars.** See [`operator-runbook.md` §2](./operator-runbook.md#2-aws-credentials) for the full credential story.
149149

150150
### 5.2 Run the broker server
151151

@@ -242,7 +242,7 @@ The stage-done script is the authoritative evaluator — never self-grade. If it
242242
| Mock server won't bind port 8090 | Stale process | `lsof -i :8090`, kill, restart |
243243
| Broker won't bind port 8091 | Stale process | `lsof -i :8091`, kill, restart |
244244
| `agentkeys init` double-prompts on macOS | Known keyring-rs update path | Filed under Stage 9 "idempotent init" item |
245-
| `bot-<ts>@bots.litentry.org` email never arrives | DNS / MX / SES receipt-rule misconfigured, or bucket missing write perm | `aws s3 ls s3://$BUCKET/inbound/ --recursive` — if empty >60s after signup, re-verify §2–§5 of `stage6-aws-setup.md` |
245+
| `bot-<ts>@bots.litentry.org` email never arrives | DNS / MX / SES receipt-rule misconfigured, or bucket missing write perm | `aws s3 ls s3://$BUCKET/inbound/ --recursive` — if empty >60s after signup, re-verify [`cloud-setup.md` §1–§2](./cloud-setup.md#1-domain--dns) |
246246
| `MalformedPolicyDocument: ... failed legacy parsing` during operator setup | Heredoc-generated JSON lost a `$VAR:r` / `$VAR:h` to a zsh modifier | Use the `jq -n --arg … '{…}'` pattern — never heredoc JSON into AWS calls |
247247

248248
## 9. When a provider changes their flow
@@ -254,8 +254,8 @@ The longer-term plan (Stage 5b) is to detect drift automatically from telemetry
254254
## 10. Further reading
255255

256256
- [`spec/plans/development-stages.md`](./spec/plans/development-stages.md) — Shipped / Active / Planned roadmap
257-
- [`stage6-aws-setup.md`](./stage6-aws-setup.md) — one-time AWS infra (operator role)
258-
- [`stage7-wip.md`](./stage7-wip.md) — broker server + OIDC-federated future
257+
- [`cloud-setup.md`](./cloud-setup.md) — one-time AWS infra (DNS, SES, S3, IAM, OIDC federation)
258+
- [`stage7-wip.md`](./stage7-wip.md) — broker server design + acceptance test
259259
- [`operator-runbook.md`](./operator-runbook.md) — start, supervise, rotate, monitor the broker
260260
- [`spec/credential-backend-interface.md`](./spec/credential-backend-interface.md) — 15-method trait contract
261261
- [`spec/ses-email-architecture.md`](./spec/ses-email-architecture.md) — Stage 6 email pipeline deep-dive

docs/operator-runbook.md

Lines changed: 105 additions & 165 deletions
Large diffs are not rendered by default.

docs/spec/plans/development-stages.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ If you're looking for setup / demo instructions, go to [`../../dev-setup.md`](..
2121
| 5a | Provisioner (deterministic) | OpenRouter + OpenAI CDP scrapers; `signupEmailOtp` pattern library; HTML-strip + label-aware OTP extractor; mandatory post-provision verify; `agentkeys provision openrouter` | 59/59 unit + live provision |
2222
| 6 (interim, 2026-04) | Hosted email infra | SES domain verification on `bots.litentry.org`; `agentkeys-daemon` IAM user → `agentkeys-data-role` assume-role; S3 inbound bucket; `ses-s3` email backend; end-to-end demo from signup → SES receipt → S3 poll → key extraction | `scripts/stage6-demo-run.sh` prints a valid `sk-or-v1-...` key |
2323
| 7 phase 1 (2026-04) | Broker server | `agentkeys-broker-server` axum service: bearer-gated `POST /v1/mint-aws-creds`, audit SQLite, supervisor probes; daemon `--broker-url` flag wired up | 22/22 unit + integration |
24-
| 7 phase 2 (2026-04) | OIDC issuer + AWS-cred wiring | OIDC discovery + JWKS + bearer-gated `POST /v1/mint-oidc-jwt` absorbed into Rust broker (TS `services/oidc-stub/` retired); CLI/MCP `provision` paths fetch AWS temp creds via the broker when `--broker-url` is set; audit destination is the broker's local SQLite per the pluggable-audit-backend framing in [`architecture.md` §11](../architecture.md) | broker integration + clippy clean; cloud federation deployment runbook in [`stage7-wip.md`](../../stage7-wip.md) |
24+
| 7 phase 2 (2026-04) | OIDC issuer + AWS-cred wiring | OIDC discovery + JWKS + bearer-gated `POST /v1/mint-oidc-jwt` absorbed into Rust broker (TS `services/oidc-stub/` retired); CLI/MCP `provision` paths fetch AWS temp creds via the broker when `--broker-url` is set; audit destination is the broker's local SQLite per the pluggable-audit-backend framing in [`architecture.md` §11](../architecture.md) | broker integration + clippy clean; cloud federation deployment runbook in [`cloud-setup.md` §4](../../cloud-setup.md) |
2525

2626
### Non-stage work shipped alongside
2727

@@ -67,7 +67,7 @@ Both phases shipped — see Shipped table above. Scratch notes: [`../../stage7-w
6767

6868
**Operational follow-ups (not architectural blockers):**
6969

70-
- Public TLS hosting of `$BROKER_OIDC_ISSUER` so `aws iam create-open-id-connect-provider` can fetch the JWKS. Per-operator deployment task; recipe in [`stage7-wip.md` §"Cloud federation deployment"](../../stage7-wip.md).
70+
- Public TLS hosting of `$BROKER_OIDC_ISSUER` so `aws iam create-open-id-connect-provider` can fetch the JWKS. Per-operator deployment task; recipe in [`cloud-setup.md` §4 "OIDC federation"](../../cloud-setup.md).
7171
- Higher-assurance signer (TEE-derived ES256 at `oidc/issuer/v1`, blocked on `heima-gaps §3`). The on-disk keypair shipped today is a complete v0.1 signer — TEE is hardening, not a Stage-7 prerequisite.
7272
- Audit-destination swap (chain anchoring or sealed log service). The broker's local SQLite is one valid choice in the [pluggable audit-backend layer](../architecture.md#11-audit-destination-is-pluggable) — operators can swap per their threat model and jurisdiction.
7373

docs/spec/ses-email-architecture.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,13 +194,13 @@ The split exists so the long-lived secret (user access key) only does ONE thing
194194
| Auth flow | `sts:AssumeRole` from IAM user (static keys) | `sts:AssumeRoleWithWebIdentity` from OIDC JWT |
195195
| AWS resource count | Same singletons | Same singletons (no new IAM per user) |
196196
| Failure mode if app has a bug | User A could read user B's mail | AccessDenied from cloud — bug caught at the boundary |
197-
| Where to read more | This spec + [`docs/stage6-aws-setup.md`](../stage6-aws-setup.md) | [`docs/stage7-wip.md`](../stage7-wip.md), §10.4 PrincipalTag pattern below |
197+
| Where to read more | This spec + [`docs/cloud-setup.md`](../cloud-setup.md) | [`docs/cloud-setup.md` §4](../cloud-setup.md#4-oidc-federation-stage-7) + §10.4 PrincipalTag pattern below |
198198

199199
The migration from Stage 6 to Stage 7 is mostly a trust-policy rewrite + a `Resource`/`Condition` swap on the bucket policy (see §10.4). No new IAM resources, no per-user provisioning. Singleton stays singleton.
200200

201201
### What this spec does NOT cover (intentionally)
202202

203-
- **Operator setup specifics** (account ID, hosted zone ID, exact ARNs) live in [`docs/stage6-aws-setup.md`](../stage6-aws-setup.md), the operator-facing runbook. Reference that for the actual AWS CLI calls.
203+
- **Operator setup specifics** (account ID, hosted zone ID, exact ARNs) live in [`docs/cloud-setup.md`](../cloud-setup.md), the operator-facing runbook. Reference that for the actual AWS CLI calls.
204204
- **PrincipalTag enforcement details** are in §10.4 below + [`wiki/tag-based-access.md`](../../wiki/tag-based-access.md).
205205
- **OIDC issuer key derivation + JWKS** are in §10.5 + [`wiki/oidc-federation.md`](../../wiki/oidc-federation.md).
206206

0 commit comments

Comments
 (0)