diff --git a/ROADMAP.md b/ROADMAP.md index 1902794..481d963 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -7,9 +7,9 @@ > Update the **Current step** line and the item status every time something moves. > Add new findings at the bottom of the relevant block rather than rewriting history. -**Current step:** Block 0 closed, plus 2.1, 2.2 and 5.1 (2026-09-18). Next: 2.3 -(Docker secret `*_FILE` loading), then 2.4/2.5 (the release gate and its decayed -preflight). Block 1 still waits on client inputs for 1.1/1.2. +**Current step:** Block 0 closed, plus 2.1, 2.2, 2.3, 2.5 and 5.1. Next: 2.4 (the +release gate the docs describe but the workflow never ran — partly addressed by +5.1), then 2.6/2.7. Block 1 still waits on client inputs for 1.1/1.2. **Last audit:** 2026-09-18, full read of `local/`, `dtf-site.html`, `deploy/`, `.gitea/`, docs and legacy prototypes. Findings below carry their audit IDs. @@ -190,7 +190,7 @@ record has no attacker IP. on the environment name: 120 new visitors per 15 minutes **site-wide** (~8/min). Normal traffic 429s. Key per source IP (after 2.1) and raise the ceiling. -### `[ ]` 2.3 — `deploy/stack.yaml` cannot boot `(F7)` +### `[x]` 2.3 — `deploy/stack.yaml` cannot boot `(F7)` It passes `DATABASE_URL_FILE`, `AWS_ACCESS_KEY_ID_FILE`, `OPERATOR_PASSWORD_FILE`, `OPERATOR_USER`. The code reads `DATABASE_URL`, `AWS_ACCESS_KEY_ID`, @@ -212,7 +212,7 @@ unit tests, then builds, pushes `latest` and calls the webhook **unconditionally - Either implement the gate or correct both documents. Do not leave the gap. -### `[ ]` 2.5 — The preflight has silently decayed `(F9)` +### `[x]` 2.5 — The preflight has silently decayed `(F9)` It blocks by string-matching source. **4 of 6 markers are dead** after the R2 refactor: `'This runtime only supports APP_ENV=local'`, @@ -413,6 +413,22 @@ charges. Fix as part of 1.1. `customer_login_failed`, `cross_origin_rejected`, `http_security_event`). - `[x]` CI runs the integration suites against a real stack before publishing. +### 2026-09-21 + +- `[x]` 2.3 — `local/secrets.py` resolves every `_FILE` into `` from the + API, worker and bootstrap entrypoints, failing closed on an unreadable or empty + secret and on a value supplied both ways. Verified by booting the API, the worker + and bootstrap with credentials supplied only as mounted files, including a + password containing `:/?#[]&=+$ ,%`. `OPERATOR_USER` in the stack became + `OPERATOR_EMAIL`, which is what the runtime reads. +- `[x]` 2.5 — The gate now loads `local/secrets.py` and makes it resolve every + secret `deploy/stack.yaml` declares, plus asserts it fails closed. Verified + against a no-op loader (11 blockers) and one that swallows a missing file + (1 blocker); only the real implementation passes. The four marker strings that + stopped matching when R2 support landed were removed; the two describing real + blockers stay, so the gate still refuses a release while the payment and + messaging adapters are fake. + ### Reporting - `[x]` Week-1 client report (`Relatorio-Semana-1-DTF.docx`), corrected 2026-09-18 to