EPIC-2 Slice L of #1097. Multi-source Blueprint catalog HTTP REST
service backed by Gitea (3 sources: public mirror, sovereign-curated,
per-Org private). Replaces the per-Org SME catalog per ADR-0001 §4.3
(different scope: SME's was Org-bound; catalyst-catalog is Sovereign-
wide multi-source).
L1 — core/services/catalyst-catalog/ Go service:
- Separate go.mod (services group is for HTTP services, controllers
group is for CRD reconcilers — documented in DESIGN.md).
- Imports the unified Gitea client via Go module replace directive.
- Promoted core/controllers/internal/gitea → pkg/gitea so the catalog
(a sibling Go module) can import it (Go internal/ rule). 5 Group C
controllers updated atomically.
- HTTP REST endpoints: /api/v1/catalog{,/{name},/{name}/versions,
/{name}/versions/{version}} + /healthz.
- Source resolution priority on collision: private > sovereign > public.
- Per-Org access filter: caller's Claims.Groups[] determines visible
private blueprints; Org A user does NOT see Org B's private set.
- 30s TTL LRU cache on blueprint.yaml reads (capacity 1024 default).
- Session-cookie / Bearer / ?access_token= claim extraction matching
catalyst-api's seam; expired-token rejection in-process.
- Containerfile: distroless-static, non-root UID 65532.
L2 — products/catalyst/chart/templates/services/catalog/ wiring:
- 5 templates (deployment, service, serviceaccount, rbac, httproute)
+ _helpers.tpl. Default-OFF gate via .Values.services.catalog.enabled.
- helm template: 0 catalog resources when OFF, 6 when ON.
- Empty image.tag fail-fasts at render per Inviolable Principle #4a.
- HTTPRoute exposes /api/v1/catalog on api.<sovereign> hostname.
- Chart bumped 1.4.85 → 1.4.86.
Gitea client extension (canonical seam, NOT per-service variant):
- +ListOrgRepos(ctx, org) []Repo — paginated repo listing.
- +ListContents(ctx, org, repo, branch, path) []ContentEntry —
directory listing for per-Org shared-blueprints fan-out.
GitHub Actions workflow:
- .github/workflows/catalyst-catalog-build.yaml — push-on-paths +
pull_request + workflow_dispatch (NO cron). go vet + go test (race +
count=1) + image build → GHCR :<sha>. repository_dispatch fan-out
to chart-bump matches the Group C controllers' pattern.
Tests (3-tier gate): unit (config, cache, auth, source, handler) +
integration (httptest-backed Gitea fixtures across all 3 sources +
priority + per-Org access). All green; race detector on.
L3 (SME catalog retirement) is deferred per the EPIC-2 master brief.
GraphQL deferred (REST first; gqlgen would pull ~80MB of indirect deps
for a feature no UI consumer has asked for yet).
Co-authored-by: hatiyildiz <hati.yildiz@openova.io>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>