Lumen/SPIKE-06-EMERGENCY-BASELINE.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

119 lines
5.6 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.

# SPIKE-06 — Emergency Baseline Architecture
- **Phase:** Architecture Validation
- **Date:** 2026-08-30
- **Decision under test:** ADR-007 (three-tier emergency architecture with an
embedded floor).
- **Outcome:** decision confirmed; tier contents fixed; version/compatibility
matrix resolved; one hardening rule added.
## 1. What belongs in each tier (fixed)
### Tier 1 — Emergency Floor (embedded in app shell, immutable per build)
Must fit ≤ 16 KB and cover "what saves a life or prevents panic in the first
minutes":
```json
{
"floor": true,
"floorVersion": "1.0.0+2026.08.20",
"emergencySchemaVersion": 1,
"generatedAt": "2026-08-20T12:00:00Z",
"sourceContentVersion": 5,
"services": {
"emergencyNumber": "911",
"security": { "phone": "+1-555-0142" },
"firstAid": { "summary": "Behind Stage B, 10:00–02:00" }
},
"address": { "lines": ["…"], "coordinates": { "lat": 41.88, "lon": -87.63 } },
"musterPoints": [ { "name": "North Field", "directions": "…" } ],
"exits": [ { "name": "East Gate" }, { "name": "West Gate" } ],
"aedSummary": "AEDs at Info Tent and Main Gate (see map when available)",
"procedures": [
{ "id": "medical", "title": "Medical emergency", "steps": ["Call 911", "Alert security: +1-555-0142", "…"] },
{ "id": "weather", "title": "Severe weather", "steps": ["…"] },
{ "id": "fire", "title": "Fire", "steps": ["…"] },
{ "id": "lost", "title": "Lost person", "steps": ["…"] }
]
}
```
Excluded from the floor (by policy): full POI lists, per-location detail,
vendor/operational info, anything that changes frequently. The floor is a
**life-safety minimum**, not a small copy of the dataset section.
### Tier 2 — Festival Emergency Dataset (signed section of the package)
Full detail: all emergency-relevant POIs with map links, complete procedure
text, per-role contacts, hours, notices, `contentVersion`/`updatedAt`
(SPIKE-04 fragment). Updateable by publishing a new package version.
### Tier 3 — Optional live emergency notices (future, reserved)
Shape reserved: `{ id, severity, title, body, publishedAtUtc, expiresAtUtc,
signature }`, delivered with a package or via the transport seam; rendered
only when signed and unexpired; **display-only, additive, never a replacement
for Tier 1/2**. Not implemented in V1.
## 2. Resolution rules (normative)
```
render_emergency():
floor = embedded floor # always exists; parses from frozen schema
section = active dataset emergency section
if section exists
and section.emergencySchemaVersion ∈ shell.supportedEmergencySchemas
and section passes integrity (already guaranteed by activation):
render section (full detail), labeled "FESTIVAL DATA v<package> · <generatedAt>"
render floor-only fields if section omits any (defensive merge)
else:
render floor, labeled "BASELINE v<floorVersion>"
append Tier-3 notices if any signed+unexpired (future)
```
Hardening rule **(new, F-1)**: the floor renderer is **forward-tolerant** —
it ignores unknown fields and never throws on dataset content; and the floor
path must be reachable with **zero IDB access**, because BASELINE_ONLY and
eviction scenarios must still render emergency info.
## 3. The cases the spike must answer
| Case | What renders | Why the floor never disappears |
|---|---|---|
| Shell old, dataset newer (section schema v2 vs floor/shell supports v1) | Floor + "update app when online" note; known-v1 fields of the section may still render if backward-compatible | Floor is compiled into the shell; dataset incompatibility can only *demote to floor*, never remove it |
| Shell new, dataset old | Dataset section (old schema is within shell's supported range) or floor | Backward range support (C-23) |
| Dataset unavailable (never prepared) | Floor | Floor ships with shell bytes |
| Dataset corrupt (verification fails at staging — never activated) | Previous dataset section if active slot intact, else floor | Corruption blocks activation (SPIKE-02); floor unaffected |
| Storage evicted | Floor | Floor is shell bytes, not IDB; Ring-0 survival |
| Network unavailable | Whatever is local: active dataset section or floor | No network call exists in the emergency render path |
| Update fails mid-flight | Old active dataset (or floor) | A/B invariant (SPIKE-02); staging never touches shell or active slot |
## 4. Tradeoffs (re-stated with verdicts)
- **Baseline staleness** (floor frozen at shell build): accepted. Mitigations:
same-source generation (no drift), floor version stamp on screen, Tier 2
updates for anything less-than-critical, organizer physical channels for
urgency.
- **Baseline scope creep**: resisted. 16 KB cap + content policy (life-safety
minimum only). Everything else belongs in Tier 2.
- **Two copies drift**: eliminated by generating floor + section from the same
emergency source sheet in the pipeline (ADR-007/§10.3).
- **Separate localStorage copy of emergency data**: rejected again — it dies in
eviction too; only shell bytes survive everything.
## 5. Cross-checks
- SPIKE-05 C8 asserts floor presence in the readiness predicate (defense
against a broken build silently dropping the floor).
- SPIKE-04 F-3 gives the emergency section independent versioning used by the
resolution rules above.
- ADR-013: the floor's provenance is the shell build itself (signed app
delivery); Tier 2 inherits package signatures; Tier 3 will require
per-notice signatures.
## 6. Verdict
**ACCEPT.** ADR-007 stands unchanged in direction; addendum records the fixed
tier contents, the resolution/merge rules, the forward-tolerant floor renderer
(F-1), and the zero-IDB requirement for the floor path.