feat(core): native add-on importer verify-then-persist core (#3425) #3476

Merged
mfreeman451 merged 1 commit from feat/native-addon-importer into staging 2026-05-31 22:03:12 +00:00
Owner

What

The verify-then-persist core of the native add-on control-plane importer (build-signing §4.1/4.2). ServiceRadar.Plugins.NativeAddonImporter (serviceradar_core) turns a verified serviceradar-native-addon-index.json entry + the add-on's addon.yaml manifest into a staged AddonPackage whose per-arch artifacts map is exactly what AgentConfigGenerator.select_addon_artifact/3 already reads ("os/arch" => {object_key, sha256, signature}).

Per architecture it:

  1. checks the tarball sha256,
  2. verifies the raw ed25519 signature over the tarball bytes against the agent release public key — the agent's exact verifyAddonArtifactSignature check, with the same hex/base64 decode parity, so a tarball the control plane accepts is one the agent will accept,
  3. mirrors via an injected :mirror function,

then maps the manifest → AddonPackage create attrs (kind/delivery/supervision → atoms, fail-closed on unknown enums; binary/install_path/capabilities/requires; source oci ref/digest/release tag) and creates a staged package via an injected actor (a SystemActor for background callers — never authorize?: false, per serviceradar_core/CLAUDE.md).

Why injected deps

The OCI fetch, Cosign verify, and object-storage upload are injected so the verification + persistence logic is unit-testable without a registry or DB — mirroring the ReleaseArtifactMirror DI pattern.

Tests

test/serviceradar/plugins/native_addon_importer_test.exs (no DB): valid-sig (hex + base64) / tampered / wrong-key / malformed-sig; sha256 match/mismatch; decode encodings; per-arch verify+mirror map and fail-closed-never-mirror; attrs mapping + unknown-delivery rejection + install_path default. mix test green (11 tests); mix compile --warnings-as-errors + mix credo --strict clean.

Remaining (tasks.md §4, noted)

  • web-ng OCI-fetch orchestration: fetch the index from the trusted release, bounded-fetch the bundle, Cosign-verify the OCI digest (reuse CosignVerifier), parse the bundle's addon.yaml + config.schema.json, assemble the per-arch fetched artifacts, and call import_entry/4.
  • default object-storage mirror: ServiceRadar.Sync.Client.upload_object (object key native-addons/<addon_id>/<version>/<os>-<arch>/<sha256>-<file>), mirroring ReleaseArtifactMirror.
  • Then onboarding/Edge-Ops can seed + approve the imported AddonPackage.

🤖 Generated with Claude Code

## What The **verify-then-persist core** of the native add-on control-plane importer (build-signing §4.1/4.2). `ServiceRadar.Plugins.NativeAddonImporter` (serviceradar_core) turns a verified `serviceradar-native-addon-index.json` entry + the add-on's `addon.yaml` manifest into a **staged `AddonPackage`** whose per-arch `artifacts` map is exactly what `AgentConfigGenerator.select_addon_artifact/3` already reads (`"os/arch" => {object_key, sha256, signature}`). Per architecture it: 1. checks the tarball `sha256`, 2. **verifies the raw ed25519 signature over the tarball bytes against the agent release public key** — the agent's exact `verifyAddonArtifactSignature` check, with the same hex/base64 decode parity, so a tarball the control plane accepts is one the agent will accept, 3. mirrors via an injected `:mirror` function, then maps the manifest → `AddonPackage` create attrs (kind/delivery/supervision → atoms, **fail-closed** on unknown enums; binary/install_path/capabilities/requires; source oci ref/digest/release tag) and creates a **staged** package via an injected actor (a `SystemActor` for background callers — never `authorize?: false`, per `serviceradar_core/CLAUDE.md`). ## Why injected deps The OCI fetch, Cosign verify, and object-storage upload are **injected** so the verification + persistence logic is unit-testable without a registry or DB — mirroring the `ReleaseArtifactMirror` DI pattern. ## Tests `test/serviceradar/plugins/native_addon_importer_test.exs` (no DB): valid-sig (hex + base64) / tampered / wrong-key / malformed-sig; sha256 match/mismatch; decode encodings; per-arch verify+mirror map **and fail-closed-never-mirror**; attrs mapping + unknown-delivery rejection + install_path default. **`mix test` green (11 tests); `mix compile --warnings-as-errors` + `mix credo --strict` clean.** ## Remaining (tasks.md §4, noted) - **web-ng OCI-fetch orchestration**: fetch the index from the trusted release, bounded-fetch the bundle, Cosign-verify the OCI digest (reuse `CosignVerifier`), parse the bundle's `addon.yaml` + `config.schema.json`, assemble the per-arch fetched artifacts, and call `import_entry/4`. - **default object-storage mirror**: `ServiceRadar.Sync.Client.upload_object` (object key `native-addons/<addon_id>/<version>/<os>-<arch>/<sha256>-<file>`), mirroring `ReleaseArtifactMirror`. - Then onboarding/Edge-Ops can seed + approve the imported `AddonPackage`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(core): native add-on importer verify-then-persist core (#3425)
Some checks failed
lint / lint (push) Successful in 1m12s
Secret Scan / gitleaks (pull_request) Successful in 44s
lint / lint (pull_request) Successful in 1m46s
Golang Tests / test-go (push) Successful in 2m30s
CI / build (pull_request) Failing after 14m33s
Elixir Quality / Elixir Quality (pull_request) Failing after 22m26s
2cb70e402e
build-signing §4.1/4.2 core. ServiceRadar.Plugins.NativeAddonImporter consumes a
verified native-addon index entry + the add-on's addon.yaml manifest and produces a
staged AddonPackage whose per-arch `artifacts` map AgentConfigGenerator already reads
(keyed "os/arch" -> {object_key, sha256, signature}).

Per architecture it: checks the tarball sha256, verifies the raw ed25519 signature
over the tarball bytes against the agent release public key (the agent's exact
verifyAddonArtifactSignature check, with the same hex/base64 decode parity so a
tarball the control plane accepts is one the agent accepts), then mirrors via an
injected mirror fn. It maps the manifest (kind/delivery/supervision -> atoms,
fail-closed on unknown enums; binary/install_path/capabilities/requires; source
oci ref/digest/release tag) to AddonPackage create attrs and creates a staged
package via an injected actor (a SystemActor for background callers; never
authorize?: false).

The OCI fetch + Cosign verify + object-storage upload are injected so the
verification + persistence logic is unit-tested without a registry or DB:
verify/tamper/wrong-key/malformed-sig, sha256 match/mismatch, hex+base64 decode,
per-arch verify+mirror map (+ fail-closed-never-mirror), and the attrs mapping.
mix test green; mix compile --warnings-as-errors + credo --strict clean.

Remaining (tasks.md §4): the web-ng OCI-fetch orchestration (fetch index from the
trusted release, bounded-fetch + Cosign-verify the bundle, parse addon.yaml +
config.schema.json, call import_entry/4) and the default object-storage mirror impl
(ServiceRadar.Sync.Client.upload_object, ReleaseArtifactMirror pattern).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
mfreeman451 deleted branch feat/native-addon-importer 2026-05-31 22:03:17 +00:00
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!3476
No description provided.