project-nomad/admin/types
chriscrosstalk 8f06e850a3
feat: support gated downloads for self-hosted curated content (#1172)
Adds an optional `auth: 'nomad_app_key'` discriminator to curated manifest
resources so a curated collection tier can carry content we host ourselves,
gated to official release builds. Without this, only Creator Packs could use
the entitlement Worker; curated tier installs always downloaded
unauthenticated.

No behaviour change for any existing manifest entry: absent `auth` means
unauthenticated, exactly as today.

- `auth` declared on both the type and the VineJS validator. It has to be on
  the validator or VineJS strips it silently on fetch, and the gated download
  would then go out with no header and 401 for everyone. A dedicated spec
  guards that regression.
- Gated resources are pinned to their manifest URL (resolveZimDownload skips
  the catalog comparison) and excluded from catalog update checks, so a
  resource-id collision cannot let a third-party mirror overwrite our content.
  Consequence, commented rather than implied: gated content does not
  auto-update; new versions ship via the manifest.
- 401/403 on a download now reports that an official build is required instead
  of a raw axios status, which is what a fork build will hit.
- The pure `isGatedResource` predicate is deliberately split from the
  env-reading header builder: importing `#start/env` into
  zim_download_resolution triggers env validation at import time and breaks its
  unit tests.

Reuses CREATOR_PACKS_APP_KEY rather than minting a second secret — the question
it answers ("is this an official build?") is identical for both content types.

Verified end to end on a test server: `auth` survives validation into the
cached spec, the Bearer header attaches to only the gated resource, the file
lands byte-exact with an installed_resources row and a Kiwix library entry, and
an entry with a gated URL but no `auth` field fails with the intended message.

No catalog entry is included here. Manifests are fetched live from `main`, so a
gated entry must not merge until this ships and is adopted — pre-`auth` builds
strip the field and 401.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-02 12:23:00 -07:00
..
benchmark.ts feat(benchmark): official multi-arch sysbench, resolved digest, platform metadata (#1158) 2026-07-27 10:26:38 -07:00
chat.ts fix(AI): improved perf via rewrite and streaming logic 2026-03-03 20:51:38 -08:00
collections.ts feat: support gated downloads for self-hosted curated content (#1172) 2026-08-02 12:23:00 -07:00
conditions.ts Add offline FDA drug reference (labels, interaction view, conditions, remedies) (#1040) 2026-07-21 11:06:18 -07:00
docker.ts feat: initial commit 2025-06-29 15:51:08 -07:00
downloads.ts feat(creator-packs): gated per-creator video packs, offline via Kiwix (#1106) 2026-07-20 16:21:18 -07:00
drug_reference.ts Add offline FDA drug reference (labels, interaction view, conditions, remedies) (#1040) 2026-07-21 11:06:18 -07:00
files.ts feat: curated content system overhaul 2026-02-11 15:44:46 -08:00
kb_ingest_state.ts feat(KB): per-file ingest state machine (Phase 1 of RFC #883) (#888) 2026-05-20 10:16:00 -07:00
kv_store.ts Add offline FDA drug reference (labels, interaction view, conditions, remedies) (#1040) 2026-07-21 11:06:18 -07:00
maps.ts feat(Maps): regional map downloads via go-pmtiles extract (#780) 2026-05-20 10:16:00 -07:00
ollama.ts feat(AI): per-model thinking toggle with global default (off) (#1079) 2026-07-20 16:33:09 -07:00
rag.ts feat(rag): add subject/collection organization to knowledge base (#1063) 2026-07-20 15:09:11 -07:00
services.ts feat: replace legacy Kolibri image default with latest v19 image (#1019) 2026-06-23 04:47:07 +00:00
system.ts feat(content): opt-in automatic updates for installed ZIM & map content 2026-06-23 04:47:01 +00:00
util.ts feat: initial commit 2025-06-29 15:51:08 -07:00
zim.ts feat: Expandable rows in Kiwix Library browser (#1060) 2026-07-18 09:55:46 -07:00