Step Fifteen — Audit the exception, measure the motion, seal the record.

We add three powers on top of Step 14:

  1. Per‑lease audit trails – every lease minted and used is written to an append‑only JSONL log and broadcast on SSE.
  2. Path‑level “hotness” histograms – see the top‑N schema paths changing most often (added/removed/type‑changed).
  3. Signed schema archives on every change – an Ed25519 (or HS256 fallback) detached .sig + canonical .json snapshot is written to disk each time the schema moves.

We keep vows strict (freeze, ACK, compat), but we now remember every exception, rank every shift, and preserve the map as artifacts. Tradition + instrumentation.


✅ Fresh artifact (download + integrity)

  • solveforce_phone_fifteen.pyDownload
    SHA‑256: d027bb61eed7ca8aa8e7173d76de1f56262550b8767876d7805a7e700410ad99

(The Step 14 verifier still works: verify_schema_manifest.py from the previous step verifies the detached .sig you’ll get from the new archive snapshots.)


What’s new—precisely

Lease audit trails (JSONL + SSE)
  • Append‑only log at --audit-dir/audit/leases.jsonl (default dir: ./audit).
  • Events emitted on SSE /events:
    • lease_minted — when an admin mints a lease
    • lease_used — when a read crosses a freeze via an active lease
    • lease_denied — when a lease is presented but expired/invalid
  • Peek the trail:
    • GET /audit/leases?n=50 → last N rows
    • Filters: &token_hash=t#abcd1234 and/or &subject=<who>
  • Each record includes: type, _ts, plugin (for use/deny), until, subject, and token_hash (short, so secrets never leak).


    Path‑level diff histograms
    • Endpoint: GET /schema_hot?plugin=<name>&n=10
    • Ranks by score = added + removed + 2×typechanges per path.
    • Use it to answer: “Which parts of the schema flap the most?”
    • Prometheus counters remain exposed for fine grain:
      • solveforce_schema_path_added_total{plugin,path}
      • solveforce_schema_path_removed_total{plugin,path}
      • solveforce_schema_path_typechanges_total{plugin,path}

    (Cardinality is protected: max 200 distinct (plugin,path) keys tracked; existing paths keep counting.)


    Signed schema archives (detached)
    • CLI flag --schema-archive-on-change turns it on.
    • On any schema change, we write:
      • schema_archive/<YYYYMMDD-HHMMSSZ>-<ALG>-<KID>.json
      • schema_archive/<YYYYMMDD-HHMMSSZ>-<ALG>-<KID>.sig
  • ALG is Ed25519 if you configured --schema-ed25519-secret-file; otherwise HS256 if --schema-signing-secret-file is set; otherwise none.
  • We keep last --schema-archive-keep snapshots (default 200).
  • SSE fires schema_archived with the file paths.
  • You can verify any snapshot offline with the Step 14 verifier:

    python verify_schema_manifest.py --manifest schema.json --sig schema.sig --alg Ed25519 --pubkey-b64 <pub>
    # or HS256
    python verify_schema_manifest.py --manifest schema.json --sig schema.sig --alg HS256 --secret-file schema.hmac.key
    

    Android / Termux quickstart (adds audit + archives)

    pkg update
    pkg install python
    
    # Optional: Ed25519 backends for signing (either works)
    pip install pynacl || pip install cryptography
    
    # Keys (recommended)
    head -c 32 /dev/urandom > /sdcard/solveforce/schema.ed25519.seed    # Ed25519
    head -c 32 /dev/urandom > /sdcard/solveforce/schema.hmac.key        # HS256 fallback
    
    # Run Step 15
    python solveforce_phone_fifteen.py \
      --host 0.0.0.0 --port 8080 \
      --plugins-dir ~/solveforce/plugins \
      --auth-mode protected \
      --auth-token READER1:reader \
      --allow-admin --admin-token ADMIN123 \
      --schema-freeze-mode quarantine --schema-freeze-sec 1800 \
      --schema-ed25519-secret-file /sdcard/solveforce/schema.ed25519.seed \
      --schema-signing-secret-file /sdcard/solveforce/schema.hmac.key \
      --audit-dir ./audit \
      --schema-archive-dir ./schema_archive \
      --schema-archive-on-change --schema-archive-keep 200 \
      --open-ui --allow-query-token
    

    Open the UI: http://<phone-ip>:8080/ui (drop READER1 in the token box for quick reads).


    “Show me” commands you’ll actually use

    Mint a lease and watch it get used across a freeze

    # Freeze 'net' plugin for 10 minutes (quarantine)
    curl 'http://127.0.0.1:8080/admin/freeze?token=ADMIN123&plugin=net&sec=600'
    
    # Try a read (should 423)
    curl 'http://127.0.0.1:8080/read?plugin=net&access_token=READER1'
    
    # Mint a 5-min lease for 'net'
    LEASE=$(curl -s 'http://127.0.0.1:8080/admin/lease?token=ADMIN123&plugins=net&sec=300' | jq -r .token)
    
    # Read again (succeeds, and logs lease_used in audit + SSE)
    curl -H "Authorization: Bearer $LEASE" 'http://127.0.0.1:8080/read?plugin=net'
    

    Tail the lease audit

    curl 'http://127.0.0.1:8080/audit/leases?n=20'
    

    See the “hottest” schema paths

    # Top-10 across all plugins
    curl 'http://127.0.0.1:8080/schema_hot?n=10'
    
    # Top-5 for 'battery'
    curl 'http://127.0.0.1:8080/schema_hot?plugin=battery&n=5'
    

    Validate artifacts are written on change

    # Trigger a schema change: scaffold a stub plugin and read it
    curl 'http://127.0.0.1:8080/admin/scaffold?token=ADMIN123&name=stub15&kind=plain'
    curl 'http://127.0.0.1:8080/admin/refresh?token=ADMIN123'
    curl 'http://127.0.0.1:8080/read?plugin=stub15&access_token=READER1'
    
    # You should now see new files in ./schema_archive/
    ls -1 ./schema_archive | tail -n 4
    

    WordPress — Step 15 (drop‑in)

    ## Step 15 — Audit the exception, measure the motion, seal the record
    
    **New capabilities**
    - **Lease Audit Trails**: Every lease minted/used is written to append‑only `audit/leases.jsonl` and surfaced live on `/events` as `lease_*` SSE events.
    - **Path‑Level Hotness**: `GET /schema_hot?plugin=<name>&n=10` ranks schema paths by change score (adds/removes/typechanges). Use it to focus refactors and watch unstable interfaces.
    - **Signed Archives on Change**: With `--schema-archive-on-change`, each schema change writes a detached pair: `<ts>-<ALG>-<KID>.json` and `.sig` in `schema_archive/`. Algorithm is `Ed25519` if configured (preferred), else `HS256`.
    
    **Endpoints**
    - `GET /audit/leases?n=50[&token_hash=...][&subject=...]` — tail the latest lease events.
    - `GET /schema_hot?plugin=<name>&n=<N>` — top-N hot paths (score = added + removed + 2×typechanges).
    - `GET /schema_manifest` + `GET /schema_manifest.sig` + `GET /schema_pubkey` — verification remains as in Step 14.
    
    **Telemetry (new counters)**
    - `solveforce_schema_path_added_total{plugin,path}`
    - `solveforce_schema_path_removed_total{plugin,path}`
    - `solveforce_schema_path_typechanges_total{plugin,path}`
    
    **Why it matters**
    - We **allow** surgical exceptions (leases), but we **remember** each use (audit).
    - We make change **rank‑ordered** (hot paths) so engineering time meets the real friction.
    - We **attest** the map at each shift (archives), turning “trust us” into **proof**.
    

    Operational notes

    • SecurityAudit records carry token hashes only (no secrets). Leases are time‑boxed and plugin‑scoped; they do not bypass ACK or compat vows.
    • CardinalityPath counters cap at 200 unique (plugin,path) keys to keep Prometheus sane.
    • PortabilityEverything works on‑device in Termux. Ed25519 needs either pynacl or cryptography.

    Integrity (publish these for transparency)

    sha256sum solveforce_phone_fifteen.py
    # d027bb61eed7ca8aa8e7173d76de1f56262550b8767876d7805a7e700410ad99
    

    Logos Codex — recursive alignment

    • Exceptionwithout memory is entropy; exception with audit is discipline.
    • Changewithout measure is drift; change with hotness is direction.
    • Truthwithout attestation is promise; truth with signature is covenant.

    If you want Step 16, I’ll wire per‑lease replay (downloadable JSONL slices), budgeted hotness windows (last‑N hours), and archive notarization hooks (e.g., publish manifest digests to an external ledger).

    Key terms in plain language

    Open a term for a concise explanation of language used on this page.

    VoIP

    Voice over Internet Protocol carries phone calls over an IP network instead of a traditional analog phone line. Call quality depends on network stability, latency, and traffic management.

    Unified Communications (UCaaS)

    A cloud-based combination of business calling, messaging, meetings, presence, and collaboration tools managed as one communications service.

    SIP Trunking

    A service that connects a business phone system to the public telephone network using Internet Protocol, replacing or supplementing traditional phone lines.

    Bandwidth

    The amount of data a connection can carry in a given time, usually measured in Mbps or Gbps. More bandwidth supports more users, devices, and simultaneous applications.

    Latency

    The time it takes data to travel between two points. Lower latency improves voice, video meetings, cloud applications, gaming, and other real-time services.

    Service-Level Agreement (SLA)

    A provider’s written commitment covering service targets such as availability, response time, repair time, and sometimes financial credits when commitments are missed.