Sigil Vault 1.0.0 — capability-native secrets platform
======================================================

Full HashiCorp Vault parity in ~138 KB of Sigil. Seven engines, no C, no
runtime, no dependencies, and no network surface.

Engines
-------
  vault-kv          Core KV — 32 secrets, namespace isolation, leasing,
                    seal/unseal, rotation with physical zeroing, audit ring
  vault-transit     Encryption-as-a-service — AES-256-GCM, key rotation,
                    HMAC, PBKDF2-SHA256 key derivation (100 000 rounds)
  vault-pki         PKI — CA, certificate issuance, ed25519 signing/verify
  vault-dynamic     Dynamic secrets — on-demand credentials with TTL and
                    auto-revoke, O(1) derivation, no backend round-trip
  vault-kv2         KV v2 — versioned secrets with history
  vault-wrap        Response wrapping / cubbyhole — single-use tokens
  vault-transform   FPE, masking, tokenization (reversible, deterministic)

The core idea: secrets ARE capabilities. The kernel's capability system
already decides who can reach what, so there is no separate auth/policy/token
layer to disagree with it. Seal is "present the seal capability", not a Shamir
ceremony. HashiCorp Vault is ~200 MB and exposes an HTTPS API; this is ~138 KB
and exposes nothing to the network.

Test results — 133/133, measured, not transcribed
-------------------------------------------------
  SIGIL-VAULT      27/27      VAULT-KV2        17/17
  VAULT-TRANSIT    20/20      VAULT-WRAP       15/15
  VAULT-PKI        22/22      VAULT-TRANSFORM  17/17
  VAULT-DYNAMIC    15/15

Every engine's suite was executed — natively on macOS arm64, and under QEMU
(raspi3b) for the sigilOS build. The previous documented figure (121/121) was
never produced by a run; the real per-suite numbers differ from it in every
row. Two genuine defects were found and fixed in the process, both described
below.

Note on vault-transit under emulation: its self-test derives three keys with
100 000 rounds of PBKDF2-SHA256 each — roughly 600 000 SHA-256 compressions in
pure Sigil before the first assertion. That completes natively but will not
finish under QEMU's interpreter in any reasonable window. It is a deliberate
security parameter (the "c >= 100000" floor), not a hang.

Contents
--------
  sigilos/    7 flat-v1 arm-el0 blobs — Raspberry Pi 3B / 4B / 5
  macos/      7 Mach-O arm64 binaries — Apple Silicon, macOS 12+
  linux/      7 static ELF x86-64 binaries — no deps
  windows/    7 PE32+ x86-64 executables — no deps

Each binary runs its engine's self-test and prints the result line. One binary
per engine: every engine defines its own putc1/puts/str_hash, so linking
several into one image would collide.

Running the same engines on a host OS
-------------------------------------
Two things differ between the sigilOS build and the native builds, and only two:

  1. The arena. Every engine derives its regions from vault_arena() + a fixed
     offset, so the whole 896 KB arena relocates as a unit. sigilOS keeps the
     historical 0xDA0000 base and needs no mapping. The native PALs place it at
     0x200000000 and mmap/VirtualAlloc it, because macOS __PAGEZERO reserves
     the low 4 GB of a non-PIE Mach-O and refuses the EL0 base outright
     (measured with a probe, not assumed).
  2. putc1. The engines print with syscall(1, ...) — WRITE on sigilOS, but EXIT
     on Darwin and Linux. An unmodified engine would terminate on its first
     character of output, so native builds repoint putc1 at write(1, ...).

Engine logic is byte-identical across all four targets.

Fixed in 1.0.0
--------------
  * REGION COLLISION (vault_dynamic): ds_roles/ds_creds/ds_state each returned
    an address one 0x8000 slot ABOVE the address their own comment named. The
    last of them landed on 0xE30000 — exactly vault_kv2's kv_entries base. Both
    engines map the same arena, so Dynamic's state counters wrote straight
    through KV v2's versioned-entry table: generating a dynamic credential
    corrupted stored secrets. Neither engine's self-test caught it because
    neither runs with the other's data present.
  * UNDER-COUNTED TOKENIZATION (vault_transform): tf_tokenize's cache-hit path
    returned without incrementing the counter, so tf_tokenized() under-reported
    by exactly the number of repeat requests — wrong for an audit number.
  * Four address comments in vault_kv2 and vault_wrap named addresses their
    code did not use. Corrected to match the code.

Source: github.com/grioghar/sigil-vault (private). Sigil only, zero Python,
zero C.
