WAP LabsProject atlas

docs/waves/resilience_work_items.md

Waves Failure Containment and Recovery Work Items

Purpose: track the additive browser, Tauri-host, and engine resilience work found by the 2026-07-29 current-main failure-containment audit.

Audit base: origin/main 6cf1682a (planning sync 2026-07-30).

Status keys:

  • todo
  • in-progress
  • blocked
  • done

Product Requirement

One malformed request, response, deck, script, timer event, or host/engine failure must not freeze or crash Waves, create an uncontrolled network storm, corrupt navigation/history state, or prevent the user from loading a known-good deck. Failures must terminate predictably, expose a useful typed error, preserve usable state where appropriate, and leave an explicit recovery path.

Scope and Ownership

  • Browser-owned containment stays in browser/frontend: navigation admission, failed-intent quarantine, recovery UI, history, and diagnostic projections.
  • Host/IPC containment stays in browser/src-tauri: request validation, cancellation/concurrency, typed errors, and transactional engine command adaptation.
  • Runtime work/output limits stay in engine-wasm: layout/render budgets and native/WASM parity.
  • WBXML decoding, transport retry semantics, and network policy stay in transport-rust.
  • The separately owned public service/deployment/examples work does not satisfy or replace these client-side containment items.
  • Coordinate browser-presenter.ts work through one active presenter/history owner; these tickets change behavior and data handling, not styling.

Immediate Containment Gate

The P1 containment gate is closed: RSL-01 quarantines terminal external-intent failures, RSL-02 bounds and cancels navigation work, RSL-03 makes mutating frame commands transactional, and RSL-04 bounds single-pass render output. RSL-05 closes malformed IPC admission and typed host failures, RSL-06 closes diagnostic/export redaction, and RSL-07 closes bounded presenter/history state.

Lane A: Navigation Containment

RSL-01 Terminal external-intent failure quarantine

  1. Issue: #510
  2. Status: done
  3. Priority: P1 release blocker; treat as P0 for a distributed build exposed to uncontrolled public content
  4. Depends On: none
  5. Files:
  • browser/frontend/src/app/navigation-state.ts
  • browser/frontend/src/app/engine-timer-runtime.ts
  • browser/frontend/src/app/browser-controller.ts
  • focused tests for those modules
  1. Build:
  • Quarantine a terminally failed external intent by request identity plus engine/navigation generation.
  • Preserve the invoking engine state and pending intent; do not weaken WML-205 rollback behavior by clearing engine state.
  • Permit a new automatic follow only when intent identity changes, or one explicit attempt when the user chooses Reload/retry.
  1. Tests:
  • A WBXML_DECODE_FAILED target followed by 50 timer ticks produces one automatic target fetch.
  • Explicit Reload causes exactly one new attempt.
  • A known-good URL or local deck loads afterward and stops the failed-intent loop.
  • The invoking deck, card, history, focus, variables, and pending engine intent remain intact.
  1. Accept:
  • Terminal failure produces one bounded outcome and one useful error surface.
  • No timer-driven automatic replay occurs without a changed intent or explicit user action.
  1. Resolution:
  • Browser navigation now quarantines terminally failed external intents by resolved request identity and navigation generation without clearing engine state. Timer snapshots suppress the same quarantined intent, while explicit Reload/Go and changed intents receive one fresh attempt.
  • Focused controller coverage proves one WBXML decode failure plus 50 timer ticks issues one target fetch, preserves the invoking state, deduplicates the failure notification, permits one explicit retry, and recovers through a changed known-good target.

RSL-02 Cancellable and admission-controlled navigation

  1. Issue: #509
  2. Status: done
  3. Priority: P1
  4. Depends On: RSL-01
  5. Files:
  • browser/frontend/src/app/navigation-state.ts
  • browser/frontend/src/app/browser-controller.ts
  • browser/frontend/src/app/shell-event-bindings.ts
  • browser/src-tauri/src/lib.rs
  • fetch command/client contracts and focused tests
  1. Build:
  • Admit or coalesce one logical navigation operation instead of starting an independent fetch for every rapid action.
  • Add a cancellable host fetch contract and stop superseded attempts/retries.
  • Bound concurrent native fetch tasks while keeping generation checks as the final state-integrity guard.
  1. Tests:
  • Eight rapid identical actions produce at most one active fetch.
  • Back or a new URL stops superseded work and cannot receive a stale toast, transport-panel update, or history mutation.
  • A hung response can be cancelled and followed by a successful known-good load.
  1. Accept:
  • Both active work and committed state remain bounded under conflicting navigation.
  1. Resolution:
  • Browser navigation now coalesces identical active request identities, assigns each admitted operation a cancellable request ID, and cancels superseded work for changed URLs, Back, Stop, mode changes, and disposal before admitting replacement transport work.
  • The generated Tauri contract exposes cancel_fetch; the host admits at most two native fetch tasks so one cancelled request still blocked in kernel I/O cannot prevent its replacement. The shared transport cancellation token prevents cancelled responses, retries, and gateway fallback from continuing after the active blocking call returns.
  • Focused frontend and host/transport tests cover eight-way coalescing, stale projection suppression, Back/Stop cancellation, hung-request recovery, bounded admission, and retry cancellation. Navigation generation checks remain the final frontend state-integrity guard.

Lane B: Engine and Frame Resource Safety

RSL-03 Transactional frame commands and viewport validation

  1. Issue: #508
  2. Status: done
  3. Priority: P1
  4. Depends On: none
  5. Files:
  • browser/frontend/src/app/browser-controller.ts
  • browser/src-tauri/src/contract_types.rs
  • browser/src-tauri/src/engine_bridge/engine_adapter.rs
  • engine-wasm/engine/src/engine_public_api.rs
  • native/WASM/Tauri boundary tests
  1. Build:
  • Define and validate one shared viewport range before engine mutation.
  • Make every mutating frame command transactional: construct a valid candidate frame before commit or restore the exact previous engine state when frame construction fails.
  • Return a typed invalid-input or resource error rather than a generic parse string.
  1. Tests:
  • u32::MAX + 1 fails before mutation.
  • Forced frame failure after load, input/key, timer, Back, edit, and clear-intent preserves the complete previous state.
  • A valid viewport and known-good deck succeed after each failure.
  1. Accept:
  • No failed frame command leaves engine and frontend state out of sync.
  1. Resolution:
  • Shared viewport bounds now reject out-of-range values with a typed error before mutation.
  • Every mutating frame adapter builds the candidate result against a cloned engine and commits only after frame construction succeeds; focused tests cover load, key/input/action, timer, Back, external-intent, input-edit, and select-edit failure paths plus successful recovery.

RSL-04 Bounded, single-pass render output

  1. Issue: #505
  2. Status: done
  3. Priority: P1
  4. Depends On: RSL-03
  5. Files:
  • engine-wasm/engine/src/layout/flow_layout.rs
  • engine-wasm/engine/src/engine_public_api.rs
  • browser/src-tauri/src/engine_bridge/engine_adapter.rs
  • browser/frontend/src/app/browser-presenter.ts
  • native/WASM/Tauri/frontend tests
  1. Build:
  • Bound layout rows, segments, draw commands, and serialized frame bytes in the engine.
  • Return a typed resource-limit failure with no partial state/presentation commit.
  • Derive legacy render and presentation output from one layout pass during migration.
  • Retain a defensive frontend output cap before HTML/DOM work.
  1. Tests:
  • Native and WASM fixtures exactly at and one unit above each output limit.
  • Rejected pathological output leaves the last good frame visible and a small deck renders next.
  • Tauri frame construction proves one layout pass and native/WASM frame parity remains stable.
  1. Accept:
  • Any accepted deck has a deterministic upper bound on render work and host-visible output.
  1. Resolution:
  • The engine now stops layout at 4,096 rows, 4,096 segments, and 4,096 legacy draw commands, and caps the combined legacy/presentation JSON projection at 2 MiB. Rust-generated EngineRenderError/ENGINE_RENDER_LIMITS contracts keep native, WASM, Tauri, and frontend enforcement aligned.
  • The Tauri compatibility frame consumes one engine render_output() result, so legacy and presentation projections share one instrumented layout pass. Candidate mutation still commits only after bounded frame construction succeeds; focused host tests preserve the last good frame and render a small replacement immediately after rejection.
  • Exact-limit and one-over-limit native/WASM tests cover every budget, the presenter rejects oversized host output before cloning or canvas work, and the RSL-04 wrapping story remains navigable through the generated example corpus.

Lane C: IPC Contract Hardening

RSL-05 Bounded request ingress and typed host errors

  1. Issue: #507
  2. Status: done
  3. Priority: P2
  4. Depends On: none; the wapcurl stream is landed, but its CLI behavior remains out of scope
  5. Files:
  • transport-rust/src/lib.rs
  • transport-rust/src/request_serialization.rs
  • browser/src-tauri/src/lib.rs
  • browser/src-tauri/src/contract_types.rs
  • generated host contracts
  • browser/frontend/src/app/tauri-invoke-guard.ts
  1. Build:
  • Define aggregate limits for request headers, IDs, POST fields, encoded request bodies, card IDs, and edit drafts at their owning Rust boundaries.
  • Reject before transport/spawn work and never echo sensitive payloads in error details.
  • Generate a typed host error envelope and validate non-null IPC responses structurally without hand-copying contract schemas.
  1. Tests:
  • One-over-limit tests for every bounded field and aggregate.
  • Invalid request, cancellation, spawn/join, mutex, engine resource, and response-shape failures remain distinguishable and recoverable.
  • Contract-generation and drift checks pass.
  1. Accept:
  • Malformed IPC terminates predictably before expensive work and all commands remain usable.
  1. Coordination:
  • Do not change transport-rust/src/request_meta.rs, transport retry semantics, or wapcurl CLI exit diagnostics as part of this item.
  1. Resolution:
  • Rust-owned request and host ingress budgets are generated into the TypeScript contracts. Every ticketed field and aggregate has a one-over test, with command-level coverage proving rejection precedes fetch registration, task admission, transport execution, and engine locking.
  • RSL-05 transport and engine host commands return the generated HostCommandError taxonomy; the generated invoke client derives runtime validators from the same Rust-projected declarations. Invalid non-null response shapes fail closed, opaque failures are redacted, and recovery tests call commands successfully after boundary, mutex, and malformed-response failures.
  • Evidence: make lint-rust-transport, make test-rust-transport, browser-host cargo clippy and serialized cargo test, frontend test/lint/typecheck/format checks, contracts:check, tauri:schemas:check, and git diff --check pass.

Lane D: Diagnostic and UI State Bounds

RSL-06 Redacted developer and timeline projections

  1. Issue: #506
  2. Status: done
  3. Priority: P2 security
  4. Depends On: none
  5. Files:
  • browser/frontend/src/session-history.ts
  • browser/frontend/src/app/timeline.ts
  • browser/frontend/src/app/browser-presenter.ts
  • associated history/timeline/presenter tests
  1. Build:
  • Keep exact internal request identity for WML history replay.
  • Build explicit allowlisted/redacted developer-panel and export DTOs.
  • Redact secret headers, legacy payloads, and typed form values while retaining safe method/count/ content-type/length metadata.
  1. Tests:
  • PIN/password, Authorization, Cookie, Proxy-Authorization, legacy payload, and typed post-field values never appear in panel/export JSON.
  • Internal Back still replays the byte-exact original POST.
  1. Accept:
  • Diagnostic artifacts are useful without disclosing replay credentials.
  1. Resolution:
  • Timeline entries are projected into a fixed allowlisted DTO when produced, while host history continues to retain the exact request identity needed for standards-compatible Back replay.
  • Drawer, detached diagnostic, and version 2 timeline-export serialization all consume the same projection. URL userinfo and credential-like query values are removed, request bodies and typed post-field values become count/length metadata, secret header values and arbitrary error details are omitted, and decoded/source payloads do not enter diagnostic state.
  • Focused frontend coverage exercises secret canaries, near-miss query names, raw transport/runtime failures, producer-boundary projection, deterministic metadata, and byte-exact internal POST history preservation.

RSL-07 Bounded toast and host-history state

  1. Issue: #504
  2. Status: done
  3. Priority: P2
  4. Depends On: RSL-06
  5. Files:
  • browser/frontend/src/app/browser-presenter.ts
  • browser/frontend/src/session-history.ts
  • browser/frontend/src/app/timeline.ts
  • associated tests
  1. Build:
  • Deduplicate and cap identical queued toasts.
  • Let successful recovery supersede stale failure notifications.
  • Define deterministic oldest-entry history eviction with a documented retained WML back depth.
  1. Tests:
  • 97 identical failures remain within capacity and create one accessible failure announcement.
  • A later successful load becomes visible immediately.
  • A 10,000-navigation simulation keeps history and exported state bounded while Back/index/forward truncation remain deterministic within the retained window.
  1. Accept:
  • UI and host-session collections remain bounded and preserve an obvious recovery signal.
  1. Resolution:
  • Toast state retains at most four notifications (one visible plus three queued), coalesces identical message/tone pairs, and lets a successful recovery status or toast immediately remove stale failures. Repeated identical failures write the accessible live region once.
  • Host history retains 32 entries: the current entry plus 31 deterministic WML Back steps. Forward history is truncated before a push, then overflow evicts the oldest entry and re-bases the index to the retained window. Retained POST request identities are independently cloned and remain byte-exact for replay.
  • Timeline production and exported diagnostic state retain at most 200 already-redacted entries, even if a caller requests a larger window. A 10,000-navigation simulation covers history, timeline, toast, and export bounds.
  • Issue #450 remains a separate follow-up: this eviction policy preserves every entry it receives (including duplicates) but does not repair same-card history identity lost across deck replacement. Persistent/searchable history must continue to wait for that identity fix.

Dispatch Order and Conflict Map

Completed containment and IPC batches:

  1. RSL-01 navigation quarantine
  2. RSL-02 cancellable/admission-controlled navigation
  3. RSL-03 transactional frame commands
  4. RSL-04 bounded single-pass render output
  5. RSL-05 bounded ingress and typed host errors

Completed diagnostic/UI-state sequence:

  1. RSL-06 diagnostic and export redaction.
  2. RSL-07 bounded toast/history state on the completed RSL-06 projection boundary.

Issue #450 history identity/cross-deck correctness remains required before persisted or searchable history.

Likely conflicts:

  • issue #450 / WBP-11 / merged shell presentation: host-history and presenter surfaces