check-safety/docs/adr/0003-isolate-proto-freshness-generation.md
2026-08-25 21:27:37 +08:00

50 lines
2.9 KiB
Markdown

# Isolate proto freshness generation from the scanned repository
Decided 2026-08-25. Check 2f ran `make proto` in the scanned CMS working tree
and compared `git status` before and after. That made a read-oriented safety
check destructive: concurrent checker processes generated into the same files,
an interrupted run could leave a partially rewritten tree, and a generated
file that was already dirty could change bytes without changing its porcelain
status.
## Decision
- Copy the proto generation inputs and existing generated outputs into a unique
temporary sandbox for every freshness invocation.
- Run `make proto` only in that sandbox. Link only the installed package-local
generator executables and their package entrypoints needed by Buf and the
export script; generated output paths never point back into the scanned
repository.
- Snapshot generated regular files and symlinks by type, mode, link target, and
SHA-256 content digest before and after generation. Sort paths before
reporting added, modified, and removed outputs in the existing porcelain-like
CLI format.
- Remove the owned sandbox on success, generator failure, and all ordinary
return paths. Abrupt process interruption can affect only disposable system
temporary state, never the scanned working tree.
- Exercise the boundary with real `make` recipes, including independent
concurrent checker processes and a generator that writes partial output
before failing.
A repository-wide lock was rejected because it serializes independent safety
runs and still leaves the live working tree vulnerable to interrupted
generation. Comparing only Git status in a temporary checkout was rejected
because status is not a content comparison and can conceal a second rewrite of
an already-modified file. Copying the entire repository, including dependency
trees and build artifacts, was rejected because proto generation needs only a
small, explicit input and output surface.
## Consequences
- Parallel check-safety processes can run proto freshness checks without
contending on generated files or corrupting the CMS checkout.
- Check 2f retains its `make proto` success, failure, and before/after finding
messages while its freshness verdict now follows deterministic file content.
- Generator stderr is still returned through `protoFreshnessResult.output`, and
sandbox preparation, snapshot, generation, and cleanup failures retain their
causal error chains.
- `proto_freshness.go` owns isolation and comparison; focused regression
coverage lives in `proto_freshness_test.go`.
Keywords: check-safety, check 2f, proto freshness, make proto, concurrency, interruption safety, sandbox, checkProtoGeneratedFreshness, checkProtoGeneratedFreshnessInSandbox, protoFreshnessResult, proto_freshness.go, proto_freshness_test.go, backend/internal/api, backend/internal/mcpserver/generated, packages/api/src, buf generate, pnpm generate-exports