AUR-012 - bootstrapping the consumer demo repository
Documento histórico do board. Pode descrever componentes removidos; para uso atual, consulte o guia do produto.
demo-repo/scaffold is the sealed source of the AurumCode consumer demo
repository, and tests/e2e/consumer/bootstrap/bootstrap.sh is the program that
installs it into an empty checkout.
The outcome this card owns is one sentence: an empty repository receives all the scenarios, without importing private AurumCode data. Both halves are measured. The first half is a count -- every scenario the catalog declares must arrive, byte for byte. The second half is a refusal -- private material is planted on purpose and the bootstrap has to abort before any effect.
Behavior
bash tests/e2e/consumer/bootstrap/bootstrap.sh <scaffold-dir> <target-dir>
<target-dir> must be an empty checkout: an existing directory with no entries,
or a path that does not exist yet. A fresh git clone or git init leaves
exactly that.
On success the program writes one line, then the copy plan in sealed order:
consumer-bootstrap/bootstrapped entries=<n> scenarios=<n> tree_digest=sha256:<hex>
copied<TAB><path>
On refusal it writes a single consumer-bootstrap/<code>[:<detail>] line and
exits 1. A detail is a path, a name or a count; payload bytes are never
printed, so a refusal can never become the leak it is reporting.
Exit codes: 0 bootstrapped, 1 typed refusal, 64 usage, 79 inconclusive
environment.
The copy itself is delegated to demo-repo/scaffold/scaffold.sh, which knows
one rule -- copy the allowlist and only the allowlist. The two programs are
deliberately separate: the copier is treated as untrusted, so the checkout it
produced is verified again by the bootstrap after the fact.
Why git is never invoked
The card's sealed profile bootstrap-readonly-v1 pins an image with bash and
a Go toolchain but no git binary, and the worker runs with a read-only
rootfs and no network. An empty checkout is therefore treated as a working tree
with no entries, which is what the consumer repository actually starts as, and
the whole claim stays provable in the only environment that gates this card.
Contract
The allowlist
demo-repo/scaffold/allowlist.manifest is line-oriented so every field is
matched by an exact expression:
schema: aurum.demo-scaffold-allowlist
version: 1
tree-root: tree
limit: <name> <value>
scenario: <id> <entry-count>
entry: <scenario-id|-> <mode> <bytes> <sha256> <path>
Entries are sorted by path. - marks an entry that belongs to no scenario.
The manifest describes demo-repo/scaffold/tree, which holds the payload that
reaches the consumer; scaffold.sh and the manifest itself are control files
and are never copied.
What keeps private data out
An allowlist alone is data, and data can be tampered with, so three independent rules have to hold before anything is written:
- Path closure. Every file under
tree/must be an allowlist entry (path-not-allowlisted) and every entry must be present (entry-missing). - Path policy, which no manifest can widen. An entry path must be a safe
relative path of at most 128 bytes matching
[A-Za-z0-9][A-Za-z0-9._/-]*with no..segment (path-shape-denied), and no segment may name an AurumCode-private root --.board,.git,.github,.taskmaster,.claude,.ssh,.aurum-bootstrap,credentials,secrets,internal, or a.envfile (private-path-denied). A symlink is refused outright (symlink-denied), so nothing can be imported by reference. - Payload screen. Bytes are read, not merely hashed. A payload carrying an
AurumCode-private marker (
private-marker-detected) or a value shaped like a real credential -- PEM private key headers,AKIA...,sk-...,gh?_...(credential-shape-detected) -- is refused even when the manifest seals its digest correctly.
The synthetic placeholder shape AURUM-FAKE-<NAME> is deliberately not
private. The catalog contains a scenario about a leaked credential, and it has
to survive the screen; that is what stops the screen from passing by refusing
everything.
After the copy, path closure, digests and the payload screen are applied again
to the bytes that actually landed. A copier that writes a file nobody
allowlisted is caught there (unlisted-entry-copied) even though the scaffold
it read was clean.
Domain limits
| limit | value | first value beyond it |
|---|---|---|
max_entries |
64 | 65 entries -> too-many-entries |
max_file_bytes |
65536 | 65537 bytes -> file-too-large |
max_total_bytes |
1048576 | beyond -> tree-too-large |
max_path_bytes |
128 | 129 bytes -> path-too-long |
max_scenarios |
32 | 33 scenarios -> too-many-scenarios |
The limits are constants in the bootstrap and are also declared in the manifest.
A manifest that declares a different number is refused with limit-divergence:
the domain lives in the program, never in the data.
The sealed catalog
Six scenarios, 15 entries, all synthetic:
| scenario | kind | what a review of it should say |
|---|---|---|
clean-change |
clean | nothing to report |
docs-drift |
documentation | the document no longer matches the code |
flaky-test |
test quality | the test depends on wall-clock timing |
null-deref |
correctness | an absent lookup result is dereferenced |
secret-leak |
security | a placeholder credential sits in source |
sql-injection |
security | a query is built by string concatenation |
Sealed values of the checked-in scaffold, recomputed by the acceptance on every run:
- scaffold input digest (allowlist plus the tree it describes):
sha256:c7b1832092b391d7437481ab0129380ad3d12e6ae27cc1db73035029812e92b1 - consumer checkout digest after a nominal bootstrap:
sha256:ab5a1b68eed1799a6838406959142eefae0828e05c008a08459d9809dc7c3b59
Example (no secret involved)
Bootstrap the demo repository into an empty checkout. This is the same call the
acceptance makes for the nominal-bootstrap vector, so the example cannot drift
from the behavior:
out="$(mktemp -d)/consumer"
bash tests/e2e/consumer/bootstrap/bootstrap.sh demo-repo/scaffold "$out"
# consumer-bootstrap/bootstrapped entries=15 scenarios=6 \
# tree_digest=sha256:ab5a1b68eed1799a6838406959142eefae0828e05c008a08459d9809dc7c3b59
Resealing the allowlist after a scenario changes, from the repository root:
cd demo-repo/scaffold
{
sed -n '1,7p' allowlist.manifest
for s in $(sed -n 's/^scenario: \([a-z0-9-]*\) .*/\1/p' allowlist.manifest); do
printf 'scenario: %s %d\n' "$s" "$(cd tree && find "scenarios/$s" -type f | wc -l)"
done
(cd tree && find . -type f | sed 's|^\./||' | LC_ALL=C sort) | while read -r p; do
case "$p" in scenarios/*/*) sc="${p#scenarios/}"; sc="${sc%%/*}" ;; *) sc='-' ;; esac
printf 'entry: %s 0644 %s %s %s\n' "$sc" \
"$(stat -c '%s' "tree/$p")" "$(sha256sum "tree/$p" | cut -d' ' -f1)" "$p"
done
} > allowlist.manifest.new && mv allowlist.manifest.new allowlist.manifest
The acceptance recomputes the same values, so a manifest that drifts from the
tree fails scaffold-manifest-divergence before any vector runs.
Diagnosis
| observation | what it means |
|---|---|
AUR-012/AC-001/behavior-missing |
the scaffold or the bootstrap is absent |
AUR-012/AC-001/detector-missed:<vector> |
a planted vector was accepted |
AUR-012/AC-001/planted-undetected:<n> |
private material reached the copy stage |
AUR-012/AC-001/MUT-001 |
the copier put an unlisted file in the consumer |
AUR-012/AC-001/nominal:scenario-not-delivered:<path> |
a scenario did not arrive |
AUR-012/AC-001/vector-effects:<v>:want=0:got=<n> |
a refusal wrote to the checkout |
AUR-012/AC-001/inconclusive/... |
environment, never red evidence |
consumer-bootstrap/inconclusive/... on stderr with exit 79 is likewise an
environment result. Only exit 0 is green; exit 1 is behavioral red.
Non-goals
Running the scenarios is not part of this card. The bootstrap proves that an empty repository receives them; executing a review over them belongs to the end-to-end cards that consume this checkout.