feat(core): native add-on object-storage mirror (build-signing §4.2) (#3425) #3478

Merged
mfreeman451 merged 1 commit from feat/native-addon-artifact-mirror into staging 2026-05-31 23:44:39 +00:00
Owner

What

build-signing §4.2 — the object-storage mirror that supplies the :mirror callback ServiceRadar.Plugins.NativeAddonImporter.import_entry/4 (#3476) takes.

ServiceRadar.Plugins.NativeAddonArtifactMirror.mirror_fun/3 returns (os, arch, bytes -> {:ok, object_key} | {:error, term}):

  • uploads each verified per-arch tarball to the datasvc object store via ServiceRadar.Sync.Client.upload_object (the ReleaseArtifactMirror channel pattern),
  • under a deterministic, traversal-safe key native-addons/<addon_id>/<version>/<os>/<arch>/<sha256>.tar.gz, carrying sha256 + addon/os/arch attributes,
  • and the importer records the resolved {object_key, sha256, signature} on AddonPackage.artifacts (the "os/arch" shape AgentConfigGenerator already reads back).

Tests

The upload fn is injected (the ReleaseArtifactMirror DI pattern), so the key/metadata logic is unit-tested without a channel/DB: key + sha256 + size + attributes, error propagation, and segment sanitization — slashes collapsed, all-dots segments (./..) neutralized so a crafted addon_id/version/os/arch can't add a path component or escape the native-addons/ prefix. mix test (5/0), mix compile --warnings-as-errors, and mix credo --strict clean.

Where §4 stands

  • §4.1 importer core: merged (#3476), DB-verified (#3477).
  • §4.2 object-storage mirror: this PR.
  • Remaining §4.1: the web-ng OCI-fetch orchestration wiring fetch+verify → this mirror → import_entry/4 (the last piece; mostly registry/HTTP I/O).

🤖 Generated with Claude Code

## What build-signing **§4.2** — the object-storage mirror that supplies the `:mirror` callback `ServiceRadar.Plugins.NativeAddonImporter.import_entry/4` (#3476) takes. `ServiceRadar.Plugins.NativeAddonArtifactMirror.mirror_fun/3` returns `(os, arch, bytes -> {:ok, object_key} | {:error, term})`: - uploads each verified per-arch tarball to the datasvc object store via `ServiceRadar.Sync.Client.upload_object` (the `ReleaseArtifactMirror` channel pattern), - under a **deterministic, traversal-safe** key `native-addons/<addon_id>/<version>/<os>/<arch>/<sha256>.tar.gz`, carrying `sha256` + addon/os/arch attributes, - and the importer records the resolved `{object_key, sha256, signature}` on `AddonPackage.artifacts` (the `"os/arch"` shape `AgentConfigGenerator` already reads back). ## Tests The upload fn is injected (the `ReleaseArtifactMirror` DI pattern), so the key/metadata logic is unit-tested without a channel/DB: key + sha256 + size + attributes, error propagation, and **segment sanitization** — slashes collapsed, all-dots segments (`.`/`..`) neutralized so a crafted `addon_id`/`version`/`os`/`arch` can't add a path component or escape the `native-addons/` prefix. `mix test` (5/0), `mix compile --warnings-as-errors`, and `mix credo --strict` clean. ## Where §4 stands - §4.1 importer core: merged (#3476), DB-verified (#3477). - §4.2 object-storage mirror: **this PR**. - Remaining §4.1: the **web-ng OCI-fetch orchestration** wiring fetch+verify → this mirror → `import_entry/4` (the last piece; mostly registry/HTTP I/O). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(core): native add-on object-storage mirror (build-signing §4.2) (#3425)
Some checks failed
Secret Scan / gitleaks (pull_request) Successful in 23s
Golang Tests / test-go (push) Successful in 1m29s
lint / lint (pull_request) Successful in 1m24s
lint / lint (push) Successful in 2m14s
CI / build (pull_request) Failing after 15m27s
Elixir Quality / Elixir Quality (pull_request) Failing after 21m10s
6959efdb7b
ServiceRadar.Plugins.NativeAddonArtifactMirror.mirror_fun/3 returns the
(os, arch, bytes -> {:ok, object_key}) callback NativeAddonImporter.import_entry/4
takes: it uploads each verified per-arch tarball to the datasvc object store via
ServiceRadar.Sync.Client.upload_object (the ReleaseArtifactMirror channel pattern)
under a deterministic, traversal-safe key
native-addons/<addon_id>/<version>/<os>/<arch>/<sha256>.tar.gz, carrying the
sha256 + addon/os/arch attributes. The importer records the resolved
{object_key, sha256, signature} on AddonPackage.artifacts (the shape
AgentConfigGenerator already reads).

The upload fn is injectable (mirrors the ReleaseArtifactMirror DI pattern), so the
key/metadata logic is unit-tested without a channel/DB: key + sha256 + size +
attributes, error propagation, and path-segment sanitization (slashes collapsed,
all-dots segments neutralized so a crafted addon_id/version can't add a path
component or escape the prefix). mix test (5/0) + --warnings-as-errors + credo
--strict clean.

Completes §4.2; remaining §4.1 is the web-ng OCI-fetch orchestration that wires
fetch+verify -> this mirror -> import_entry/4.

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!3478
No description provided.