The fetch -> TTL -> last-good -> bundled pipeline that four services
re-implemented (and that produced the bundled-index and proxy-rewrite
incidents) now lives once in utils/remote_index. The extension registry
and theme registry become thin normalizers over it; the registry gains
the failure-retry throttling the theme copy had already hardened to
(last-good under full TTL, bundled held only error_ttl). Deliberate
non-adopters, documented: template_service (keyed per-repo cache with
targeted invalidation) and security_feed (DB-durable last-good for a
daily job). Engine unit tests pin the semantics; registry/theme/signing
suites stay green (test seeds updated to the shared cache seam).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Review feedback + follow-up on the review-stamps feature:
- The 409 trust gate now distinguishes reason 'unreviewed' (community
code not vetted) from 'unverified' (no pinned checksum, possible even
for first_party), each with an accurate message; the risk dialog
carries the reason and matches its title/body to the actual case
instead of always claiming 'unreviewed community extension'
- Unreviewed registry entries are now developer-stage content: hidden
from the Marketplace catalog and refused at the install endpoint
(404) unless the panel runs in a development context (Flask debug /
testing config, or the dev_mode setting). Hidden means not
installable; the 409 acknowledgment flow only exists where they list
- dev_mode setting description mentions the Marketplace effect
- tests: reason assertions on both 409 cases; catalog visibility and
404-on-hidden-install coverage (38 passing)
The registry index (schema v3) can now carry a review object per entry
(reviewer, date, sha256, optional commit/notes) asserting that someone
inspected the exact artifact being listed. The stamp is bound to the
artifact hash: review.sha256 must equal the entry sha256, so any change
to the released zip invalidates the review.
- registry_service: keep review through normalization (validated),
derive trust per entry: first_party, reviewed (stamp matches the
pinned hash), or unreviewed
- marketplace install route: unreviewed (or sha256-less) entries return
409 requires_acknowledgment unless the admin posts
acknowledge_risk: true; acknowledged installs record trust in the
audit log. Consent gate, consistent with ADR 0002
- Marketplace UI: Reviewed badge (reviewer + date tooltip) and
Unreviewed warning badge on registry cards, plus a risk confirmation
modal that retries the install with acknowledge_risk
- tests: trust derivation and the install gate (409 + acknowledge path)
- docs: EXTENSIONS_REGISTRY.md documents the field and the flow
Flip DEFAULT_REGISTRY_URL to https://serverkit.ai/ext/index.json (the
long-planned go-live default: cached proxy of the raw index with logo URL
rewriting). Add logo fields to the bundled offline index so Marketplace
cards get real art even before the first successful fetch, and update the
registry tests + docs for the new default.
Stop stripping the v2 fields in registry_service normalization: add repo,
logo, bundled to _FIELDS. Repo-relative logos (assets/<slug>/<file>) are
resolved to absolute URLs against the index URL they came from, so one
relative path works for both the raw-GitHub index and the serverkit.ai
/ext endpoint. Bundled entries are excluded from the Browse catalog by
default (they duplicate builtin cards) and reachable via
?include_bundled=true. Detail modal gains a Source repo link.
Tests: v2 normalization, relative-logo resolution, v1 unaffected, bundled
exclusion + include_bundled endpoint flag. Full test_registry.py green (19).
Docs: EXTENSIONS_REGISTRY.md documents schema_version 2 + v2 fields.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
SERVERKIT_REGISTRY_URL unset now resolves to the curated raw index at
jhd3197/serverkit-extensions (the go-live step for the registry infra);
set-but-empty explicitly disables remote fetching (air-gapped panels,
and how the test suite stays offline — pinned in conftest). URL is
resolved per fetch so env changes apply without a restart. Cache ->
bundled fallback chain unchanged; the Marketplace never blanks.
3 proving tests (default, empty-disables, override); registry/plugin
selection 76 passed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>