ADR-0080: Sealed root-worker GNU version requirement inventory

Status: accepted
Date: 2026-08-10
Decision owners: NAUX architecture and x86-64 root-requester boundary

Context

ADR-0076 inventories version requirements made by the three exact dependency providers. ADR-0077 through ADR-0079 prove provider namespace compatibility and inventory their dynamic symbols. The sealed root worker is a different ELF object: its own undefined symbols are the requests a future sovereign resolver must eventually satisfy, but its DT_VERNEED/Vernaux chains have never been independently inventoried.

ADR-0071 records the worker’s direct DT_NEEDED names, and ADR-0072 admits the exact caller-reviewed declarations. ADR-0075 closes those names over exact provider identities. None of those decisions proves which GNU version namespaces the worker requests. Reading those chains later inside symbol lookup would merge requester inventory, provider compatibility, and resolution into one oversized authority boundary.

Decision drivers

  • Read only the already verified, immutable root-worker descriptor; never reopen its original path.
  • Independently decode the root ELF layout and exact GNU Verneed/Vernaux chains without section headers or a host ELF library.
  • Bind every requirement filename to exactly one direct ADR-0072 declaration and exactly one ADR-0075 provider identity.
  • Preserve record/auxiliary order, flags, hashes, local version indices, names, offsets, and predecessor identities under explicit limits.
  • Keep requirement inventory separate from definition matching and symbol lookup.

Considered options

Reuse host-loader diagnostics

Rejected. Loader output and host search state are not sealed semantic inputs.

Trust ADR-0071 direct dependencies as version requirements

Rejected. DT_NEEDED proves only an object-level declaration. It contains no version name, version hash, flags, or local version index.

Reuse ADR-0076 evidence for the root worker

Rejected. ADR-0076 is explicitly scoped to canonical ADR-0075 providers and binds each record to a provider object ordinal. The worker is the root requester, not another provider appearance.

Combine requirement inventory, definition matching, and symbol lookup

Rejected. These are three different judgments. A malformed requester chain must fail before NAUX considers provider namespaces or lookup precedence.

Emit a root-only proof ledger and defer compatibility

Selected. ADR-0080 inventories exactly what the worker asks for and which reviewed direct provider the filename denotes. A later ADR must independently join those names to ADR-0077 definitions before root dynsym/versym or symbol resolution can consume them.

Decision

Introduce one root-worker requirement evidence object. Emission first replays ADR-0071, ADR-0072, and the accepted ADR-0075 closure, then obtains bytes only from the verified artifact descriptor. The new decoder independently:

  1. validates ELF64 little-endian x86-64 ET_DYN, program headers, bounded read-only PT_LOAD mappings, and one exact PT_DYNAMIC segment;
  2. requires paired DT_STRTAB/DT_STRSZ and paired optional DT_VERNEED/DT_VERNEEDNUM tags with a canonical terminated dynamic table;
  3. walks exactly DT_VERNEEDNUM 16-byte records and each exact 16-byte Vernaux chain, rejecting overlaps, early/late terminals, zero counts, invalid relative offsets, unsupported revisions, and reserved flags;
  4. decodes bounded printable names from the admitted string table and verifies every auxiliary’s System V ELF name hash;
  5. requires every requirement filename to equal exactly one ordered ADR-0072 direct dependency and one exact ADR-0075 provider SONAME; the interpreter is not an implicit dependency candidate unless explicitly declared by DT_NEEDED;
  6. preserves root artifact identity, declaration ordinal, provider ordinal, record/auxiliary ordinals, raw fields, exact names/hashes/indices, record ranges, predecessor evidence hashes, and domain-separated local/aggregate seals.

Verification preflights bounded evidence shape and predecessor roots, then replays the decoder from the immutable descriptor and requires exact evidence equality. Requirement order is semantic evidence and is never sorted or deduplicated.

Frozen limits

  • exactly one root requester;
  • at most 64 program headers, 16 load segments, and 4,096 dynamic entries;
  • at most 64 root requirement records and 64 auxiliaries per requirement;
  • at most 4,096 total root auxiliaries;
  • string table at most 1 MiB and each filename/version name at most 256 bytes;
  • Verneed revision exactly 1;
  • only zero or GNU weak flag bits are structurally recognized; weak compatibility remains ungranted;
  • accepted ADR-0071 inventory policy root 1a6c96c8b47a2001d9969488785c6bb2b846c378280b0498f2c16b0f14fd3bbf;
  • accepted ADR-0072 declaration policy root 5a69470530ec8f65be018f53927379381a6d20cec7ca9076a69441a80183ec22;
  • accepted ADR-0075 closure policy root 6835b65f73be7d214da23b20c92b93013ac02c5f3b96c4abf743cd503761bd56;
  • proof-only inventory; encoder policy remains 1.4.0.

Consequences

  • Positive: a future resolver receives a complete root requester namespace ledger instead of decoding version chains while binding symbols.
  • Positive: every requirement file is already tied to a reviewed sealed provider identity without using host search paths.
  • Positive: path replacement after artifact admission cannot change the inventoried root bytes.
  • Negative: successful inventory does not prove that any requested version or symbol exists.
  • Negative: verification replays the accepted artifact/declaration/closure chain before decoding.
  • Risk: weak requirements remain recorded but cannot be interpreted as fallback authority.
  • Open: root requirement-to-definition compatibility, root dynamic-symbol and version-index inventory, lookup scopes, interposition, binding, relocation, mapping, initialization, TLS/IFUNC and execution remain separate decisions.

Acceptance gates

  1. Lock the exact ordered root Verneed and Vernaux counts, filenames, provider ordinals, version names, hashes, flags, and local indices.
  2. Missing, duplicate, mismatched, truncated, excessive, overlapping, early/late-terminal, revision, flag, count, offset, string, name/hash, declaration/provider, stale-root, reorder, and locally resealed mutations fail closed.
  3. A coherent mutation selecting a different valid direct provider and recomputing every local seal still fails independent regeneration.
  4. Replay remains exact after source-path replacement; production source has no filesystem, path, process, section-header, host parser/loader, definition-matching, symbol, relocation, native, timing, or claim authority.
  5. Focused, workspace, strict lint, governance, refinement, format, shell, link, parity, static-authority, and descriptor-replay gates pass before acceptance.
  • ADR-0071 supplies the sealed root ELF and exact direct DT_NEEDED declarations.
  • ADR-0072 supplies caller-reviewed direct dependency authority.
  • ADR-0075 supplies exact canonical provider identities.
  • ADR-0077 is the future compatibility target but grants no authority to this inventory.
  • ADR-0079 supplies only provider symbol facts, not root requester facts.

Acceptance record

Accepted on 2026-08-10 under policy root 1e728341f69e0cb1ba9d5ce8a6400cdbe72c8866a1ed8ec8e52a1a50fa9fecdf. The immutable root worker exposes three ordered requirement records and twenty ordered auxiliaries: three GCC_* names for libgcc_s.so.1, sixteen GLIBC_* names for libc.so.6, and one GLIBC_2.3 name for ld-linux-x86-64.so.2. Every file binds to its exact ADR-0072 declaration and ADR-0075 provider. Local version indices are sealed per exact artifact and remain valid and globally unique; they are not falsely equated across different feature-linked worker binaries.

Raw probes reject dynamic-tag, count, revision, file/name offset, duplicate file, auxiliary-link, flag, version-index, and ELF-name-hash mutations. Evidence probes reject stale predecessor roots, totals, records, auxiliaries, and a coherent alternate direct-provider choice after all affected seals are recomputed. Admission, inventory, mutation, and verification continue from the sealed descriptor after the original root-worker source is replaced and deleted.

The final all-feature workspace exits successfully. The library suite reports 413 passed, zero failed, and six intentionally ignored tests in 434.92 seconds; the ADR-0073 through ADR-0080 carrier reports two passed and zero failed in 524.68 seconds; the process-isolation carrier reports three passed and zero failed in 308.73 seconds. Strict Clippy with warnings denied, cargo check, 22/22 governance, 8/8 strict refinement, all nine shell syntax checks, format/diff, 343/343 local Markdown targets, locked policy-root tests, production static-authority inspection, raw/evidence mutation probes, and exact descriptor replay pass.

Acceptance grants no requirement-to-definition compatibility, root dynamic- symbol or .gnu.version inventory, lookup, selection, interposition, binding, weak fallback, mapping, relocation, initialization, execution, sandbox, standalone, timing, performance-claim, or global encoder-policy authority.