192 lines
9.6 KiB
Markdown
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.
|