9.7 KiB
HWLAB Artifact Catalog Contract
The artifact catalog is the DEV-only MVP contract for interpreting generated
deployment artifacts. It pins which HWLAB service image, commit, profile,
namespace, and health path GitOps render must inject into runtime manifests.
deploy/deploy.json stays the human-authored runtime config truth source.
This file is not automatically a CI publish record. It proves only the state it declares:
artifactState: "contract-skeleton"means the source/artifact commit and image tags are aligned, butciPublished=false,registryVerified=false, and every digest must staynot_published.artifactState: "published"is allowed only after a DEV publish report proves every required enabled service was published for the same source commit with a realsha256:<64 hex>registry digest. Services explicitly disabled in the service inventory must staynot_publishedand carry a disabled reason.
Do not infer registry existence, digest values, or deployment from commit tags. Real publish evidence must come from the publishing workflow and registry metadata, then be copied into the catalog by the refresh command below.
Scope
- Environment: DEV only.
- Namespace:
hwlab-dev. - Public DEV endpoint:
http://74.48.78.17:16667. - Profile:
dev. - Health path:
/health/live. - Artifact state: contract skeleton only.
- PROD deployment, PROD smoke, secret reads, force push, real image publish, and UniDesk runtime substitution are forbidden.
Files
| File | Role |
|---|---|
deploy/artifact-catalog.dev.json |
Machine-readable DEV artifact identity truth for generated image, digest, commit, and publish provenance fields. |
deploy/deploy.json |
Human-authored DEV runtime config such as service topology, env, health, profile, replicas, and endpoints. |
scripts/g14-gitops-render.mjs |
Declares the Tekton primitive CI tasks and minimal guardrails that generate the G14 CI/CD control plane. |
scripts/deploy-desired-state-plan.mjs |
Read-only planner/checker for catalog artifact identity, generated identity leakage into deploy config, and deploy/runtime config contracts. |
scripts/refresh-artifact-catalog.mjs |
Previews artifact catalog identity by default; only G14 Tekton promotion uses --write to update deploy/artifact-catalog.dev.json before committing generated state to G14-gitops. |
scripts/validate-artifact-catalog.mjs |
Local static validator for the catalog and deploy manifest skeleton. |
scripts/preflight-dev-base-image.mjs |
Local DEV builder base-image preflight for future artifact publish. |
docs/dev-base-image-preflight.md |
Operator contract for interpreting preflight readiness and blockers. |
Pin Rules
Every service entry in deploy/artifact-catalog.dev.json must satisfy these
rules:
| Field | Rule |
|---|---|
serviceId |
Must be one of the frozen HWLAB service IDs and must appear exactly once. |
commitId |
Must match the top-level catalog commit ID. Short or full lowercase Git SHA is allowed. |
image |
Must match the DEV registry target <registry>/<namespace>/<serviceId>:<imageTag>. The matching field must not be copied into deploy/deploy.json. |
imageTag |
Must be the first seven characters of commitId. Mutable tags such as latest, dev, or main are forbidden. |
profile |
Must be dev. |
namespace |
Must be hwlab-dev. |
healthPath |
Must be /health/live and match the DEV health contract. |
publishState |
Must be skeleton-only in a blocked skeleton catalog, or published only when the catalog was refreshed from a successful publish report. |
sourceState |
Must be source-present for MVP services with repository source, or intentionally-disabled for zero-replica services excluded from MVP publication. |
artifactRequired |
Must match serviceInventory.requiredServiceIds; only required services need publish digests. |
artifactScope |
required for services that must be published, or disabled with a notPublishedReason. |
digest |
Must be not_published in the skeleton catalog; it may be a registry sha256:<64 hex> digest only after publish evidence exists. |
The catalog commitId is the artifact source commit, not proof that a registry
artifact exists. It must match every service commitId and the image tag. If a
later target ref changes artifact build inputs after the
publish source, the DEV gate preflight may reopen artifact-source-commit even
when the base-image blocker is already closed.
Desired-State Plan
Use the read-only planner before refreshing or reviewing deploy desired-state:
node scripts/deploy-desired-state-plan.mjs --plan --pretty
node scripts/deploy-desired-state-plan.mjs --check
node scripts/deploy-desired-state-plan.mjs --target-ref origin/G14 --pretty
node scripts/deploy-desired-state-plan.mjs --target-tag <tag> --pretty
node scripts/deploy-desired-state-plan.mjs --promotion-commit <sha> --check
The planner treats deploy/deploy.json as human-authored runtime config,
deploy/artifact-catalog.dev.json as artifact identity truth, and
deploy/k8s/base/workloads.yaml as a runtime template. It reports catalog
service commitId/image/imageTag, blocks generated artifact identity that
leaks into deploy.json, and leaves workload image/env mirror values to GitOps
render because render overwrites them from the catalog.
--check exits non-zero when the source files are missing or invalid, generated
artifact identity leaks into deploy.json, an explicit target tag is invalid or
mutable, or catalog artifact identity does not match the requested target. The
source branch catalog is only a seed contract; published artifact identity is
stored on G14-gitops. The optional report snapshot is contextual evidence only
and is not an authoritative desired-state source.
For PR review or CI/CD promotion handoff, use --promotion-commit <sha> --check. That mode is stricter than a --target-ref plan: the catalog
top-level commit and each catalog service commit/image tag must align with the
promotion commit/tag. A stale but internally consistent catalog is a blocker in
promotion mode because applying it would roll DEV back.
The planner does not prove registry existence, publish success, DEV apply, or
M3 DEV-LIVE. Only real DEV observation of
res_boxsimu_1:DO1 -> hwlab-patch-panel -> res_boxsimu_2:DI1 with operation,
trace, audit, and evidence records can be called M3 DEV-LIVE.
Refresh Boundary
Human source work must not refresh artifact identity into the source branch. To preview what a blocked catalog would look like, use read-only mode:
node scripts/refresh-artifact-catalog.mjs --target-ref HEAD --blocked --no-write
node scripts/deploy-desired-state-plan.mjs --check
This prints the planned catalog state and does not modify any repository file. Blocked skeleton refresh is intentionally preview-only.
After a successful DEV artifact publish, only the G14 Tekton promotion path may record digests from the publish report:
node scripts/refresh-artifact-catalog.mjs --target-ref <source-sha> --publish-report /workspace/source/dev-artifacts.json --write
The publish-report mode refuses to update the catalog unless the report says
artifactPublish.status="published", covers every frozen service in the v2
publish plan, matches the target source commit, and contains a valid sha256
digest for each required service. Disabled services remain skeleton-only with
digest: "not_published". The written catalog is committed only to
G14-gitops; deploy/deploy.json remains human-authored source truth.
Relationship To deploy/deploy.json
deploy/deploy.json remains the human-authored deploy manifest. The artifact
catalog does not replace it and must not be consumed as proof that a release was
built. GitOps render combines human config from deploy.json with generated
artifact identity from the catalog; artifact identity must not be copied back
into deploy.json.
If a future CI workflow publishes real images, it should update or generate a publish result that includes registry digests and provenance. That publish result may be compared with this contract, but it must not be inferred from this contract.
DEV Builder Preflight
Before a future DEV artifact publish attempts to build or publish service images, run:
npm run --silent dev-base-image:preflight
The preflight is local-only and checks for an approved builder base image through
HWLAB_DEV_BASE_IMAGE, a local node:20-* Docker image, or an explicit local
HWLAB dev base tag such as hwlab-dev-base:<tag>. It prints the image source,
local tag, image ID, publish usability, blockers, next steps, and
machine-readable preload/provision commands. The recommended source is
node:20-bookworm-slim; the recommended HWLAB-local tag is
127.0.0.1:5000/hwlab/hwlab-dev-base:node20-bookworm-slim. A blocked result
means artifact publish must stop and must not be reported as a successful
publish.
Validation
Run the local static validator:
node --check scripts/deploy-desired-state-plan.mjs
node --check scripts/src/deploy-desired-state-plan.mjs
node --test scripts/deploy-desired-state-plan.test.mjs
node scripts/deploy-desired-state-plan.mjs --check
node --check scripts/validate-artifact-catalog.mjs
node --check scripts/refresh-artifact-catalog.mjs
node --check scripts/preflight-dev-base-image.mjs
node --check scripts/src/dev-base-image-preflight.mjs
node scripts/validate-artifact-catalog.mjs
The validator and refresh command read local repository files and optional
publish reports; refresh is read-only unless --write is explicitly supplied.
The desired-state planner has the same read-only boundary.
These commands do not contact a registry, read secrets, build images, push
images, deploy to DEV, or deploy to PROD.