Skip to content

feat(plugins-registry): serve GET /bundles.json + /bundles-schema.json - #95

Merged
acamarata merged 1 commit into
mainfrom
p6/e4-w3-s3-t8-bundles-json-route
Sep 13, 2026
Merged

acamarata merged 1 commit into
mainfrom
p6/e4-w3-s3-t8-bundles-json-route

Conversation

@acamarata

Copy link
Copy Markdown
Contributor

Summary

P6-E4-W3-S3-T8. Adds the two missing CF worker routes ADR-P6-03 specifies:

  • GET /bundles.json — bundle-to-plugin membership map
  • GET /bundles-schema.json — the schema it validates against

Both fetch from GitHub via the same authenticated Contents API pattern
fetchProRegistry already uses (reused, not reimplemented — see
fetchGitHubContentsJson in index.js / the mirrored helpers in
registry.ts), cached in PLUGINS_KV under their own keys
(bundles-json-v1, bundles-schema-v1) distinct from the existing
registry:* keys, and POST /api/sync now busts those two keys as well.

bundles.json is structurally validated against the 6 canonical bundle
slugs (task, chat, claw, family, sentry, clawde) before being served —
a fetch failure or a schema failure both return 502, never a malformed
200.

Implemented in both index.js (the file wrangler.toml actually deploys —
main = "src/index.js") and the parallel index.ts / registry.ts
module that this repo also typechecks in CI, kept functionally in sync.

Repo-rename note (important)

The plugins-probundles rename (ADR-P6-01 / P6-E4-W3-S3-T6) has not
landed
. nself-org/bundles does not exist yet. This PR therefore fetches
from nself-org/plugins-pro (current, live repo name) — not bundles
so it works today. Once the rename lands, update the two URL constants:

  • BUNDLES_JSON_API_URL / BUNDLES_SCHEMA_API_URL in
    .workers/plugins-registry/src/index.js
  • the equivalent constants in .workers/plugins-registry/src/registry.ts

Nothing else in this route needs to change — the route handlers, KV keys,
validator, cache headers, and tests are all repo-name-agnostic.

Counts endpoint

The ticket's guide step for "counts" says GET /plugins already returns
live free / pro / total counts computed from the fetched registry
array lengths (handlePluginList) — confirmed by reading the source, this
requires zero code change. No separate /counts.json worker route was
added; I could not find any consumer (CLI, ping_api, web) that expects the
worker itself to serve counts — the CLI's nself plugin count reads a
vendored plugins/counts.json artifact directly from the plugins repo,
unrelated to this worker.

Test plan

  • pnpm run typecheck (tsc --noEmit) — clean, 0 errors
  • pnpm run test (node --test src/*.test.mjs) — 21/21 pass (9
    pre-existing + 12 new in bundles.test.mjs, covering
    validateBundlesJson structural checks and handleBundlesJson's
    KV-hit / fetch-failure / schema-failure / happy-path branches via a
    mocked globalThis.fetch, no real network call)
  • wrangler dev --local/health 200, /bundles.json gracefully
    502s with no GH_ACCESS_TOKEN set (never a malformed 200), the
    404 fallback's endpoint list includes both new routes
  • wrangler deploy --dry-run --env production — clean build (36.97
    KiB / 8.80 KiB gzip), all production bindings resolve
  • Sanity check: ran the real, current plugins-pro/bundles.json off
    disk through validateBundlesJson() — passes with 0 errors
  • Live curl https://plugins.nself.org/bundles.jsonnot done,
    deploy is owner-gated (see below)

Not deployed. wrangler deploy was intentionally not run.

Adds the CF worker route ADR-P6-03 specifies (P6-E4-W3-S3-T8): proxies
plugins-pro/bundles.json (and bundles-schema.json) via the GitHub Contents
API, mirroring fetchProRegistry's existing fetch+decode+KV-cache pattern
rather than reimplementing it. Cached in PLUGINS_KV under its own
bundles-json-v1 / bundles-schema-v1 keys, distinct from registry:* so a
refresh of one never busts the other. bundles.json is schema-validated
against the 6 canonical bundle slugs before serving — 502 on upstream
fetch failure or schema failure, never a malformed 200.

Implemented in both index.js (the file wrangler.toml actually deploys,
main = "src/index.js") and the parallel index.ts/registry.ts module, kept
functionally in sync. POST /api/sync now also busts the two new KV keys.
Both new routes are listed in the 404 fallback's endpoint list.

The plugins-pro -> bundles repo rename (ADR-P6-01 / P6-E4-W3-S3-T6) has
NOT landed yet, so this fetches from nself-org/plugins-pro (current repo
name), not nself-org/bundles. The two URL constants (BUNDLES_JSON_API_URL /
BUNDLES_SCHEMA_API_URL in both index.js and registry.ts) are the only
things that need to change once the rename lands.

Counts: /plugins already returns free/pro/total counts computed live from
fetched registry lengths (handlePluginList) — verified this requires zero
code change, so no separate counts endpoint was added.

Tests: 12 new cases in bundles.test.mjs (validateBundlesJson structural
checks + handleBundlesJson KV-hit/fetch-fail/schema-fail/happy-path via a
mocked global fetch, no real network call), reusing the existing
`node --test src/*.test.mjs` runner. All 21 tests pass (9 pre-existing +
12 new). tsc --noEmit clean. wrangler deploy --dry-run --env production
builds clean (36.97 KiB / 8.80 KiB gzip). Sanity-checked
validateBundlesJson() against the real, current plugins-pro/bundles.json
on disk: passes with 0 errors.

Not deployed — production wrangler deploy is owner-gated.
@acamarata
acamarata merged commit 3b6a7f0 into main Sep 13, 2026
29 checks passed
@acamarata
acamarata deleted the p6/e4-w3-s3-t8-bundles-json-route branch September 13, 2026 07:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant