E1 secret-ingress experiment¶
This is Phase-0 evidence code for issue 2. It is not the v1 implementation and it will not be maintained past the research report it produces.
The design permits it in as many words: "Narrow prototypes are allowed to obtain that evidence."
What it is for¶
Design §7.1 requires that known or operator-marked secrets be extracted before any ordinary plaintext persistence, across import, drift adoption, draft updates, original YAML text, parsed indexes, request logs, error reports and staging — and forbids retaining an observed configuration in a plaintext draft to redact later, because backups and history would already hold it.
This program exists to make that claim testable against the investigation fixtures, and to produce the evidence a research report can cite. It answers a feasibility question. It does not establish how v1 will be built.
Why its own module¶
experiments/e1-secret-ingress is a separate Go module on purpose. When an implementation module
appears at the repository root, its ./... will not reach this code, so disposable evidence code
cannot be swept into the implementation by accident. mise run go names each experiment module
explicitly for the same reason.
Running the matrix¶
The fixtures must be up first (fixtures/bin/up), and E1_OUT must name an absolute path on disk,
outside this checkout, with room for the bundles:
E1_OUT=<somewhere with a few hundred MiB> experiments/e1-secret-ingress/run/screen
E1_OUT=<the same directory> experiments/e1-secret-ingress/run/matrix
E1_OUT=<the same directory> experiments/e1-secret-ingress/run/schema
E1_OUT=<the same directory> experiments/e1-secret-ingress/run/collect-evidence
E1_OUT has no default on purpose. Every bundle carries a PostgreSQL data directory, so a full
matrix runs to hundreds of megabytes; a default under /tmp would put that in RAM on most systems,
and one inside the checkout would be destroyed by fixtures/bin/down along with the state it is
evidence about. Deleting it afterwards is part of finishing the run — nothing sweeps it.
run/screenis Tier A: every combination of flow, staging mode, outcome and crash point, with no bundle captured. Its only authority is finding candidates. A passing row says the run root and the live tables were clean at that moment and says nothing about the heap, the write-ahead log or the backups. Pass--marks <file>or--mark-suffix <list>to re-run it against a different mark source; the table is named for the source so the two can be compared. Pass--reset-tablesto empty the prototype's tables first, which is required after a matrix has left the deliberate controls' plaintext in the live rows, and must never be passed while a matrix or a capture is in flight.run/matrixis Tier B: the runs that get afixtures/bin/evidencebundle, each asserted byrun/assert-bundle.run/capturetakes one of them on its own.run/schemameasures detection against a ground truth built from the fixture's own rule over the secrets bundle, and plants a secret where no rule looks to show what detection misses and the operator mark catches. It writes the values it works from intoE1_OUT; those files hold real synthetic secrets and are never committed.run/collect-evidencecopies the committable text intoevidence/, rewriting absolute paths and refusing to leave anything the fixture's own patterns match. Run it last, with the fixture still up: it re-reads the control plane and the injection log.
Every honest bundle's leak-scan.txt must hold exactly two lines: the fixture's own positive
control and the reachability control each run plants in its run root. The scan records hits only, so
a directory that scanned clean is identical in the report to one it never walked — fewer than two
lines means the run root went unscanned and the bundle proves nothing about it. More than two is a
leak, and which secret it was is settled by opening the file named, never by the count: the
fixture's synthetic values share a prefix.
A control that comes back clean means that surface is not evidence. Say which one and change the design before drawing a conclusion from it, not after.
One database serves the whole matrix, and the plaintext a --persist-first control commits stays
readable in the heap, the write-ahead log, the dump and the snapshots for every run after it. So
run/matrix takes every bundle that must scan clean before the first control, and the run that
closes the §9.1 machine-state bracket at the end is asserted as residue instead: the run is
honest, the database is not, and a clean scan there would mean the controls' plaintext had gone
away on its own. Re-running the matrix therefore needs a fresh fixture (fixtures/bin/down then
fixtures/bin/up), not just a fresh E1_OUT.
What it deliberately does not do¶
No upstream Talos composition, merge or typed validation. No reference resolution. No release, plan, approval or dispatch. No SQLite, no age/SOPS, no rotation or retention. No migration framework, no concurrency, no server.
It selects nothing: not the marked-secret syntax, not a secret or encryption provider, not a database driver, not a deployment profile. Those decisions belong to their own work items and are made from evidence, not from what this prototype happened to import.