2026-09-02 00:52:04 +02:00
|
|
|
# Deployment gates
|
|
|
|
|
|
2026-09-14 01:08:50 +02:00
|
|
|
The StatefulSet is deployed as of 2026-09-14. The metadata receipt is
|
|
|
|
|
`docs/evidence/2026-09-14-approval-engine-deployment.json`. SQLite is intentionally limited to one replica, `ReadWriteOnce`
|
Reconcile the release record; guard the image pin with tests
The publication at b51d174 pinned the manifest and appended a note, but left
three documents asserting the opposite. docs/image-scan-2026-09-06.md said "It
has not been pushed" in its Outcome block at the top while recording the
successful push at the bottom; its "Release status" section still said no
release digest existed and the manifest carried REPLACE_WITH_RELEASE_DIGEST;
and deploy/README.md still instructed an operator to replace a placeholder that
is now a real digest -- an instruction to undo the pin.
This is the derived-artifact staleness this repo argued for a rule about in
v0.8 §12 and then produced in its own release evidence, in the file another
repository would read to confirm what shipped. Superseded sections are now
marked in place with what replaced them rather than deleted, since they record
why the base changed and why the release was held. The scan doc carries a
status marker naming which parts state current state, including that a clean
scan is point-in-time and ages as advisories are published.
The workplan gains the publication entry it never got, and a re-check of T03's
full acceptance: a published image reads like a finished task, but the digest
was one of five requirements. Nothing is deployed -- the namespace is empty and
no secrets exist -- and production serve refuses to start without authenticated
audit delivery, so a rollout today would fail closed and prove nothing. T03
stays wait on T01's registrations and the audit credential.
Also corrects an earlier caution in the workplan that the digest was "a local
image id, not a release digest". That was wrong: with the containerd/OCI store
the build id is the manifest digest, and the registry resolves it.
tests/test_deploy_manifest.py holds the pin mechanically instead of by review:
both image references exist, are digest-pinned rather than tagged, are
identical, and no placeholder remains. The identity check matters because the
init container migrates the database the server then serves -- two different
digests there is a split-brain migration. Verified the guard fails on the drift
it targets, not only that it passes today. 116 tests pass.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PM5HnEAhokxdfcPqBNpT7D
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 715850@bnt-lap001
Assistant-Session: eb557e93-7cb1-45d0-9e57-7d15b3edc60e
2026-09-07 09:04:34 +02:00
|
|
|
storage, and an `OnDelete` update: never start two writers against a copied
|
|
|
|
|
database.
|
|
|
|
|
|
2026-09-14 01:08:50 +02:00
|
|
|
**Image: pinned, published and deployed.** Both `image:` references carry
|
2026-09-10 19:35:05 +02:00
|
|
|
`sha256:251941a5cb2724b57cc32cff6b693b1ab0be695bee4f56f02d51961189c0fa49`
|
|
|
|
|
(registry tag `0.1.0-hfact-be1a388`, source `be1a388`). Both references MUST stay
|
|
|
|
|
identical immutable digests: migration and server share one database.
|
Reconcile the release record; guard the image pin with tests
The publication at b51d174 pinned the manifest and appended a note, but left
three documents asserting the opposite. docs/image-scan-2026-09-06.md said "It
has not been pushed" in its Outcome block at the top while recording the
successful push at the bottom; its "Release status" section still said no
release digest existed and the manifest carried REPLACE_WITH_RELEASE_DIGEST;
and deploy/README.md still instructed an operator to replace a placeholder that
is now a real digest -- an instruction to undo the pin.
This is the derived-artifact staleness this repo argued for a rule about in
v0.8 §12 and then produced in its own release evidence, in the file another
repository would read to confirm what shipped. Superseded sections are now
marked in place with what replaced them rather than deleted, since they record
why the base changed and why the release was held. The scan doc carries a
status marker naming which parts state current state, including that a clean
scan is point-in-time and ages as advisories are published.
The workplan gains the publication entry it never got, and a re-check of T03's
full acceptance: a published image reads like a finished task, but the digest
was one of five requirements. Nothing is deployed -- the namespace is empty and
no secrets exist -- and production serve refuses to start without authenticated
audit delivery, so a rollout today would fail closed and prove nothing. T03
stays wait on T01's registrations and the audit credential.
Also corrects an earlier caution in the workplan that the digest was "a local
image id, not a release digest". That was wrong: with the containerd/OCI store
the build id is the manifest digest, and the registry resolves it.
tests/test_deploy_manifest.py holds the pin mechanically instead of by review:
both image references exist, are digest-pinned rather than tagged, are
identical, and no placeholder remains. The identity check matters because the
init container migrates the database the server then serves -- two different
digests there is a split-brain migration. Verified the guard fails on the drift
it targets, not only that it passes today. 116 tests pass.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PM5HnEAhokxdfcPqBNpT7D
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 715850@bnt-lap001
Assistant-Session: eb557e93-7cb1-45d0-9e57-7d15b3edc60e
2026-09-07 09:04:34 +02:00
|
|
|
|
2026-09-10 19:35:05 +02:00
|
|
|
The new artifact carries `LATEST_SCHEMA_VERSION = 5`, matching this source:
|
|
|
|
|
`entries.principal_type` and explicit `approvals.human_control`. Its release scan
|
|
|
|
|
found zero HIGH/CRITICAL vulnerabilities. Disposable on-disk v4-to-v5 migration,
|
|
|
|
|
negative service/agent binding, human binding/consumption and restart persistence
|
|
|
|
|
passed inside the non-root container with no network and a read-only root.
|
|
|
|
|
See [the image evidence](../docs/evidence/2026-09-10-human-control-image.json).
|
|
|
|
|
This is artifact evidence; native identity, audit delivery and production restore
|
|
|
|
|
remain deployment gates. Never roll the old v3 image over a v5 database; use the
|
|
|
|
|
matching verified pre-migration backup for rollback.
|
2026-09-09 14:38:21 +02:00
|
|
|
|
2026-09-14 01:08:50 +02:00
|
|
|
The existing KeyCape consumer registration and CCR-2026-0021 audit projection
|
|
|
|
|
were already verified by their owners. Live inspection confirmed the projection
|
|
|
|
|
Ready, exact key name, receiver c82e0442 and existing producer ingress; custody
|
|
|
|
|
was reused without reading or rotating its value. Added the exact namespace AND
|
|
|
|
|
pod-label ingress to KeyCape for JWKS (`deploy/keycape-ingress.yaml`).
|
2026-09-02 00:52:04 +02:00
|
|
|
|
2026-09-14 01:08:50 +02:00
|
|
|
The pod requests 25m CPU/64Mi with unchanged 500m/256Mi limits: the node had
|
|
|
|
|
3975m of its 4000m CPU reserved, so the prior 50m request could not schedule.
|
|
|
|
|
Initial native observation was 1m CPU/20Mi. No other workload was resized.
|
|
|
|
|
Kubernetes token automount is disabled; the service uses no Kubernetes API.
|
|
|
|
|
|
|
|
|
|
The live service passed schema-v5 integrity, current JWKS reachability, anonymous
|
|
|
|
|
and invalid-bearer 401, first heartbeat delivery with zero pending outbox,
|
|
|
|
|
pod replacement with unchanged persisted outbox, verified online backup and an
|
|
|
|
|
isolated restore opened by the actual engine. An independent 0600 backup copy
|
|
|
|
|
was inspected locally. No live database was overwritten. The initial backup
|
|
|
|
|
copies are test evidence, not a long-term backup schedule or disaster-recovery
|
|
|
|
|
acceptance. Capacity and independent retention remain operational follow-up.
|
|
|
|
|
|
|
|
|
|
The real PEP adoption is still T05: CCR-2026-0019's operator group/reader,
|
|
|
|
|
requesting identity and real human approval are not supplied by deployment.
|
|
|
|
|
|
|
|
|
|
For a future reinstall or release:
|
2026-09-02 00:52:04 +02:00
|
|
|
|
|
|
|
|
1. Register the exact `approval-engine` audience, caller scopes, and service
|
|
|
|
|
clients in KeyCape. Confirm the in-cluster JWKS endpoint and configured
|
|
|
|
|
issuer match the manifest.
|
|
|
|
|
2. Register `approval-engine` as an audit-core sender, add matching audit-core
|
|
|
|
|
ingress, and provision `approval-engine-audit` through the credential owner.
|
|
|
|
|
The Secret must contain key `audit-token`; never commit its value.
|
Reconcile the release record; guard the image pin with tests
The publication at b51d174 pinned the manifest and appended a note, but left
three documents asserting the opposite. docs/image-scan-2026-09-06.md said "It
has not been pushed" in its Outcome block at the top while recording the
successful push at the bottom; its "Release status" section still said no
release digest existed and the manifest carried REPLACE_WITH_RELEASE_DIGEST;
and deploy/README.md still instructed an operator to replace a placeholder that
is now a real digest -- an instruction to undo the pin.
This is the derived-artifact staleness this repo argued for a rule about in
v0.8 §12 and then produced in its own release evidence, in the file another
repository would read to confirm what shipped. Superseded sections are now
marked in place with what replaced them rather than deleted, since they record
why the base changed and why the release was held. The scan doc carries a
status marker naming which parts state current state, including that a clean
scan is point-in-time and ages as advisories are published.
The workplan gains the publication entry it never got, and a re-check of T03's
full acceptance: a published image reads like a finished task, but the digest
was one of five requirements. Nothing is deployed -- the namespace is empty and
no secrets exist -- and production serve refuses to start without authenticated
audit delivery, so a rollout today would fail closed and prove nothing. T03
stays wait on T01's registrations and the audit credential.
Also corrects an earlier caution in the workplan that the digest was "a local
image id, not a release digest". That was wrong: with the containerd/OCI store
the build id is the manifest digest, and the registry resolves it.
tests/test_deploy_manifest.py holds the pin mechanically instead of by review:
both image references exist, are digest-pinned rather than tagged, are
identical, and no placeholder remains. The identity check matters because the
init container migrates the database the server then serves -- two different
digests there is a split-brain migration. Verified the guard fails on the drift
it targets, not only that it passes today. 116 tests pass.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PM5HnEAhokxdfcPqBNpT7D
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 715850@bnt-lap001
Assistant-Session: eb557e93-7cb1-45d0-9e57-7d15b3edc60e
2026-09-07 09:04:34 +02:00
|
|
|
3. For a new release only: `make image-release` (build, scan, push — the scan
|
|
|
|
|
gate fails the build on any CRITICAL or HIGH, so a failing scan blocks the
|
|
|
|
|
push), then pin both `image:` references to the returned registry digest and
|
|
|
|
|
run `make deploy-dry-run`. The current digest is already pinned; skip to 4
|
|
|
|
|
unless you are cutting a new image.
|
2026-09-02 00:52:04 +02:00
|
|
|
4. Take a verified backup. Roll out by deleting the sole pod, then prove
|
|
|
|
|
readiness, restart persistence, outbox drain, heartbeat, and restore.
|
|
|
|
|
5. Enable a caller namespace only by applying label
|
|
|
|
|
`railiance.io/approval-engine-client=true`; JWT scope checks remain the inner
|
|
|
|
|
boundary.
|
|
|
|
|
|
|
|
|
|
The audit-core receiver-side registration, cadence findings, and accepted-count
|
|
|
|
|
reconciliation are tracked by `AUDIT-WP-0009-T04/T06/T09` and cannot be closed
|
|
|
|
|
from this repository.
|