feat(web-ng): native add-on import orchestration on a shared OCI client (#3425) #3479

Merged
mfreeman451 merged 1 commit from feat/native-addon-web-importer into staging 2026-06-01 00:21:42 +00:00
Owner

What

build-signing §4.1 (web-ng half) — imports a first-party native add-on from a trusted Forgejo release into a staged AddonPackage, closing the loop with the merged core importer (#3476) + object-storage mirror (#3478) + DB test (#3477).

Modules

  • ServiceRadarWebNG.Plugins.ForgejoOciClient — shared transport, extracted so the native importer (and, in a follow-up, FirstPartyImporter) reuse one client: repo/release/asset fetch, OCI manifest+blob fetch (registry bearer-token + docker-config auth, redirect handling), Cosign verify, trusted-host/URL validation, digest/string utils. Same injection seams as FirstPartyImporter (:first_party_plugin_import_http_client, :first_party_plugin_cosign_verifier, …) so existing config/tests apply.
  • ServiceRadarWebNG.Plugins.NativeAddonImporter.import/1 — resolve repo + release tag → fetch serviceradar-native-addon-index.json → find entry → fetch + Cosign-verify the OCI manifest → assert each per-arch tarball_digest/signature_digest + the bundle_digest is a layer of the verified manifest and pull those blobs by digest (content-addressed) → extract addon.yaml + config.schema.json → assemble per-arch artifacts → core import_entry/4 with NativeAddonArtifactMirror.mirror_fun/3 + a SystemActor.

Trust split: web-ng owns transport + discovery (OCI + cosign); the core owns per-arch ed25519 verification + persistence.

Verification

mix compile --warnings-as-errors + mix credo --strict clean (both modules). The core (#3476/#3477) and mirror (#3478) it builds on are unit- and DB-tested.

Remaining (tasks.md §4)

  • Migrate FirstPartyImporter to delegate to ForgejoOciClient. The shared module is in use by the native importer; FPI still holds its own transport copies. The migration is import ForgejoOciClient + deleting ~50 now-duplicated defps — all-or-nothing on the import (name/arity conflicts), so I kept it out of this PR to avoid destabilizing the working WASM path. It's a pure, test-gated dedup (FPI's test is unit-style, mocks http/cosign, no DB) — a clean focused follow-up.
  • End-to-end test of the web-ng importer (fake OCI/HTTP client serving a fixture index + bundle + per-arch blobs → scratch DB → staged AddonPackage), mirroring first_party_importer_test.exs.

🤖 Generated with Claude Code

## What build-signing **§4.1 (web-ng half)** — imports a first-party native add-on from a trusted Forgejo release into a **staged `AddonPackage`**, closing the loop with the merged core importer (#3476) + object-storage mirror (#3478) + DB test (#3477). ## Modules - **`ServiceRadarWebNG.Plugins.ForgejoOciClient`** — shared transport, **extracted** so the native importer (and, in a follow-up, `FirstPartyImporter`) reuse one client: repo/release/asset fetch, OCI manifest+blob fetch (registry bearer-token + docker-config auth, redirect handling), Cosign verify, trusted-host/URL validation, digest/string utils. Same injection seams as `FirstPartyImporter` (`:first_party_plugin_import_http_client`, `:first_party_plugin_cosign_verifier`, …) so existing config/tests apply. - **`ServiceRadarWebNG.Plugins.NativeAddonImporter.import/1`** — resolve repo + release tag → fetch `serviceradar-native-addon-index.json` → find entry → fetch + **Cosign-verify** the OCI manifest → **assert each per-arch `tarball_digest`/`signature_digest` + the `bundle_digest` is a layer of the verified manifest** and pull those blobs by digest (content-addressed) → extract `addon.yaml` + `config.schema.json` → assemble per-arch artifacts → **core `import_entry/4`** with `NativeAddonArtifactMirror.mirror_fun/3` + a `SystemActor`. Trust split: web-ng owns transport + discovery (OCI + cosign); the core owns per-arch ed25519 verification + persistence. ## Verification `mix compile --warnings-as-errors` + `mix credo --strict` clean (both modules). The core (#3476/#3477) and mirror (#3478) it builds on are unit- and DB-tested. ## Remaining (tasks.md §4) - **Migrate `FirstPartyImporter` to delegate to `ForgejoOciClient`.** The shared module is in use by the native importer; FPI still holds its own transport copies. The migration is `import ForgejoOciClient` + deleting ~50 now-duplicated `defp`s — **all-or-nothing on the import** (name/arity conflicts), so I kept it out of this PR to avoid destabilizing the working WASM path. It's a pure, test-gated dedup (FPI's test is unit-style, mocks http/cosign, no DB) — a clean focused follow-up. - **End-to-end test** of the web-ng importer (fake OCI/HTTP client serving a fixture index + bundle + per-arch blobs → scratch DB → staged `AddonPackage`), mirroring `first_party_importer_test.exs`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(web-ng): native add-on import orchestration on a shared OCI client (#3425)
Some checks failed
Secret Scan / gitleaks (pull_request) Successful in 51s
lint / lint (push) Successful in 1m53s
lint / lint (pull_request) Successful in 1m57s
Golang Tests / test-go (push) Failing after 2m20s
CI / build (pull_request) Failing after 13m59s
Elixir Quality / Elixir Quality (pull_request) Failing after 28m44s
7ce9c31414
build-signing §4.1 web-ng half. Imports a first-party native add-on from a
trusted Forgejo release into a staged AddonPackage, completing the loop with the
merged core importer (#3476) + object-storage mirror (#3478).

- ServiceRadarWebNG.Plugins.ForgejoOciClient: shared transport extracted for reuse
  (repo/release/asset fetch, OCI manifest+blob fetch with registry bearer-token +
  docker-config auth and redirect handling, Cosign verify, trusted-host/URL
  validation, digest/string utils). Importer-agnostic; same injection seams as
  FirstPartyImporter so existing config/tests apply.
- ServiceRadarWebNG.Plugins.NativeAddonImporter.import/1: resolve repo + release
  tag -> fetch serviceradar-native-addon-index.json -> find entry -> fetch +
  Cosign-verify the OCI manifest -> assert each per-arch tarball_digest/
  signature_digest + the bundle_digest is a layer of the verified manifest and pull
  those blobs by digest (content-addressed) -> extract addon.yaml + config.schema.json
  -> assemble per-arch artifacts -> core import_entry/4 with
  NativeAddonArtifactMirror.mirror_fun/3 + a SystemActor. Web-ng owns transport +
  discovery trust (OCI + cosign); the core owns per-arch ed25519 trust + persistence.

compile --warnings-as-errors + credo --strict clean (both modules).

Remaining (noted in tasks.md): (a) migrate FirstPartyImporter to delegate to
ForgejoOciClient (the shared module is in use by the native importer; FPI still
holds duplicate transport copies — a pure, test-gated dedup follow-up, all-or-
nothing on the import so kept out of this PR to not destabilize the WASM path);
(b) an end-to-end test (fake OCI/HTTP client + scratch DB -> staged AddonPackage),
mirroring first_party_importer_test.exs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
mfreeman451 left a comment

lgtm

lgtm
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
carverauto/serviceradar!3479
No description provided.