mirror of
https://github.com/Crosstalk-Solutions/project-nomad.git
synced 2026-03-29 21:19:25 +02:00
manifesto: hard-offline first, one shot when the world blinks back
This commit is contained in:
parent
edcfd937e2
commit
d3aec3d535
115
docs/emergency/ARCHITECTURE.md
Normal file
115
docs/emergency/ARCHITECTURE.md
Normal file
|
|
@ -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.
|
||||
33
docs/emergency/BOOTSTRAP_PROMPT.md
Normal file
33
docs/emergency/BOOTSTRAP_PROMPT.md
Normal file
|
|
@ -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.
|
||||
119
docs/emergency/LOCAL_API.md
Normal file
119
docs/emergency/LOCAL_API.md
Normal file
|
|
@ -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.
|
||||
29
docs/emergency/README.md
Normal file
29
docs/emergency/README.md
Normal file
|
|
@ -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.
|
||||
Loading…
Reference in New Issue
Block a user