diff --git a/docs/emergency/COLLECTIONS_SEAM.md b/docs/emergency/COLLECTIONS_SEAM.md new file mode 100644 index 0000000..605851c --- /dev/null +++ b/docs/emergency/COLLECTIONS_SEAM.md @@ -0,0 +1,143 @@ +# Collections Seam Decision + +## Decision + +The emergency fork should **reuse the collections seam**, but **not import the whole upstream collections stack as-is**. + +The right split is: + +- **reuse in place**: manifest JSON files and their resource contract +- **reuse via adapter**: schema validation, tier resolution, and installed-status logic +- **do not reuse directly in v1**: controller, route, and update-service wiring that is tied to Adonis, Lucid, and the current server/admin runtime + +In short: + +> the collections seam is strong enough to preserve, but the current upstream implementation is too framework-coupled to become the emergency runtime boundary unchanged. + +## Evidence from upstream + +### What is strong and worth preserving + +The upstream collections layer is already explicit, versioned, and content-oriented. + +Relevant upstream files: + +- `collections/kiwix-categories.json` +- `collections/maps.json` +- `collections/wikipedia.json` +- `admin/types/collections.ts` +- `admin/app/validators/curated_collections.ts` + +Why this is a strong seam: + +- manifests are versioned with `spec_version` +- resource entries are explicit: `id`, `version`, `title`, `description`, `url`, `size_mb` +- maps, curated ZIM content, and Wikipedia are all represented through the same family of contracts +- validators already define the acceptable schema cleanly + +### What is reusable, but only behind a thin adapter + +Relevant upstream files: + +- `admin/app/services/collection_manifest_service.ts` +- `admin/app/models/collection_manifest.ts` +- `admin/database/migrations/1770849108030_create_create_collection_manifests_table.ts` +- `admin/app/models/installed_resource.ts` +- `admin/database/migrations/1770849119787_create_create_installed_resources_table.ts` + +Useful parts: + +- fetch and cache semantics for versioned specs +- pure tier resolution logic +- installed-status computation +- installed resource registry shape + +Why it should sit behind an adapter: + +- `CollectionManifestService` is coupled to Axios, Vine, Lucid, and hard-coded upstream URLs +- persistence is expressed through the current admin app models +- emergency runtime will likely want its own daemon-owned storage and sync state + +### What should not be reused directly in v1 + +Relevant upstream files: + +- `admin/app/controllers/easy_setup_controller.ts` +- `admin/app/controllers/collection_updates_controller.ts` +- `admin/start/routes.ts` +- `admin/app/services/collection_update_service.ts` + +Why not: + +- route/controller layer is tied to the admin UX and Adonis route tree +- update flow assumes current upstream API orchestration choices +- emergency runtime needs `ON` / `OFF` policy enforcement and armed one-shot semantics that do not exist here + +## Practical reuse strategy + +### Reuse in place + +Keep these upstream assets as the canonical source-selection layer for now: + +- `collections/*.json` + +This preserves incremental compatibility and gives the emergency fork a stable seam with minimal divergence. + +### Reuse through an emergency adapter + +Create a future emergency-side adapter that owns this contract: + +- load a manifest spec from local file or cached remote source +- validate against the upstream schema +- resolve tier inheritance +- compute installed status from local install state +- expose normalized results to the emergency daemon + +This adapter should be framework-light and daemon-friendly. + +### Keep emergency storage independent but mappable + +The emergency runtime should not depend directly on Lucid models, but it should remain easy to map from upstream concepts: + +- `collection_manifests` -> cached upstream specs +- `installed_resources` -> local package/install state + +This gives you compatibility without inheriting the current runtime stack. + +## Recommendation for v1 + +For the first technical implementation: + +1. Treat `collections/*.json` as canonical upstream inputs. +2. Mirror the schema contract from `admin/types/collections.ts`. +3. Port or reimplement only the pure logic from `CollectionManifestService`: + - tier resolution + - installed-status computation + - filename parsing +4. Do not reuse `CollectionUpdateService` directly. +5. Put all remote fetch and one-shot policy logic behind the emergency daemon. + +## Concrete next extraction target + +The best next code seam is: + +> a pure emergency collections adapter with no Adonis dependency + +That adapter should accept: + +- manifest type +- raw manifest JSON +- local installed resource state + +And return: + +- validated normalized manifest +- resolved tiers/collections +- install status +- candidate resources for one-shot sync + +## Bottom line + +The emergency fork should **stay aligned to upstream collections data** while **owning its own runtime behavior**. + +That is the cleanest way to keep incremental compatibility without dragging the entire admin/server stack into the emergency core. diff --git a/docs/emergency/README.md b/docs/emergency/README.md index f53573f..0388a6a 100644 --- a/docs/emergency/README.md +++ b/docs/emergency/README.md @@ -22,6 +22,7 @@ The profile is designed for a dedicated Android device running Ubuntu/Linux wher - [Architecture](./ARCHITECTURE.md) - [Local API](./LOCAL_API.md) - [Seam Map](./SEAM_MAP.md) +- [Collections Seam](./COLLECTIONS_SEAM.md) - [Bootstrap Prompt](./BOOTSTRAP_PROMPT.md) ## Intended use