Skip to content

Fix storage decode policy - #28

Draft
GCdePaula wants to merge 7 commits into
mainfrom
feature/review-ledger-and-tracks
Draft

Fix storage decode policy#28
GCdePaula wants to merge 7 commits into
mainfrom
feature/review-ledger-and-tracks

Conversation

@GCdePaula

Copy link
Copy Markdown
Collaborator

Storage decode policy

convert.rs promised saturating conversions to keep corrupted DB rows from crashing the process, the opposite of docs/invariants.md's fail-loud policy. A 116-call-site audit found every non-test width-conversion site contract-bound, so the width converters now panic on out-of-range values instead of fabricating plausible ones. Deliberate saturation survives only where the full range is legal: clock conversions (F8), the new explicitly-named saturating_query_bound for WS cursors/limits, and the fee-policy clamps in query_batch_policy. Bonus from the audit: two saturating_adds on contract-bound counters became checked_add, and safe_accepted_batches.nonce gained its missing CHECK (nonce >= 0).

Housekeeping

Restore docs/review/. The squash that merged the cockroach branch dropped the review ledger while AGENTS.md/CLAUDE.md kept pointing at it. Restored with statuses updated: F7 (feed invalidation, high) stays open with PR #26 recorded as WP5's field-extension half, and the interim mirror rule (treat any socket drop as a discontinuity, rebuild the soft suffix) is now written down in-tree.

Record the 2026-07 coordination tracks. New docs/plans/ (indexed from CLAUDE.md/AGENTS.md) holding the plan of record for the in-flight efforts: feed & replay protocol redesign (generation id, historical replay endpoints), dump/Application API redesign, the LLM-docs review campaign, and the deferred fee LUT (exact-floor decided, pending a design decision that may retire log-space fees).

@GCdePaula GCdePaula changed the title Review ledger and tracks Fix storage decode policy Jul 30, 2026
@GCdePaula
GCdePaula force-pushed the feature/review-ledger-and-tracks branch from 1f6a8a1 to 9f1a644 Compare August 18, 2026 18:18
…story foundation

One process, one data directory, one way in: this lands the authority
boundary the 2026-08 ADR designed, with admission derived from durable
facts and history given real coordinates.

Process ownership and containment:
- Kernel-enforced one-process-per-data-dir (runtime/process_lock.rs); the
  controller retains the lock through settlement, nested blocking work
  retains clones until it actually stops.
- RuntimeScope: the runtime-lifetime capability (sticky containment
  OnceLock, independent two-second terminal-abort watchdog, best-effort
  fault recorder), constructible only from a held lock.
- The Authorized externalization token: acks, L1 sends, WS frames, and
  snapshot-stream starts require a token minted by consulting containment
  — forgetting the check is a compile error, not a convention.

Commands and the exit-code contract:
- commands/ owns the operator brackets (run + worker supervisor, setup +
  fill, flush); runtime/ is the capability substrate consumed crate-wide.
- One CommandError taxonomy with the R4 exit projection (10 expect
  recovery / 20 transient / 30 terminal, do not restart, page / 40 setup
  needs recovery); terminality declared beside each worker error type.

Fact-derived admission (reviews L2/L3):
- Admission is three facts, each with one owner: the process lock,
  two-sided setup_complete, and the absorbing canonical_divergence marker.
  No lifecycle state machine, no operator acknowledgement; standard
  recovery is automatic and cockroach rebuild is the one manual path.
- The only durable telemetry is the terminal_faults black box: append-only
  terminal-cause rows, written best-effort and verdict-neutrally.
- Boot is prepare -> admit (the same pure reducer re-run over one
  consistent fact set) -> single-use AdmittedRuntime -> non-yielding
  launch.

Startup recovery:
- A pure reducer over one transactionally consistent inspection selects at
  most one phase; every completed phase returns to inspection; flush/sync
  witnesses are boot-local and never persist.
- admission.tla proves terminal dominance, one-phase-per-inspection,
  witness requirements, crash/restart soundness, and capability soundness
  (TLC: 860 generated / 266 distinct / depth 13 / 0 violations).

Durable history foundation:
- (EraId, RecoveryGeneration, K) coordinates, each recorded at the moment
  it happens; the executed_inputs canonical projection; setup completion
  as a synchronous=FULL linearization point; snapshot lifecycle hardening
  (lease reset, GC, orphan sweep, promotion restamp).
- sequencer-core: one shared typed execution boundary writes the consensus
  coordinate; raw hooks are structurally unreachable; app-boundary decode
  and genesis paths return typed refusals.
The documentation practice gains a lifecycle, now recorded in AGENTS.md
("Documentation Practice"): living docs are timeless — present tense,
reasoning inline, no dates, no amendment banners, no review codenames —
while history lives only in docs/review/ and commit messages, and a review
ledger is distilled when it closes. Conclusions with reasoning outlive the
path taken to them. Plus the comment rule: comment the non-obvious, never
restate what the code expresses.

- docs/review/register.md is the new hub: open findings (statuses verified
  against the tree), owed tests with recipes and harness levers, open
  maintainer decisions, settled decisions with each reasoning's current
  home, refuted proposals (do-not-re-propose), and a historical codename
  map so older commit messages stay decodable. CLAUDE.md/AGENTS.md point
  there.
- All eight dated ledgers distilled to stubs or compact decision records
  (docs/review/ 2,392 -> 502 lines); full originals remain in git history.
- The authority-boundary ADR rewritten present-tense (769 -> ~210):
  context, the four mechanisms, rejected alternatives with their
  arguments, revisit conditions; cutover chronology and raw benchmark
  tables reduced to their conclusions. The superseded terminal-containment
  plan is deleted; the coordination-tracks doc is rewritten to current
  truth (Track 5's LUT rationale kept in full).
- Living docs scrubbed of tense leakage; the concepts formerly cited as
  review codes now have real names homed in invariants.md, which also
  gains the do-not-simplify list and I9's content-equal => effect-equal
  argument. ~90 codename citations removed from code comments and the
  schema.
- Adversarial review of the distillation (24 agents, three lenses):
  23 confirmed findings fixed. The lost-content lens restored two real
  casualties with updated homes: cockroach recovery's flush is best-effort
  by construction (no watermark survives the wipe; the fail-safe
  flush-floor option recorded) -> cockroach.md step 2 + register; and the
  supervisor recipes (systemd RestartPreventExitStatus; on Kubernetes the
  crash-loop bound is exit-code alerting, since Deployments cannot honor
  exit codes and there is no boot gate) -> the operator runbook.
L2TxFeedConfig::default() set batch_submitter_address to None — "filter
nothing", the I11-violating value — so the feed a test or future caller
got by default fanned our own batch envelopes out to WS subscribers.
Production was correct only because the runtime glue remembered to
override the default.

The address is now a required constructor argument and the Option is
threaded out end to end: the filter compares plain addresses (matching
the inclusion lane's spelling), and the unfiltered SQL arm in
storage/egress.rs — reachable only through the deleted default — is
gone. Fixtures that seed no own-batch rows pass a sentinel address that
collides with no seeded sender; Address::ZERO is a real fixture sender
and must not be used for that.
…he launch bracket

Simplification pass over the run-command startup glue, adversarially
reviewed: two verification rounds over the proposals and a fidelity
review over the landed diff. Behavior-preserving; operator-visible
deltas are limited to log fields (the "listening" line reports the
resolved bound address; drain warnings carry a structured `phase`).

- L1Config carries the pinned DeploymentIdentity verbatim, built once in
  run(): exactly one route to identity below the gate. The poster's
  start_block round-trip through the reader is gone, and the test
  fixture builds one identity literal instead of hand-copied fields.
- PreparedRuntime is now exactly the launch-argument bundle: config
  structs die in prepare (lane_config, api_config, snapshot_state,
  bound_addr in; run_config, l1_config, db_path, dumps_dir out), and
  launch is six spawns plus the "listening" log.
- The EIP-712 domain is derived in prepare from l1_config.identity —
  one source, now that the identity travels whole.
- ApiConfig owns the deployment-varying ingress values (domain, payload
  bound) via a mandatory constructor; the service limits stay module
  constants, documented as deliberately not operator-tunable.
  start_on_listener drops to six parameters.
- AdmittedRuntime is collapsed into launch(self, RuntimeAdmission): the
  witness is the mechanism, the wrapper was presentation. Vocabulary
  swept through AGENTS.md, the ADR, invariants, the recovery README and
  admission.tla comments; the spec's admittedRuntime state names are
  deliberately kept (TLC unchanged: 860/266/depth 13/0).
- finish's two drain loops merge into one two-phase loop with a single
  precedence match (contained > primary > signal > first drain error).
  The register's drain-merge refutation was scoped to the naive
  re-awaiting sketch ("as sketched" in the 2026-08-18 source); the
  entry is scope-narrowed with the source cited.
- select_first_exit destructures Self exhaustively, closing the one
  per-worker site a seventh worker could silently skip.
- Startup snapshot hygiene moves to commands/run/startup_hygiene.rs;
  its five order-critical steps were mis-documented as four.
- Fee-oracle bootstrap: RunFeeOracleBootstrapError deleted (exit codes
  proven unchanged; double-prefixed misconfig messages fixed); the
  transient connect arm reuses the provider it already built. The
  previously untested Some-limb drain path gets a pin.
- The WORKER_LAUNCH_COUNT probe and its global test mutex are deleted:
  the ProcessLock::acquire assertion is the stronger behavioral
  detector, and the tests it serialized are now independent.
The submitter's signing key rode through three Debug-derived structs
(KeyArgs inside RunConfig/FlushConfig, and L1Config) in plaintext hex —
one future ?config log away from leaking. It now enters the process as
SubmitterKey at the clap value_parser: Debug prints [redacted], no
Display exists (a %key log line is a compile error), and the raw hex is
reachable only through expose_secret(), whose call sites are the
provider builders and address derivation. A test pins that a carrier
struct's derived Debug never prints the secret.

No public-address accessor: the key's public identity is the pinned
identity.batch_submitter_address beside it, already in the startup log.
Closes the register's Debug-derive open finding; the startup log's full
RPC URL (token-bearing per the help-leak test's threat model) is a
recorded, deferred tension.
@GCdePaula
GCdePaula force-pushed the feature/review-ledger-and-tracks branch from a8c23eb to 5233880 Compare August 24, 2026 12:00
Require and persist a fresh fee quote during setup, then retain the last price across transient runtime failures.

Keep the process lock through cancellable feed preparation and make E2E mining follow the safe-block clock without synthesizing future L1 time.
Couple stopped-process outage time with L1 progress, update the backward-clock scenario to assert retryable admission denial, and keep the live stuck-Tip injection recoverable after its detector exit.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant