contribute-workbench-image ยท diff
git:20260819.47e5c70 to git:20260823.224d9da
59 added, 173 removed. Audit A to A.
---
name: contribute-workbench-image
- description: Use when an external contributor or maintainer adds or changes an NPA workbench container image and must carry it safely from a fork pull request through licensing review, trusted build, private source-registry push, live validation, and incremental GHCR publication.
+ description: Use when an external contributor or maintainer adds or changes an NPA workbench image and must carry it through licensing review, trusted public-dev build, real validation, and digest-identical GHCR release promotion.
---
# Contribute A Workbench Image
- Keep source contribution, trusted building, and public publication as separate
- approval boundaries. Let anyone propose reproducible image code. Let only a
- maintainer run reviewed code with registry access, and let an authorized human
- make the irreversible public-release decision.
+ Keep source contribution, trusted building, and supported release promotion as
+ separate approval boundaries. Public development pushes are irreversible public
+ disclosures even when their tags are later deleted.
- ## Load The Governing Rules
+ ## Governing Rules
- Read these before changing an image:
+ Before acting, read:
- - `docs/workbench/contributing-a-containerized-solution.md`
- - `docs/workbench/container-packaging.md`
+ - `skills/atomic/audit-container-docs/SKILL.md`
+ - `skills/atomic/secure-image-build/SKILL.md`
- `skills/atomic/solution-licensing/SKILL.md`
+ - `skills/atomic/third-party-eula-preflight/SKILL.md`
- `skills/atomic/build-and-push-image/SKILL.md`
- - `skills/atomic/audit-container-docs/SKILL.md`
- `skills/atomic/testing-conventions/SKILL.md`
-
- Use `npa/.venv/bin/python` for repository validation. Keep tenant, project,
- registry, bucket, service-account, key, IP, and secret values out of committed
- files. Preserve unrelated dirty-tree changes.
-
- ## Choose The Role
-
- ### External contributor
-
- Prepare code and evidence in a fork. Do not request, receive, or use the
- official registry credentials. An optional candidate image may live in the
- contributor's own registry, but maintainers must rebuild the official artifact
- from reviewed repository source.
-
- ### Maintainer
-
- Review the fork with unprivileged CI, merge or reproduce the reviewed commit on
- a maintainer-owned branch, build the exact trusted commit, validate the pushed
- bytes, and publish only after explicit authorization.
-
- Never check out or execute untrusted fork code in a privileged
- `pull_request_target` or `workflow_run` job. Never expose registry credentials
- to a fork PR, a contributor-controlled action, or a build step that requires a
- secret. Public-image builds must need no build-time application credential;
- gated runtimes, weights, and data belong in an operator-authorized runtime
- fetch.
-
- ## Prepare The Contribution
-
- 1. Fork the repository and branch from current `origin/main`.
- 2. Use a new, additive tag. Do not reuse or overwrite a released public tag.
- 3. Build from checked-in source under `npa/docker/workbench/<tool>/`; do not
- make a detached Dockerfile or an image that can only be reconstructed from a
- developer machine.
- 4. Add or update the applicable surfaces:
-
- - `Dockerfile` and, when useful, `build.sh`
- - `npa/docker/workbench/packaging-contract.yaml`
- - `npa/src/npa/deploy/images.py` and the supported version source
- - CLI, SDK, and `npa.workflow` image resolution when behavior changes
- - golden evaluation, focused tests, human documentation, and the relevant
- tool skill
-
- Before finalizing the contribution, use
- `skills/atomic/audit-container-docs/SKILL.md` to reconcile
- `docs/workbench/container-image-catalog.md`. Add a public table row only when
- the image is actually selected for the public mirror and anonymously
- pullable; otherwise verify and document why it remains outside the table.
-
- 5. Make the final stage non-root, pin resolvable bases by digest, keep secrets
- out of layers, and make service health behavior machine-checkable.
- 6. Classify the source, baked runtime, and weights/data separately. Record
- `redistribution: public` only when every shipped component may be handed to
- third parties. Record ambiguity and stop for human review; never weaken a
- guard or relabel an artifact merely to make publication pass.
- 7. Keep gated weights, datasets, and proprietary SDKs out of layers. Fetch them
- at runtime using the operator's own credential and acceptance when that
- design is legally valid. Test any refusal or acceptance gate as product
- behavior.
-
- ## Validate The Pull Request
+ - `docs/workbench/container-packaging.md`
+ - `docs/workbench/container-image-catalog.md`
+ - `docs/workbench/contributing-a-containerized-solution.md`
- Create the repository virtualenv if needed, then run focused checks before the
- full non-live suite:
+ Use `npa/.venv/bin/python`. Keep live infrastructure identifiers, credentials,
+ and customer data out of commits, workflow inputs, logs, and PR prose.
- ```bash
- python3 -m venv npa/.venv
- npa/.venv/bin/pip install -e "npa[dev]"
- npa/.venv/bin/python -m pytest \
- npa/tests/docker/ npa/tests/deploy/ \
- npa/tests/guardrails/test_skills_index.py -q
- make test PYTHON=npa/.venv/bin/python
- make lint PYTHON=npa/.venv/bin/python
- ```
+ ## Contributor Boundary
- Build locally without credentials when practical. For a runtime-fetch image,
- test both refusal without acceptance/credentials and success with the
- operator-supplied runtime inputs. Add committed live-infrastructure coverage
- for a new or changed workflow/tool path, following `testing-conventions`.
+ An external contributor supplies reproducible code and evidence in an
+ unprivileged fork. Never expose official package credentials to fork-controlled
+ code or run untrusted code in privileged `pull_request_target`/`workflow_run`
+ jobs. Maintainers rebuild the reviewed commit through the repository workflow.
- Open the fork PR against `main`. Include:
+ Add or update the Dockerfile/build script, packaging contract, image resolver
+ and version source, CLI/SDK/workflow surfaces, golden evaluation, tests, docs,
+ and relevant skill together. Use non-root final stages, digest-pinned bases when
+ resolvable, and runtime fetch for gated or non-redistributable material.
- - exact image name and proposed tag;
- - base image and digest;
- - expected architecture and approximate size;
- - build-time credential statement;
- - source, runtime, weights, and data license evidence;
- - packaging tier and redistribution class;
- - unit, image, and live functional results; and
- - known vulnerabilities or residual release risks.
+ Classify source, baked runtime, weights, data, caches, and outputs separately.
+ Only `redistribution: public` images may enter official GHCR. Restricted images
+ remain build-your-own in an operator registry.
- ## Build The Trusted Artifact
+ ## Trusted Public Development Build
- After review, build from the exact trusted commit. Prefer the checked-in
- `build.sh`; otherwise use `docker buildx build --push` so a large image streams
- to the configured private source registry rather than unpacking into the local
- daemon. Resolve the registry from NPA configuration and pass it as an argument;
- do not commit its concrete identifier.
+ After review, build the exact trusted full SHA with the manual
+ `publish-public-images.yml` workflow on a ref whose code contains that workflow:
```bash
- npa/docker/workbench/<tool>/build.sh \
- --registry "$NPA_REGISTRY" \
- --tag <new-tag> \
- --push
-
- crane manifest "$NPA_REGISTRY/npa-<tool>:<new-tag>" >/dev/null
+ gh workflow run publish-public-images.yml \
+ --ref <reviewed-branch> \
+ -f dry_run=true \
+ -f development_sha=<full-git-sha> \
+ -f build_development_tools=<tool> \
+ -f tool=<tool>
```
- If the checked-in script has different flags, use its help rather than
- inventing an alternate build path. Match the pushed name and tag exactly to the
- pin resolved by `npa.deploy.images`.
-
- Inspect the registry artifact, not only the Dockerfile or local daemon:
-
- - run the appropriate Trivy/SBOM and layer-history checks;
- - scan the full filesystem for payloads whose absence is part of the license
- decision;
- - confirm non-root runtime and absence of credentials, caches, weights, and
- checkpoints;
- - run the real capability test on the intended CPU/GPU architecture; and
- - record the immutable manifest digest and exact source commit.
-
- Never publish a `restricted` image. A successful build is not evidence that
- redistribution is permitted.
+ The workflow must finish all pre-publication gates before it pushes
+ `ghcr.io/nebius/nebius-physical-ai/npa-<tool>:dev-<full-git-sha>`. It must not
+ attach a bootstrap/attestation label unless it actually proved the declared
+ contract. After push, record the digest and prove anonymous pullability.
- ## Verify Source And Public State
+ Inspect the registry artifact rather than trusting the Dockerfile: layers,
+ history, OCI config, SBOM/provenance attestations, vulnerabilities, secrets,
+ licenses, non-root user, credentials, caches, checkpoints, customer data, live
+ infrastructure data, and tool-specific restricted-payload scans must all pass.
- Do not infer current coverage from the number of GHCR package pages. A package
- may be public while the repository's newly pinned tag is absent.
+ ## Functional And Release Gates
- Set `NPA_PUBLIC_REGISTRY` to the intended public target before either check.
- The explicit `--target` arguments below avoid silently validating a different
- configured registry.
+ Run the smallest real capability on the intended physical GPU from the exact
+ public development digest. Imports, startup, and CUDA availability are not
+ functional evidence. Preserve redacted hardware, digest, command, exit status,
+ and output-artifact measurements.
- Check every pinned source tag with the configured read credential:
+ Promote only that validated digest:
```bash
- : "${NPA_PUBLIC_REGISTRY:?set NPA_PUBLIC_REGISTRY to the intended public registry}"
- unset NEBIUS_IAM_TOKEN NPA_NEBIUS_IAM_TOKEN
- npa/scripts/nebius_registry_docker_login.sh
npa/.venv/bin/python -m npa.deploy.publish_public \
- --target "$NPA_PUBLIC_REGISTRY" --preflight
- ```
-
- Check every exact target tag through the anonymous path:
-
- ```bash
+ --target ghcr.io/nebius/nebius-physical-ai \
+ --development-sha <full-git-sha> --dry-run
npa/.venv/bin/python -m npa.deploy.publish_public \
- --target "$NPA_PUBLIC_REGISTRY" --verify-public
+ --target ghcr.io/nebius/nebius-physical-ai \
+ --development-sha <full-git-sha>
```
- Interpret the results precisely:
-
- - source missing: build/push the pinned tag or correct the pin;
- - source present and target HTTP 404: the tag still needs mirroring;
- - both present with equal `crane digest` output: current and complete;
- - both present with different digests: stop and investigate tag reuse or an
- unintended rebuild before copying anything; and
- - source denial: fix identity or permissions; never treat it as a missing
- image.
-
- ## Publish Incrementally
-
- Public publication is an explicit human decision. Do not dispatch it, change a
- package's visibility, or accept a release risk without authorization for the
- exact plan.
-
- 1. Run **Publish public images** on `main` with `dry_run=true` and
- `skip_missing=false`.
- 2. Review the plan, source preflight, license gates, and exact pins.
- 3. After authorization, run it once with `dry_run=false`.
- 4. Confirm the summary says every planned image is anonymously pullable.
-
- The publisher compares manifest digests and skips unchanged images. It does not
- republish the entire mirror. A new tag in an existing package inherits that
- package's public visibility. A completely new package is private after its
- first push and needs one manual **Danger Zone -> Change visibility -> Public**
- operation by an administrator, followed by verification. Treat that change as
- irreversible.
+ Verify the supported tag anonymously and require it to resolve to the same
+ digest. On failure, delete only an exact run-owned development tag/version after
+ matching package, tag, and digest; deletion cannot revoke earlier downloads.
## Completion Evidence
- Report the PR and merge commit, source and GHCR digests, scan results, real
- functional-test result, publication run URL, and anonymous verification count.
- State missing or mismatched tags explicitly. Clean up temporary credentials,
- builders, worktrees, and scratch files after preserving the evidence needed in
- the PR.
+ Report the reviewed commit, public development reference/digest, gate summaries,
+ real capability result, release reference/digest when promoted, anonymous pull
+ checks, and exact cleanup. Mark untested capability or release claims deferred.