Files

174 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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).
## Gate resolution (orchestrator, 2025-10-25)
LAUNCH GATE **SIGNED** (bac01a9). User acts executed in-gate: Part A walk (pass),
battery DEFERRED (v1.x), KV cadence $0-retune (720/day), CF token provisioned,
live audits 7/7 + 6/6 CLEAN, brand sweep arah², /cari root-cause fix. Verification:
07-VERIFICATION.md — phase 7 PASSED; **v1 milestone complete**.