diff --git a/docs/emergency/ARCHITECTURE.md b/docs/emergency/ARCHITECTURE.md new file mode 100644 index 0000000..c8e7504 --- /dev/null +++ b/docs/emergency/ARCHITECTURE.md @@ -0,0 +1,115 @@ +# Emergency Runtime Architecture + +## Summary + +The emergency runtime is a downstream profile of Project N.O.M.A.D. for a dedicated handheld device. + +The architectural center is not "online mode versus offline mode". +The center is a hard-offline local runtime that can ingest updates while the network exists. + +## Product truth + +- The primary asset is the local corpus. +- The primary read path is local search and local maps. +- The primary update path is opportunistic sync. +- Network loss is a normal operating assumption. +- In hostile or uncertain conditions, the device may need to remain on `OFF` and use only explicit one-shot exceptions. + +## Downstream strategy + +This fork should stay incrementally compatible with Project N.O.M.A.D. where practical. + +Reuse first: + +- collections and manifest shapes +- provider adapters and source metadata +- content ingestion and packaging logic +- offline maps plumbing where useful + +Break away only where required by the emergency device use case: + +- admin panel as primary UX +- Docker-orchestrated runtime assumptions +- mandatory Ollama/Qdrant path +- server-first deployment shape + +## Runtime shape + +The recommended runtime shape is: + +1. installable mobile PWA +2. local daemon on the device +3. loopback HTTP API between UI and daemon +4. local SQLite plus FTS for text search +5. local filesystem storage for content and maps + +The read path should remain local even when the device has connectivity. + +## Network policy model + +### `ON` + +Use when continuous background sync is acceptable. + +Behavior: + +- daemon may probe connectivity +- daemon may refresh manifests on schedule +- daemon may download and index changed packages +- UI still resolves from local data first + +### `OFF` + +Use for battery conservation, OPSEC, or deterministic offline operation. + +Behavior: + +- daemon does not perform normal network requests +- probing is suppressed +- cached reachability state may become stale +- local corpus remains fully usable + +### Armed one-shot sync + +Use when the device should stay logically `OFF` but the operator wants to exploit a short or uncertain network window. + +Behavior: + +1. choose a bounded scope: `all`, `manifests`, `documents`, `maps`, or a single source +2. keep base policy at `OFF` +3. if a usable network is available, run one short sync job +4. if a usable network is not available yet, remain armed until timeout +5. auto-disarm after one attempt, success, failure, or timeout + +Recommended defaults for v1: + +- one-shot timeout: 10 minutes +- byte cap config exists but is disabled by default +- download count cap config exists but is disabled by default + +## Operational rule + +Treat network policy and observed reachability as separate concerns: + +- policy answers "may the device use the network?" +- reachability answers "is a usable network currently present?" + +This matters because in insecure scenarios a device may observe a usable network and still need to remain on `OFF`. + +## Initial repo strategy + +Keep emergency-specific work additive and easy to diff against upstream. + +Recommended approach: + +- keep upstream structure intact where possible +- add emergency docs under `docs/emergency/` +- add emergency runtime code in new bounded paths instead of patching unrelated upstream areas early +- prefer adapters and feature flags over broad rewrites + +## Immediate milestones + +1. Document the emergency profile and local API. +2. Identify the smallest reusable seams from upstream. +3. Build a loopback-only daemon skeleton for status, search, and one-shot sync. +4. Keep the first implementation local-search-first and map-capable. diff --git a/docs/emergency/BOOTSTRAP_PROMPT.md b/docs/emergency/BOOTSTRAP_PROMPT.md new file mode 100644 index 0000000..47cb9b8 --- /dev/null +++ b/docs/emergency/BOOTSTRAP_PROMPT.md @@ -0,0 +1,33 @@ +# Emergency Bootstrap Prompt + +Use this brief when scaffolding emergency-specific work in this downstream fork. + +## Goal + +Build an emergency runtime profile on top of Project N.O.M.A.D. that favors hard-offline usefulness, local search, and bounded sync. + +## Constraints + +- Keep upstream compatibility where practical. +- Prefer additive paths over invasive rewrites. +- Assume the device is a dedicated Android or Ubuntu handheld. +- Keep v1 deterministic: search, excerpt, source, maps. +- Do not make LLM or vector infrastructure a hard runtime dependency. + +## Network model + +- Base policy: `ON` or `OFF` +- Explicit exception: armed one-shot sync +- One-shot must support: + - bounded scope + - timeout + - byte cap setting + - download count cap setting + - auto-disarm + +## Quality bar + +- Keep the read path local. +- Keep network usage explicit. +- Keep the delta against upstream small and understandable. +- Prefer boring and reliable over clever abstractions. diff --git a/docs/emergency/LOCAL_API.md b/docs/emergency/LOCAL_API.md new file mode 100644 index 0000000..d3d0e67 --- /dev/null +++ b/docs/emergency/LOCAL_API.md @@ -0,0 +1,119 @@ +# Emergency Local API + +## Purpose + +This API exists to expose the emergency runtime to a local PWA over loopback only. + +The API is not public and should not be exposed on the internet. + +## Base URL + +```text +http://127.0.0.1:4187/api/v1 +``` + +## Core model + +- Read operations are local-first. +- Base network policy is `ON` or `OFF`. +- One-shot sync is an explicit bounded exception path. + +## Key endpoints + +### `GET /status` + +Returns high-level runtime state. + +Example: + +```json +{ + "network_policy": "OFF", + "network": { + "reachable": null, + "last_checked_at": "2026-03-24T18:20:00Z", + "probe_allowed": false + }, + "oneshot": { + "armed": true, + "state": "armed", + "scope": "manifests", + "timeout_seconds": 600, + "enforce_byte_cap": false, + "byte_cap_mb": 0, + "enforce_download_cap": false, + "download_cap_count": 0, + "armed_at": "2026-03-24T18:30:00Z", + "expires_at": "2026-03-24T18:40:00Z" + }, + "sync": { + "state": "idle", + "last_success_at": "2026-03-24T18:20:00Z" + } +} +``` + +### `GET /mode` + +Returns base network policy and one-shot state. + +### `PUT /mode` + +Sets base network policy. + +Request: + +```json +{ + "network_policy": "OFF" +} +``` + +Allowed values: + +- `ON` +- `OFF` + +### `POST /sync/oneshot` + +Triggers or arms a bounded one-shot sync while leaving base policy unchanged. + +Request: + +```json +{ + "scope": "manifests", + "reason": "manual", + "arm_if_offline": true, + "timeout_seconds": 600, + "enforce_byte_cap": false, + "byte_cap_mb": 0, + "enforce_download_cap": false, + "download_cap_count": 0 +} +``` + +Behavior: + +- if network is available now, queue one short sync job +- if network is unavailable and `arm_if_offline = true`, keep the request armed until timeout +- auto-disarm after one attempt, success, failure, or timeout + +### `POST /sync/run` + +Triggers a normal sync cycle. +This route is intended for policy `ON`. + +### `GET /search` + +Returns local search results only. + +### `GET /documents/:document_id` + +Returns locally stored document content and provenance metadata. + +## Notes + +- `network.reachable` may be `null` when active probing is suppressed by `OFF`. +- One-shot is the preferred explicit exception path from `OFF`. +- Cap fields are present in v1 but disabled by default until payload sizes are better understood. diff --git a/docs/emergency/README.md b/docs/emergency/README.md new file mode 100644 index 0000000..9da42c8 --- /dev/null +++ b/docs/emergency/README.md @@ -0,0 +1,29 @@ +# Emergency Runtime Profile + +This folder defines a downstream emergency profile for Project N.O.M.A.D. + +The profile is designed for a dedicated Android device running Ubuntu/Linux where the system must remain useful with zero network and treat network availability as an opportunistic ingest path, not as part of the main read path. + +## Core principles + +- Hard-offline first: search, maps, and critical reads must work from local storage. +- Incremental compatibility: reuse upstream Project N.O.M.A.D. code where practical and keep the delta small. +- Device-first runtime: prefer a local daemon plus a mobile-friendly PWA over server/admin assumptions. +- Bounded sync: network use should be explicit, short, and policy-driven. + +## Network policy model + +- `ON`: normal background sync is allowed. +- `OFF`: no normal network activity is allowed. +- Armed one-shot sync: a bounded exception that can remain armed while base policy stays `OFF`. + +## Document map + +- [Architecture](./ARCHITECTURE.md) +- [Local API](./LOCAL_API.md) +- [Bootstrap Prompt](./BOOTSTRAP_PROMPT.md) + +## Intended use + +This is not a chat-first product. +It is a continuity-of-information runtime that keeps a local corpus current while it can, then continues to serve that corpus when the network disappears or should not be used.