Files
pikasTech-HWLAB/docs/artifact-catalog.md
T
2026-05-22 15:23:52 +00:00

192 lines
9.6 KiB
Markdown

# HWLAB Artifact Catalog Contract
The artifact catalog is the DEV-only MVP contract for interpreting deployment
artifacts. It pins which HWLAB service image, commit, profile, namespace, and
health path a static deploy manifest is claiming for acceptance review.
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, but `ciPublished=false`, `registryVerified=false`, and every
digest must stay `not_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
real `sha256:<64 hex>` registry digest. Services explicitly disabled in the
service inventory must stay `not_published` and 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 catalog sample and static source of truth for the skeleton. |
| `deploy/deploy.json` | DEV deploy manifest skeleton that the catalog explains. |
| `CI.json` | Lightweight command and forbidden-action skeleton. |
| `scripts/deploy-desired-state-plan.mjs` | Read-only planner/checker for commit, image tag, workload image, and env mirror convergence across deploy desired-state files. |
| `scripts/refresh-artifact-catalog.mjs` | Refreshes source/artifact commit tags and records either blocked `not_published` state or proven publish digests. |
| `scripts/validate-artifact-catalog.mjs` | Local static validator for the catalog, deploy manifest, and CI forbidden list. |
| `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 catalog and `deploy/deploy.json` commit ID. Short or full lowercase Git SHA is allowed. |
| `image` | Must match the DEV registry target `<registry>/<namespace>/<serviceId>:<imageTag>` and the matching `deploy/deploy.json` service image. |
| `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 `deploy/deploy.json`, 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:
```sh
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/main --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`,
`deploy/artifact-catalog.dev.json`, and `deploy/k8s/base/workloads.yaml` as the
authoritative source desired-state. It reports top-level commit IDs, catalog
service `commitId`/`image`/`imageTag`, deploy service image tags, workload
images, and present env mirrors including `HWLAB_COMMIT_ID`, `HWLAB_IMAGE`,
`HWLAB_IMAGE_TAG`, and `HWLAB_SKILLS_COMMIT_ID`.
`--check` exits non-zero only when the source files are missing or invalid, the
desired-state has internal partial drift, an explicit target tag is invalid or
mutable, or some authoritative fields already point at a target while others do
not. A uniform older state under `--target-ref` is a promotion review plan, not a
failure. 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: every top-level
commit, catalog service commit, deploy service image tag, workload image tag,
and present mirror env (`HWLAB_COMMIT_ID`, `HWLAB_IMAGE`,
`HWLAB_IMAGE_TAG`, `HWLAB_SKILLS_COMMIT_ID`, `HWLAB_IMAGE_DIGEST`) must align
with the promotion commit/tag. A stale but internally consistent manifest 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 Workflow
When the source commit changes and no publish report proves digests, refresh the
catalog and deploy manifests in blocked mode:
```sh
node scripts/refresh-artifact-catalog.mjs --target-ref origin/main --blocked
node scripts/deploy-desired-state-plan.mjs --promotion-commit $(git rev-parse --short=7 origin/main) --check
```
This updates `deploy/deploy.json`, `deploy/artifact-catalog.dev.json`, and
`deploy/k8s/base/workloads.yaml` to the selected commit tag. It keeps
`artifactState: "contract-skeleton"`, `ciPublished=false`,
`registryVerified=false`, and every service digest as `not_published`.
After a successful DEV artifact publish, record digests only from the publish
report:
```sh
node scripts/refresh-artifact-catalog.mjs --target-ref origin/main --publish-report reports/dev-gate/dev-artifacts.json
node scripts/deploy-desired-state-plan.mjs --promotion-commit $(git rev-parse --short=7 origin/main) --check
```
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"`.
## Relationship To `deploy/deploy.json`
`deploy/deploy.json` remains the deploy manifest skeleton. The artifact catalog
does not replace it and must not be consumed as proof that a release was built.
The catalog explains the artifact identity that `deploy/deploy.json` currently
claims, then adds stricter DEV-only rules around commit pinning, image tags,
health paths, forbidden profiles, and publish state.
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:
```sh
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:
```sh
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 only local repository files and optional
publish reports. 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.