Lumen/SPIKE-05-OFFLINE-READY.md
Lumen Stage1 c0bfd413ff Stage 1: project foundation (strict TS, lint boundaries B-1..B-7, directory structure, CI, boundary tests)
- dedicated git repo at /home/avi/Projects/Lumen (main)
- TypeScript strict (target ES2022, bundler, exactOptionalPropertyTypes, noUncheckedIndexedAccess)
- ESLint 9 + typescript-eslint strictTypeChecked + eslint-plugin-boundaries for B-1..B-7, no-restricted-globals/syntax for B-1/B-7
- Prettier 3.5
- Structure per IMPLEMENTATION-CONTRACT.md §4 (src/platform/idb|cache|sw, storage, data, sync/{transport,verifier}, domain/{emergency,schedule,map,festival,readiness,clock,favorites}, ui/{components,views,router,render}, app, emergency-baseline, assets, public, content, pipeline, tests, scripts)
- CI: .github/workflows/ci.yml (typecheck + lint + format + test)
- Boundary tests: tests/unit/boundaries.test.ts (4 tests) + scripts/check-boundaries.ts
- No feature code, no PWA/IDB/sync/mesh/accounts per contract Stage 1
2026-08-30 23:25:35 -05:00

7.1 KiB
Raw Permalink Blame History

SPIKE-05 — Offline Ready Model

  • Phase: Architecture Validation
  • Date: 2026-08-30
  • Decision under test: the readiness state machine in ARCH §12 (R1–R7).
  • Outcome: model confirmed; predicate formalized, tightened (time independence, optional sections), and failure-state taxonomy completed.

1. What READY must actually guarantee

Deriving from the product promise ("everything attendees need works with zero connectivity"), READY must guarantee, from local evidence only:

  1. The app can launch and render without network (shell complete).
  2. Emergency information is available (floor always; dataset section if present).
  3. The schedule is browsable and Now/Next computable (schedule section present; note: computable even with a wrong clock — a clock problem is a warning, never a readiness failure).
  4. The map is usable (map section + its required assets present).
  5. Festival info is readable (info section present).
  6. The dataset is authentic and untampered (signature + hashes verified).
  7. The dataset is compatible with this shell (schema envelope).
  8. The claim itself is evidenced (a stored verification record matching the active version, not a memory of success).

2. The exact predicate (normative)

OFFLINE_READY ⟺
    C1  shell_valid:            every precache entry present in the current shell cache
    ∧   C2  dataset_present:    active slot exists for the active edition
    ∧   C3  authenticity:       manifest signature verified against embedded key set
                                (recorded verification matches active packageVersion)
    ∧   C4  integrity:          all manifest-listed files present, sizes match;
                                hashes verified at staging (recorded), spot-check at boot
    ∧   C5  schema_compatible:  package schemaVersion ∈ shell.supportedRange
                                ∧ package.appCompatibility satisfied by APP_VERSION
    ∧   C6  required_sections:  every section with required=true present and parseable:
                                {emergency, schedule, map, info, assets-inventory}
    ∧   C7  required_assets:    every asset referenced by a required section present
                                (size-verified; hash verified at staging)
    ∧   C8  emergency_floor:    embedded baseline present (trivially true; asserted
                                so a broken build cannot silently lose the floor)

Rules of evaluation:

  • Time independence (new, F-1): the predicate must not consult any clock. A device with a wildly wrong clock must still be able to know it is READY. (No expiration fields exist in the package — SPIKE-04 F-2 — so nothing tempts a time check.)
  • Optional sections never gate READY (new, F-2): sections with required=false (future announcements, i18n packs) report their own presence in the status detail but cannot demote READY.
  • Evidence-based: C3/C4 rely on the stored verification record (SPIKE-02 F-2) keyed to the active packageVersion; if the record is absent or mismatched, a full re-verification is required before READY can be claimed.
  • All-or-nothing for READY; everything else is enumerated.

3. State taxonomy (complete)

State Definition User sees Primary action offered
READY C1–C8 all true Green chip "OFFLINE READY ✓" None (status detail on tap)
PARTIAL(list) Shell valid; one or more required sections/assets missing, none corrupt; e.g., prep interrupted Amber chip; status screen enumerates exactly what is missing and what still works "Continue setup" (resumes staging)
NOT_READY Shell valid; no dataset staged or active (fresh install) Neutral chip "Get festival data" Preparation flow
RECOVERY(reason) Previously-verified state now fails checks: storage evicted (missing), verification mismatch (corrupt), incompatibility after app/dataset skew (incompatible) Red chip; honest explanation of what happened "Restore festival data" (re-prep; needs connectivity) — emergency floor works meanwhile
BASELINE_ONLY Storage unavailable (private mode, blocked website data, quota 0) and app cannot persist anything Distinct notice: offline saving unavailable; emergency info still here Install / normal-mode / free-space guidance
FAILED(op) A specific operation failed and no automatic recovery applied (activation transaction repeatedly failing, IDB errors) — distinct from RECOVERY because the cause is an error, not missing data Error screen with plain cause + diagnostics entry Retry; if persistent, re-prep; diagnostics share option

Notes:

  • The brief's example predicate listed schedule_present, map_present, festival_info_present, emergency_baseline_present individually. This model keeps them (C6/C8) but wraps them in the required-section mechanism so future optional sections don't require predicate surgery.
  • FAILED is the added state: RECOVERY means "data is gone/wrong"; FAILED means "an operation errored". Keeping them separate keeps user messaging and diagnostics accurate.

4. Evaluation cadence and cost

When What Cost target
Every boot Light check: C1 (cache list), C2 (slot existence), C4-light (sizes + verification-record match), C5 ≤ ~150 ms; no hashing
After staging completes Full: all hashes + schema (C3–C7 full) Seconds; once per update
Activation Record written atomically with the flip; readback spot-check (pending flag, SPIKE-02 F-3) ms
User-initiated "Check my data" Full re-verification Seconds, with progress
After any IDB error Full re-verify of active slot; quarantine on failure Seconds

5. Edge cases adjudicated

Case State Why
Eviction between install and festival RECOVERY(missing) Light check finds no slot; floor still works
Verification record present but files gone RECOVERY(missing) Sizes check fails
Files present but record missing (e.g., partial restore) PARTIAL → full re-verify path READY cannot be claimed without evidence
New shell, dataset schema too old RECOVERY(incompatible) with "update data when online" guidance; floor + status usable C5 false
Wrong device clock READY unaffected; separate clock warning (SPIKE-08) Time independence
Optional announcements section missing READY F-2
Private browsing, nothing persistable BASELINE_ONLY Storage probes fail early
Activation failed twice FAILED(activation) Distinct from data loss

6. Cross-checks

  • Consistent with SPIKE-02 (verification record + readback pending flag).
  • Consistent with SPIKE-04 (required flag, no expiration).
  • Consistent with SPIKE-06 (floor assertion C8; emergency never depends on READY).
  • Consistent with SPIKE-07 (prep levels map onto PARTIAL/READY transitions).

7. Verdict

ACCEPT (with formalization). The ARCH §12 model was directionally correct; it is now normative: predicate C1–C8, time independence, optional-section rule, and the full six-state taxonomy including FAILED. Changes are refinements of the design document, not a direction change; no ADR-level reversal.