Files
arah2/.planning/phases/07-hardening-private-launch/07-06-SUMMARY.md
T

14 KiB
Raw Blame History

phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, key-decisions, requirements-completed, duration, completed
phase plan subsystem tags requires provides affects tech-stack key-files key-decisions requirements-completed duration completed
07-hardening-private-launch 06 qa-gates
launch-gate
device-matrix
battery-record
privacy-audit
budget-audit
canary
setmycommands
deferred-debt
phase provides
07-03 scripts/privacy-audit.mjs + scripts/lib/source-gates.mjs — the runtime-hosts gate the /help pointer adjudication extends, and the --live probe contract
phase provides
07-04 scripts/budget-audit.mjs + docs/BUDGETS.md — the KV-list over-ceiling finding and the signature block this gate signs
phase provides
07-05 docs/KNOWN-LIMITATIONS.md + the /help pointer line (en + ms) — the shipped doc the checklist verifies
phase provides
06-DEVICE-GATE.md the never-fake device-gate protocol and the file structure this gate copies
.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)
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)
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
created modified
.planning/phases/07-hardening-private-launch/07-LAUNCH-GATE.md
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)
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
47min 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.