the-custodian/docs/changes/CUST-WP-0080/forge-template-operations.md

145 lines
8.2 KiB
Markdown

# Forgejo template inheritance
FORGE-WP-0006-T02, coordinated by CUST-WP-0080 G07. Proposal
`forge-template-proposal.json` records the exact source, executor, target,
verification and recovery for trial `FORGE6-TEMPLATE-LIFECYCLE-001`.
Standing build-mode blue-lane authorization applies; this is not an autopilot
grant or a claim of independent owner approval.
The October 13 execution reached Deployment generation 12 Ready, preserving the
image and all 22 previously installed profiles. The live Forgejo global Git
configuration selects `/opt/forge-secret-template`. Native Git initialization
using that configuration inherited the exact regular, executable scanner hook;
malformed input was refused and the owned temporary repository was removed.
The execution receipt is
`docs/evidence/2026-10-13-netkingdom-security/forge-template-activation.json`.
## Durable source
railiance-apps commit `390a30a` owns the immutable non-secret ConfigMap manifest,
Helm volume/mount/encoded environment setting, and the Make prerequisite that
installs the ConfigMap before a future Helm deployment. A file `subPath` mount
is intentional: Git must copy a regular executable, not a ConfigMap projection
symlink. The hook still invokes the two previously admitted binaries on the
existing data PVC. Backup/restore must preserve or re-admit those exact binaries;
the template alone cannot recreate them. Missing scanner artifacts refuse
pushes, rather than disabling detection.
The live change used a conditional JSON Patch because the running Deployment
contains changes newer than its last Helm revision. Reapplying that old Helm
release was outside scope. The patch added one volume, four file mounts and one
configuration environment variable; resourceVersion/UID tests guard the write.
Images, replica/strategy/resource settings, identities, existing environment
entries and Secret objects were unchanged. Initial-only admin bootstrap and
the existing admin row were verified before the restart. Configuration conversion
uses the existing chart's environment-to-ini process.
## Recovery
Do not replay the apply operation after activation. It refuses the changed
Deployment template. To recover this exact change, after checking the current
target and the source record:
```sh
python3 docs/changes/CUST-WP-0080/activate_forge_template.py \
--proposal docs/changes/CUST-WP-0080/forge-template-proposal.json \
--receipt /tmp/forge-template-rollback.json --rollback
```
Rollback removes only the exact added mounts/volume and sets the added environment
variable to `/usr/share/git-core/templates`. Merely removing the environment
variable would leave the saved application/global-Git setting behind. The
ConfigMap remains inert; original and already inherited repository hooks remain.
Readiness, health, exact original 22 profiles, binary custody and default template
selection must pass again. Reconcile the owner Helm source to that explicit default
before another deployment; the original source otherwise intentionally re-enables
the desired control. Unknown concurrent changes cause refusal and require the
railiance-forge abort owner to review the current target, not overwrite it.
Automatic recovery after an incomplete apply is limited to a Deployment whose
template matches the exact attempted result. An uncertain submission checks
current state before deciding whether recovery is needed. The readiness budget
is 240 seconds per rollout/recovery; failure remains unverified in the receipt.
The original October 12 receive-hook activation retains its old pod binding.
Do not edit that old proposal to pretend it targets the replacement pod.
## Remaining acceptance
This closes configuration persistence and native Git inheritance for future
creation paths that use Forgejo's configured Git initialization. It does not prove
an authenticated production API/browser creation, SSO journey or imported/mirrored
content check. Imports and mirrors use clone/fetch; a receive hook is insufficient
for those paths. The refreshed inventory has 166 repositories: 22 installed
profiles and 144 builtin-only inventories. Existing repository expansion, CI
authority, private finding-to-response, historical/LFS/log/artifact coverage and
the applicable DSM requirements remain open in the existing owner plans.
Validation: 30 isolated exact-image lifecycle/configuration/rollback checks, six
conditional-patch/recovery tests, non-secret Helm rendering and matching server
dry-run. Local test containers were removed. The isolated environment used SQLite;
the deployed proof is scoped to configuration, restart, Git inheritance and the
preserved existing profiles.
## October 13 custody regression and recovery
The original generation-12 receipt proves only its listed checks. Ordinary source
push acceptance subsequently failed: Kubernetes volume processing left the
scanner binaries group-writable (0775), which the scanner correctly refuses.
The trial remains failed; later corrections are recovery revisions of the same
proposal, not new unchanged successes. Do not use the original malformed-input
check as evidence that the scanner can open and scan its admitted executable.
- Revision 2: `forge-custody-repair-proposal.json` and
`repair_forge_custody.py` restore only the two hash-pinned files to 0755.
- Revision 3: `forge-custody-rollout-proposal.json` and
`deploy_forge_custody.py` add the unprivileged first init container. The exact
Helm source is railiance-apps `50b66c4`; only the existing security subtree is
mounted. Kubernetes defaults are declared explicitly. The first startup and
real installed-scanner receive probe passed.
- Revision 4: `forge-custody-restart-proposal.json` and
`restart_forge_custody.py` repeat acceptance on another pod. Use its receipt to
determine completion. The revision-3 `--restart-proof` preparation is withdrawn:
its local JSON Pointer helper did not decode the annotation's slash. Its dry-run
refused before mutation. Original executed files and hashes remain preserved.
The guard checks all artifact hashes and owners before changing either mode. It
refuses unexpected permissions, symlinks and mismatched binaries. Missing or
changed artifacts stop startup for investigation; never disable scanning to make
that check pass. The six isolated custody checks simulate fsGroup mode changes.
Native probes use temporary repositories and the real inherited installed hook;
production builtin authorization is excluded there. A normal source sync push is
required separately for authenticated SSH acceptance.
For rollback after revision 4, first conditionally remove only the owned
`custodian.coulomb.social/custody-proof` annotation whose value is the revision-4
marker. Review the resulting template against revision 3's patched digest; wait
for that replacement to finish. Then revision 3 `--rollback` removes only the
exact guard, waits for readiness, and repairs the exact binaries to 0755 after
remount. The next unguarded restart may widen modes again, so rollback is temporary
recovery and does not establish durable acceptance. Reconcile the owner Helm
source before its next deployment. Any unexpected deployment or artifact change
stops this procedure for the named abort owner. Original template rollback is a
separate operation and must not silently remove the custody repair.
### Exact original proposal storage
`forge-template-proposal.json` and `forge-template-source-render.json` are now
lossless archival envelopes. A public ConfigMap source checksum under a filename
containing `secret` triggered the generic API-key detector. The archive keeps
paths and SHA-256 values in separate fields and retains all original metadata.
No detector ignore, exception or rule change was added. The executed original
proposal digest remains unchanged; it is the digest of the restored bytes, not
of the envelope. `forge-custody-metadata-triage.json` records this classification.
Restore the historical proposal to a new private file before using its original
executor (which remains byte-for-byte unchanged):
```sh
python3 docs/changes/CUST-WP-0080/restore_forge_proposal.py \
docs/changes/CUST-WP-0080/forge-template-proposal.json \
/tmp/forge-template-original.json
```
The helper refuses an existing destination or any reconstruction whose digest
differs. Restoration does not authorize replaying a stale live proposal.