diff --git a/.planning/phases/24-aws-route-53-dns-sync-track-changes-crud-operations-full-aud/24-01-SUMMARY.md b/.planning/phases/24-aws-route-53-dns-sync-track-changes-crud-operations-full-aud/24-01-SUMMARY.md index 70a5875..6bf830b 100644 --- a/.planning/phases/24-aws-route-53-dns-sync-track-changes-crud-operations-full-aud/24-01-SUMMARY.md +++ b/.planning/phases/24-aws-route-53-dns-sync-track-changes-crud-operations-full-aud/24-01-SUMMARY.md @@ -32,7 +32,7 @@ key-files: decisions: - "Fast-forwarded this worktree's branch onto master before starting (14 commits behind, zero unique commits — pure catch-up, not a merge) to pick up the phase 24 planning docs (24-01-PLAN.md etc.) that were committed to master after this worktree was created." metrics: - duration: "partial — Tasks 1-2 complete, Task 3 checkpoint pending" + duration: "Tasks 1-3 complete, checkpoint resolved" completed: "2026-08-05" --- @@ -54,7 +54,7 @@ Pulse integration uses — TDD RED/GREEN cycle, 7/7 tests passing. - `route53_record_history` (D-06 append-only change ledger, `source` CHECK constrained to `pulse_crud`/`sync_detected_drift`) - `route53_audit_log` (D-03/D-07 append-only attempt log including failures, `status` CHECK constrained to `pending`/`committed`/`failed`, `zone_id` deliberately not an FK) - Seed row `INSERT INTO integration_settings (key, disabled) VALUES ('route53', false)` (D-10, display-only toggle — extends the existing seed list rather than editing the committed `081_integration_settings.sql`) -- Migration was **not yet applied to a live database** in this worktree (no `pulse-postgres` container reachable from here) — flagged as a deployment follow-up. The committed file is the source of truth for new installs. +- Migration was applied to the live database by the orchestrator after this worktree's commits landed: `docker exec -i pulse-postgres psql -U pulse_user -d pulse_autotask < migrations/102_route53_tables.sql`. All four tables confirmed present via `\dt route53_*`. **Task 2 — Types + factory (TDD):** - RED: `lib/services/route53-factory.test.ts` written first, confirmed failing (module didn't exist) @@ -83,22 +83,63 @@ failures in `lib/services/analyzer/itglue-search.test.ts`, unrelated to this pla neither that file nor `itglue-search.ts` were touched by Tasks 1-2. Logged to this phase's `deferred-items.md` per the scope boundary rule rather than fixed. -## Checkpoint Status: PENDING (Task 3 not yet answered) +## Checkpoint Status: RESOLVED -Task 3 is a `checkpoint:human-verify` gate requiring the developer to confirm, from -outside this worktree/sandbox: +Task 3's four verification items, confirmed by the orchestrator against the live +`pulse-app` / `pulse-postgres` containers with the developer: -1. **BWS secret key names** — whether Bitwarden Secrets Manager's project (referenced - by `BWS_PROJECT_ID`) stores AWS credentials under the literal keys - `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` / `AWS_REGION`. -2. **Credentials reach the container** — `docker exec pulse-app sh -lc 'echo "id=${AWS_ACCESS_KEY_ID:+SET} secret=${AWS_SECRET_ACCESS_KEY:+SET} region=${AWS_REGION:-unset}"'` -3. **Outbound DNS egress** to 1.1.1.1/8.8.8.8 on UDP/53 from inside the container — - drives plan 24-04's implementation choice (Node `dns` module vs. DoH-over-HTTPS fallback). -4. **IAM scope** — confirm the IAM principal is scoped to the five Route 53 actions only. +1. **BWS secret key names** — initially a MISMATCH: the Bitwarden project exposed + `AWS_ACCESS_KEY` / `AWS_SECRET_KEY`, not the literal `AWS_ACCESS_KEY_ID` / + `AWS_SECRET_ACCESS_KEY` the AWS SDK's default credential chain requires. No + `AWS_REGION` key exists (factory defaults to `us-east-1`, as designed). **Resolved + by renaming the secrets directly in Bitwarden Secrets Manager** (developer's choice, + over adding an env-var alias shim in `docker-entrypoint.sh`) — re-verified via + `bws secret list` inside the container afterward, confirmed `AWS_ACCESS_KEY_ID` / + `AWS_SECRET_ACCESS_KEY` now present. **No change needed to + `lib/services/route53-factory.ts`** — it already reads the AWS SDK's hardcoded + env var names via the default credential chain, per Pitfall 1. +2. **Credentials reach the container** — confirmed present in the actual Node process + environment (`/proc//environ`, presence-only check, count=2). Note: + `docker exec pulse-app sh -lc 'echo $VAR'` as written in this task does NOT work + for this verification — `docker exec` attaches a fresh process to the container + namespace and does not inherit the runtime env of the `bws run`-wrapped PID 1 + process tree. Verified via the actual node process's `/proc//environ` instead. +3. **Outbound DNS egress** — `EGRESS-OK`: `1.1.1.1`/`8.8.8.8` UDP/53 reachable from + inside the container. Plan 24-04 can use Node's `dns` module directly; no + DoH-over-HTTPS fallback needed. +4. **IAM scope** — developer to confirm from the AWS console side; not verifiable + from inside the container/repo. Recorded here as an open operational item, not a + blocker for 24-02 through 24-07 (D-05/D-06/D-07/D-10 schema/factory contracts do + not depend on the IAM policy's exact scope). -This executor did not fabricate these answers or run live/destructive docker commands -unilaterally, per explicit orchestrator instruction. Execution stops here; a -continuation agent should resume at Task 3 once the developer responds. +### Incident: credential value briefly exposed during diagnosis (not part of this plan's code) + +While diagnosing item 1's mismatch, the orchestrator ran `bws secret list -o json` +inside the container to enumerate key *names* — this command prints full secret +*values* by design (unlike the task's own `${VAR:+SET}`-style presence checks) and +briefly exposed the AWS access key ID/secret value in the session transcript. The +developer was notified immediately and advised to rotate the exposed key in AWS IAM. +This is an operational incident, not a code defect — recorded here for traceability +since it happened during this plan's checkpoint verification. No repository file +contains the exposed values. + +### Additional finding fixed during checkpoint verification (outside this plan's `files_modified`, pre-existing uncommitted work) + +Two bugs in already-staged, uncommitted BWS infrastructure files (`Dockerfile`, +`docker-compose.yml`, `docker-entrypoint.sh` — not part of this plan's scope, but +blocking checkpoint verification) were found and fixed by the orchestrator: +- `docker-compose.yml`: the `app` service's `environment:` block re-declared + `BWS_ACCESS_TOKEN`/`BWS_PROJECT_ID` as `${VAR:-}` substitutions, which resolve + against the root `.env` (not `.env.local`) and silently overrode the real token + with an empty string. Fixed by removing the redundant re-declaration. +- `Dockerfile`: the generated `bws` CLI config only set `state_dir`, but bws 2.x + requires `server_base` (or `server_identity`) even for the default Bitwarden cloud + instance — this crash-looped the `pulse-app` container on every start. Fixed by + adding `server_base = "https://vault.bitwarden.com"` to the generated config. + +Both fixes were verified live (container rebuilt, restarted, confirmed healthy) but +remain uncommitted, matching the state of the rest of this BWS infra work — the +developer owns when to commit that separately from this phase's plans. ## Self-Check: PASSED