prepare records an immutable manifest of every regular backend/dist file (path/size/sha256/dev/ino) in the owned root and binds its record identity in ownership; serve revalidates record and every file before spawn, passes the manifest to the child on fd 4, and the immutable preload hash-verifies all files at startup and serves only cached verified bytes for any import below backend/dist, so imported dependency replacement is refused before RUNNING or never executes. The render command validates the commit snapshot.json manifest, binds snapshot bytes to the manifest digest and the installed Git blob, and passes the expected digest to the renderer, which revalidates head/files digest with bounded no-follow reads and renders only verified bytes with lease release on refusal.
67 lines
4.2 KiB
Markdown
67 lines
4.2 KiB
Markdown
# Task 9 quality audit — final 5
|
|
|
|
**Scope:** the two blocking findings from `task9-quality-audit-final4.md` — unbound production
|
|
module graph at manual serve, and commit-addressed snapshots accepted without content identity at
|
|
render. Manual acceptance remains **PENDING**; no `VERDICT.md` was created.
|
|
|
|
## Verdict: APPROVED for the two final integrity blockers
|
|
|
|
### 1. Manual serve binds the complete `backend/dist` module graph, not only `server.js`
|
|
|
|
`prepare` now builds a post-build manifest of every regular `backend/dist` file
|
|
(relative path, size, SHA-256, device, inode) and writes it as an exclusive `0600` record
|
|
(`installation/runtime/backend-dist.manifest.json`) inside the owned root; `ownership.json`
|
|
records that record's path/device/inode/size/SHA-256. `serve` revalidates the manifest record
|
|
identity and bytes, revalidates every distribution file against it (no-follow, single inode,
|
|
size and digest), and refuses before spawning. The manifest descriptor is passed to the child on
|
|
fd 4 together with the entrypoint on fd 3. The immutable preload parses the manifest, verifies
|
|
the entrypoint cross-digest, reads and hash-verifies **every** file at startup, caches the
|
|
verified bytes, and its load hook serves **only** those cached bytes for any import below
|
|
`backend/dist` (entry URL still served from the bound fd-3 bytes). A same-path regular
|
|
replacement of any imported dependency is therefore refused before `RUNNING` (serve-time
|
|
validation), refused at child startup (startup verification), or rendered harmless (cached
|
|
bytes), and the parent revalidates the full manifest at `RUNNING` publication and at `stop`.
|
|
|
|
### 2. Renderer binds snapshot content to its commit identity
|
|
|
|
The generated render command validates the bounded saved read/publish revisions, the
|
|
commit-addressed owned snapshot path, the installed Git HEAD, and the bounded
|
|
`snapshot.json` manifest of that commit: `head` equals the commit, `files[<id>.yaml]` is the
|
|
SHA-256 of the snapshot bytes, the manifest revision binds commit/blob/snapshot path, the saved
|
|
revision blob equals the manifest blob, and `git rev-parse <commit>:workspaces/<id>.yaml` plus
|
|
`git hash-object` of the snapshot bytes both equal that blob. It passes the expected digest as
|
|
`--snapshot-sha256`. The renderer re-reads the bounded `snapshot.json` (`head`,
|
|
`files[<id>.yaml]` must equal the carried digest), opens the snapshot once with no-follow
|
|
semantics and bounded reads, renders only the digest-verified bytes, re-verifies around lease
|
|
publication, releases the lease in `finally`, and publishes no output on any refusal.
|
|
|
|
## Deterministic regressions added
|
|
|
|
- static regular replacement of an imported production dependency after `prepare` is refused,
|
|
no marker, no accepted PID record, no orphan;
|
|
- deterministic dependency check/load swap (`beforeSpawn` rename) is refused by the child's
|
|
startup verification, no marker, no PID record, no orphan;
|
|
- after `RUNNING`, a same-path regular dependency replacement is never executed: the loader
|
|
serves the verified cached bytes (health-visible source stays the original) and the marker is
|
|
absent;
|
|
- renderer refuses a same-path regular snapshot byte replacement against the carried digest and
|
|
manifest, with lease release and no output;
|
|
- renderer refuses manifest `head`, `files` digest, expected-digest, missing, and malformed
|
|
cases, with lease release and no output;
|
|
- wrapper refuses missing manifest, manifest head/digest/revision tampering, saved-revision blob
|
|
mismatch, Git blob mismatch, and snapshot-vs-Git-bytes mismatch, and passes the exact
|
|
`--snapshot-sha256` on the valid path (stub renderer records arguments).
|
|
|
|
## Verification
|
|
|
|
- `bash scripts/test-p1-manual-acceptance.sh` (backend build + both suites): **59 tests, 59
|
|
pass, 0 fail**; no `8791/8792` listener and no `--p1-manual-nonce` process remain.
|
|
- `npx tsc --noEmit -p .` (backend): PASS.
|
|
- Real-repository `prepare` + `cleanup` cycle: 39 distribution files bound, entrypoint
|
|
cross-digest verified, owned root fully removed afterwards.
|
|
- Diff check: only the seven Task 9 paths are touched; no Task 8 file was modified.
|
|
- This report and the implementation contain no fixture secret or canary values.
|
|
|
|
Manual acceptance remains **PENDING** by design; the walkthrough and human verdict are
|
|
unchanged.
|