A privacy lattice for oblivious DNS (formerly oDNS), proved in Agda: per-field reader-set labels under which self-defeating privacy compositions are refused, built to instantiate secret-types' noninterference theorem.
A Lintel label names the oblivious-DNS roles (client, proxy, target) that may
observe a field, and combining fields intersects their readers. The client’s
address may reach the proxy and the query name may reach the target, but the
two together are the client’s alone. A composition that would show one
non-client role both of them therefore needs a flow the lattice refuses. The
proofs are in Agda (--safe --without-K). The noninterference theorem the
lattice is built to instantiate comes from
hyperpolymath/secret-types,
consumed at a pinned commit.
just # lists every task (build, test, validate, audit, ...)
just validate # structure + metadata checksLintel was minted from rsr-template-repo, which supplies:
-
Machine-readable metadata (
.machine_readable/descriptiles/) —STATE,META,ECOSYSTEM,PLAYBOOK,AGENTIC,NEUROSYM,CLADE, andanchors/ANCHOR, in deed, so tools and agents can read the project’s state and boundaries. -
AI gatekeeper protocol —
lintel_chora.deed(the repo deed) is the universal entry point that tells an AI agent how to work in this repo before it touches anything; it carries the AI allocation policy and the ply directory tree. -
Typed ABI/FFI seam —
src/interface/Abi/(Idris2 type + layout proofs) oversrc/interface/ffi/(Zig implementation), with generated C headers. -
CI/CD — GitHub Actions for quality, security (CodeQL, Scorecard, secret scanning), multi-forge mirroring, and RSR anti-pattern enforcement.
-
Supply-chain & reproducibility — container layering (stapeln), Guix shells, SBOM, and signing hooks.
-
Governance —
GOVERNANCE.adoc,MAINTAINERS.adoc,.github/community health files, and a releaseAUDIT.adocgate.
The authoritative map is generated, so it cannot drift from the tree:
docs/architecture/REPOSITORY-MAP.adoc
(regenerate with just repo-map; CI fails if it is stale).
The short version:
| Path | What lives there |
|---|---|
|
Start here - humans and AI agents respectively. |
|
The code and its tests. |
|
Human documentation, including the full map above. |
|
Manifests, contractiles and policies that tools read. |
|
Every task runs through |
|
CI configuration; GitHub reads |
-
The repository map — generated; what every directory is for.
-
EXPLAINME — the engineering deep-dive: how the pieces actually work.
-
AFFIRMATION — the dated, signed honesty snapshot of the repo’s true state.
-
AUDIT — the release audit gate.
-
PLACEHOLDERS — the full placeholder reference.
Lintel labels each field with the set of oblivious-DNS roles (client, proxy, target) allowed to observe it. Combining fields intersects their readers, so the client’s address (client and proxy) combined with the query name (client and target) is the client’s alone. The guarantee is secret-types' termination-insensitive noninterference (TINI) at this lattice, with one observer per role: two finishing runs that agree on what a role may observe end up agreeing on it. It holds for programs over the two fields and the client’s local state, not only for labels (L-6, L-7), under the non-collusion assumption A-1.
| ID | Claim | Status | Artefact |
|---|---|---|---|
L-1 |
A lattice, not just a poset. ⊑ is a decidable partial order, ⊔ and ⊓ are least upper and greatest lower bounds, |
PROVEN |
|
L-2 |
⊑ is reverse inclusion of reader sets. A role sees a label exactly when the label may flow to that role’s observer level. |
PROVEN |
|
L-3 |
The laws secret-types' generic TINI needs hold here: |
PROVEN |
|
L-4 |
Address and query name each reach their own role. Composed, only the client may observe them. |
PROVEN |
|
L-5 |
The typechecker refuses the self-defeating compositions and accepts the client’s. |
TESTED |
|
L-6 |
|
PROVEN |
|
L-7 |
Self-defeating privacy compositions cannot be built as programs. A typed command writes a value depending on both fields, through its expression or through the guards around it, only into a variable that the client alone may read, for any variables and labelling. With Lintel’s variables that is the client’s local state alone, and a typed command can write the link there, so the refusal is of the destination, not of every composition. |
PROVEN |
|
A-1 |
Non-collusion: no party holds both the proxy and the target role. TINI holds for coalitions too (L-6), but the confinement of the link (L-4, L-7) is per role: proxy and target together see the address and the query name, each by a permitted flow, and can join them outside any program. Coalition TINI is not determinism in disguise: the coalition does not see the client’s local state, so it relates stores that differ there, and says their runs end agreeing on the address and the query name. |
ASSUMED |
Non-collusion, as in proven-servers |
The Lattice record is defined once, in secret-types. Lintel proves the laws and
supplies the instance. just proof-check-lintel checks everything above (it
runs scripts/fetch-siblings.sh then scripts/check.sh), and so does the
Agda proofs workflow: Agda 2.6.4.3 with the flags of scripts/proof-flags.sh,
the canonical --safe --without-K --cubical-compatible (PROOF-POLICY.adoc
§2.1) and --no-libraries --ignore-interfaces --double-check -W error besides,
secret-types pinned at 45046c2.
Grade. The PROVEN claims (L-1 to L-4, L-6, L-7) are at Proof Witness Grade
PWG-2ii (PROOF-POLICY.adoc §8) and no higher. Each is also re-proved by
hand in Rocq (Coq 8.18.0) and in Lean (4.24.0, no Mathlib), on top of
secret-types' own legs at the same pin, with no axioms in either. The statements
are compared in verification/legs/README.adoc;
Claude Code wrote that comparison, and it is provisional until the owner reviews
it. bash scripts/check-legs.sh checks both legs. Not PWG-1: no per-commit
receipt captures each checker’s observed result yet.
L-5 is a set of checked refusals and A-1 an assumption; neither is a theorem, so
neither is graded. The machine record is
verification/receipts/agda-pwg_praxis.deed,
generated by scripts/grade-receipt.sh and checked in CI, and the per-claim
record is docs/status/PROOF-STATUS.adoc.
Code, configuration and scripts are Mozilla Public License 2.0
(MPL-2.0); prose documentation is CC-BY-SA-4.0. Both texts live in
LICENSES/, and per-file SPDX-License-Identifier headers are authoritative.
The GitHub-detected licence is MPL-2.0 (the root LICENSE). Long-term
attribution uses Quantum-Safe Provenance — see
the Quantum-Safe Provenance exhibit.