- unsigned protocol file, audit-green restoration, /cari root-cause fix, deploy dd55a073 + full canary verification documented - task 2 (the physical walk + battery run) BLOCKING for the human; task 3 (STATE.md record) orchestrator-owned
167 lines
14 KiB
Markdown
167 lines
14 KiB
Markdown
---
|
||
phase: 07-hardening-private-launch
|
||
plan: 06
|
||
subsystem: qa-gates
|
||
tags: [launch-gate, device-matrix, battery-record, privacy-audit, budget-audit, canary, setmycommands, deferred-debt]
|
||
|
||
# Dependency graph
|
||
requires:
|
||
- phase: 07-03
|
||
provides: scripts/privacy-audit.mjs + scripts/lib/source-gates.mjs — the runtime-hosts gate the /help pointer adjudication extends, and the --live probe contract
|
||
- phase: 07-04
|
||
provides: scripts/budget-audit.mjs + docs/BUDGETS.md — the KV-list over-ceiling finding and the signature block this gate signs
|
||
- phase: 07-05
|
||
provides: docs/KNOWN-LIMITATIONS.md + the /help pointer line (en + ms) — the shipped doc the checklist verifies
|
||
- phase: 06-DEVICE-GATE.md
|
||
provides: the never-fake device-gate protocol and the file structure this gate copies
|
||
provides:
|
||
- ".planning/phases/07-hardening-private-launch/07-LAUNCH-GATE.md — the UNSIGNED launch protocol: Part A (4 clients × 7 interactions, PASS/FAIL/NOT RUN), Part B (11-field Android battery record), Part C (the 12 automated-half commands), Part D (the six D-09 checklist items), executor notes, unsigned FINAL VERDICT"
|
||
- "Audit-green tree restored: npm run privacy-audit exits 0 again (the 07-05 /help pointer adjudicated as a documented doc-pointer static-text class, SA6-pinned)"
|
||
- "The /cari menu defect ROOT-CAUSED and FIXED: register-commands.mjs sent the scope under the wrong Bot API field name (bot_command_scope; the field is scope) — Telegram silently ignored it, every call hit the default scope, the clear calls wiped the default set; all private-chat scopes now read back help, privacy, cari"
|
||
- "Fresh deploy dd55a073 with canaries verified: webhook armed (secret-token channel, no fresh errors), menu button web_app, all six command scopes armed + read-back proven, _headers policy observed live (immutable assets / revalidating HTML)"
|
||
affects: [the human launch gate (Parts A–D are walked and signed), STATE.md milestone completion record (written by the orchestrator AFTER signing), forks (the gate file as onboarding evidence)]
|
||
|
||
# Tech tracking
|
||
tech-stack:
|
||
added: []
|
||
patterns:
|
||
- "Scope adjudications stay NARROW and pinned: a static-text host class consults ONLY bare URL literals — a fetch( target naming the same host still fails (SA6)"
|
||
- "A quoted string is always a fetch TARGET — a URL colon must not masquerade as a TS annotation colon"
|
||
- "canary read-back with the CORRECT API parameter names: setMyCommands ok:true proved nothing about scope until getMyCommands read back per scope"
|
||
- "canary staleness protocol: getWebhookInfo.last_error cannot clear until the next real update — record last_error_date, compare against the deploy timeline"
|
||
|
||
key-files:
|
||
created:
|
||
- .planning/phases/07-hardening-private-launch/07-LAUNCH-GATE.md
|
||
modified:
|
||
- scripts/lib/source-gates.mjs
|
||
- scripts/test/privacy-audit.test.mjs
|
||
- docs/PRIVACY-AUDIT.md
|
||
- docs/KNOWN-LIMITATIONS.md
|
||
- bot/scripts/register-commands.mjs
|
||
- bot/README.md
|
||
- bot/src/bot/commands/start.ts
|
||
- web/src/shell.css
|
||
- README.md, AGENTS.md, 4 mockup screens (logo residue)
|
||
|
||
key-decisions:
|
||
- "The /help pointer host (gitmirah) is adjudicated as a SOURCE-side doc-pointer static-text class following the audit's own laws — the URL stays the repo's actual published remote (07-05's decision); the class is narrow (URL literals only) and SA6-pinned; forks replace it with their own origin"
|
||
- "The KV-list over-ceiling (1,440/day vs 1,000/day) is NOT auto-fixed: it is a designed product-timing decision (the due-card math couples tick and cadence) carried to the human gate with the documented options — a 90 s tick is NOT expressible in cron (minimum granularity 60 s)"
|
||
- "The kv-expiry --live leg stays NOT RUN: it needs CLOUDFLARE_API_TOKEN + CLOUDFLARE_ACCOUNT_ID which the executor's environment does not carry — an auth gate surfaced to the maintainer, never faked; a manual wrangler corroboration (namespace lists []) IS recorded"
|
||
|
||
requirements-completed: [] # PX-04 completes at the SIGNED gate (task 2); the orchestrator marks requirements
|
||
|
||
# Metrics
|
||
duration: 47min
|
||
completed: 2026-10-25
|
||
---
|
||
|
||
# Phase 7 Plan 06: Launch Gate (automated prep) Summary
|
||
|
||
**The unsigned launch-gate protocol written (4×7 device matrix, 11-field battery record, 12-command automated half, the six D-09 checklist items), the audit-green state restored (the 07-05 `/help` pointer adjudicated lawfully), the `/cari` menu defect root-caused to a wrong Bot API field name and FIXED, and the fresh deploy verified by the full canary protocol.**
|
||
|
||
## Performance
|
||
|
||
- **Duration:** 47 min (21:15Z → 22:02Z)
|
||
- **Started:** 2026-10-24T21:15:21Z
|
||
- **Automated prep completed:** 2026-10-24T22:02Z
|
||
- **Tasks:** 1/3 executed (task 2 = THE BLOCKING HUMAN GATE; task 3 = orchestrator-owned, deferred per the spawn objective)
|
||
- **Files modified:** 15 (1 created, 14 modified/landed)
|
||
|
||
## Accomplishments
|
||
|
||
- **07-LAUNCH-GATE.md** exists as a complete, unsigned protocol: Part A — the ONE consolidated walk (D-05): Android + iOS + Telegram Desktop + plain browser × (boot · search→route · guidance · minimize/resume · trip-end · theme flip · landscape/fullscreen), ⬜ cells, the PASS/FAIL/NOT RUN vocabulary defined in the file's own voice, and per-interaction observable pass conditions; Part B — the 11-field Android battery record with the no-extrapolation rule; Part C — the 12 exact automated-half commands with ⬜ result cells and the "a NOT-RUN --live probe is NOT a pass" note; Part D — the six D-09 checklist items, each naming its evidence; executor notes carrying every known-open item; an unsigned dated FINAL VERDICT block
|
||
- **Audit-green restored:** the deferred-items #1 RED (07-05's `http://gitmirah:3000` /help pointer, 2 runtime-hosts violations) fixed per the gates' OWN laws — a documented `DOC_POINTER_STATIC_TEXT_HOSTS` class on the source-side runtime-hosts gate, NARROW (URL literals only) and pinned by the new SA6 vector; `npm run privacy-audit` → **PRIVACY AUDIT CLEAN — 5 gate(s) passed, 0 violations**, suite 13/13
|
||
- **Rule 1 bonus (found by SA6's RED):** the fetch( call-site handler's declaration heuristic misclassified any quoted absolute URL as a TS method declaration — quoted fetch targets now reach the host check
|
||
- **The /cari menu defect's true root cause found and FIXED at the canary:** the Bot API parameter is `scope` (verified against core.telegram.org/bots/api); the script's `bot_command_scope` was silently ignored so every call hit the default scope and the two "clear" calls wiped the default set entirely. Registration re-run; `getMyCommands` read back per scope with the correct param: default (agnostic/en/ms) + all_private_chats (agnostic/ms) all list `help, privacy, cari`; group scopes verified cleared. The limitations doc's wrong attribution corrected; residual client menu-caching caveat + workaround kept
|
||
- **Fresh deploy `dd55a073` + full canary protocol verified:** webhook armed with the secret-token channel (`last_error` stale from the phase-3 era, `last_error_date` 2026-10-22T11:18Z recorded, pending 0), menu button `web_app` → deployed origin, all command scopes armed, secrets in gitignored `.dev.vars` only; the live asset-headers leg **PASS** (immutable `/assets/*`, revalidating HTML — 07-04's `_headers` policy observed on the shipped origin)
|
||
- **Part C green at prep time:** bot 126/126, web 165/165, routing 65/65, search 57/57, both corpora PASS, ladder p95 74.055 ms (documented c3 band), privacy-audit CLEAN, budget-audit CLEAN, captures 22/22
|
||
|
||
## task Commits
|
||
|
||
Each unit committed atomically:
|
||
|
||
1. **fold 07-03 residue (status-first header probe, XHTML namespace, evidence-reason contract)** — `7a1206d` (fix)
|
||
2. **RED — SA6 doc-pointer vector** — `b06c64d` (test)
|
||
3. **GREEN — the doc-pointer static-text class + PRIVACY-AUDIT.md adjudication + dated addendum** — `2489cca` (fix)
|
||
4. **logo-asset replacement residue (quick task 261024-001, commit recorded TBD in STATE)** — `b7576c1` (chore)
|
||
5. **landscape cockpit geometry refinement (07-02 device-walk feedback) + re-run captures** — `71fff10` (fix)
|
||
6. **/cari root-cause fix + limitations-doc correction + README row** — `141d6d2` (fix)
|
||
7. **the launch gate protocol file** — `53930eb` (docs)
|
||
|
||
## Files Created/Modified
|
||
|
||
- `.planning/phases/07-hardening-private-launch/07-LAUNCH-GATE.md` — NEW: the unsigned protocol
|
||
- `scripts/lib/source-gates.mjs` — DOC_POINTER_STATIC_TEXT_HOSTS + the fetch-handler fix
|
||
- `scripts/test/privacy-audit.test.mjs` — the SA6 vector (plus the folded CP2/AU1 contract updates)
|
||
- `docs/PRIVACY-AUDIT.md` — the adjudication + dated gate-prep re-run addendum
|
||
- `docs/KNOWN-LIMITATIONS.md` — the /cari section corrected to the real root cause
|
||
- `bot/scripts/register-commands.mjs` — `scope` field name + the fix documented at the site
|
||
- `bot/README.md`, `README.md`, `AGENTS.md`, 4 mockup screens, `bot/src/bot/commands/start.ts`, `web/src/shell.css`, 6 captures — residue landed
|
||
|
||
## Decisions Made
|
||
|
||
- **Adjudicate, don't weaken:** the pointer URL keeps its host (07-05's documented decision — the repo's actual remote); the AUDIT gains a documented, narrow static-text class. A protocol-relative or host-neutral rewrite would have gamed the scanner while leaving drivers a dead link.
|
||
- **The KV-list cadence stays a user decision:** 07-04 classified the retiming as Rule 4 (the due-card math couples `SCAN_TICK_S` into `projectTurnCards`' due rule); this prep carries the three documented options into the gate file and the checkpoint, plus the correction that a 90 s tick is not cron-expressible.
|
||
- **The kv-expiry live leg is an auth gate, not a skip-failure:** absent CF credentials degrade to exit 2 by design; the manual wrangler listing (`[]`) corroborates the namespace's live state and is recorded in the gate file.
|
||
|
||
## Deviations from Plan
|
||
|
||
### Auto-fixed Issues
|
||
|
||
**1. [Rule 1 - Bug] The fetch( call-site handler misclassified quoted absolute URLs as TS declarations**
|
||
- **Found during:** SA6's RED phase
|
||
- **Issue:** `argText.includes(":")` treats any quoted URL's colon as a TS annotation colon, skipping quoted absolute fetch targets entirely — the doc-pointer class could not be narrow
|
||
- **Fix:** quoted strings are targets; only unquoted colon-carrying args are declarations
|
||
- **Files modified:** scripts/lib/source-gates.mjs
|
||
- **Commit:** 2489cca
|
||
|
||
**2. [Rule 1 - Bug] register-commands.mjs sent the wrong Bot API field name (the /cari menu defect's true root cause)**
|
||
- **Found during:** the deploy canary (default-scope read-back was empty, all_private_chats lacked cari)
|
||
- **Issue:** `bot_command_scope` is not a Bot API field; Telegram silently ignores it — all four registration calls hit the default scope and the two clear calls cleared the default set
|
||
- **Fix:** field renamed to `scope` in all six calls; registration re-run; per-scope read-back proven with `getMyCommands` + the correct param; docs corrected
|
||
- **Files modified:** bot/scripts/register-commands.mjs, docs/KNOWN-LIMITATIONS.md, bot/README.md
|
||
- **Commit:** 141d6d2
|
||
|
||
**3. [Rule 3 - Blocking residue] Pre-existing uncommitted work landed (07-04's residue caution + the logo quick task's TBD commit)**
|
||
- **Found during:** tree prep before deploy
|
||
- **Issue:** the 07-03 follow-up fixes were described in 07-03-SUMMARY but absent from its commits; the logo replacement was complete but uncommitted (and web/public assets were untracked while start.ts referenced them)
|
||
- **Fix:** landed as three commits (`7a1206d`, `b7576c1`, `71fff10`) after re-verifying the baselines (bot 126/126, web 165/165, captures 22/22)
|
||
- **Files modified:** scripts/lib/cloudflare-probes.mjs + source-gates.mjs + test; logo residue set; shell.css + captures
|
||
|
||
---
|
||
|
||
**Total deviations:** 3 auto-fixed (2 bugs, 1 residue landing)
|
||
**Impact on plan:** the audit-green state is restored and the launch canaries are genuinely armed; no plan surface was dropped. Task 2 (the physical walk + battery run) and task 3 (STATE.md record) remain.
|
||
|
||
## Issues Encountered
|
||
|
||
- No Cloudflare API token in the executor's environment (`bot/.dev.vars` carries only BOT_TOKEN/WEBHOOK_SECRET/WEBHOOK_URL) — the kv-expiry live leg stays NOT RUN (exit 2, honest class); exact token-creation steps surfaced at the checkpoint
|
||
- The stale phase-2/3-era Telegram command sets (all_chat_administrators: `start`; all_private_chats: `help, privacy` without cari) are now genuinely cleared/overwritten by the fixed registration
|
||
- `npm run capture` needs a >120 s window (Playwright legs) — completed with an extended timeout
|
||
|
||
## Known Stubs
|
||
|
||
None — the gate file is a protocol by design (every verdict cell starts ⬜ per T-07-27); no product code carries placeholder data.
|
||
|
||
## User Setup Required
|
||
|
||
**One auth gate (kv-expiry live leg):** create a Cloudflare API token (Account scope: Workers KV Storage → Read) and export `CLOUDFLARE_API_TOKEN` + `CLOUDFLARE_ACCOUNT_ID`, then re-run `npm run privacy-audit -- --live` and `npm run budget-audit -- --live` at gate time.
|
||
|
||
## Next Phase Readiness
|
||
|
||
- **The gate file is ready to walk:** Part 0 (the automated half — every command exits 0 at prep time, re-run at gate time), Part A (the physical walk — the user's legs), Part B (the battery run — the user's legs), Part D (the signature)
|
||
- **Two decisions ride with the signature:** the KV-list cadence (options in the gate file) and the kv-expiry credential provision
|
||
- Baselines: bot 126/126, web 165/165, routing 65/65, search 57/57, privacy suite 13/13, budget suite 19/19, captures 22/22; deploy `dd55a073`
|
||
|
||
---
|
||
*Phase: 07-hardening-private-launch*
|
||
*Completed: 2026-10-25*
|
||
|
||
## Self-Check: PASSED
|
||
|
||
- `07-LAUNCH-GATE.md` on disk with all six section headings; 32 ⬜ lines; no APPROVED string.
|
||
- All 7 commits verified in git log (`7a1206d`, `b06c64d`, `2489cca`, `b7576c1`, `71fff10`, `141d6d2`, `53930eb`).
|
||
- Final suite: bot 126/126, web 165/165, routing 65/65, search 57/57; privacy-audit CLEAN; budget-audit CLEAN.
|
||
- STATE.md and ROADMAP.md untouched (orchestrator-owned, per the spawn objective).
|