README (53269B)
1 # rhizome 2 3 This is the README for `rhi` which listens on Rad Roots networks and maintains 4 a stable activity record for parties buying and selling agricultural goods. 5 6 ## Public API boundary 7 8 The library exposes one curated crate-root API. Every implementation module is 9 private, and public errors use RHI-owned stable classifications with redacted 10 diagnostics and no raw dependency-owned source chain or caller path. The shared 11 runtime-path, service-SQLite, storage, event, and trade values that appear in 12 signatures are deliberate governed contract types; raw SQLx, Serde, transport, 13 filesystem, and task authority never crosses this boundary. 14 15 The shared clock and entropy traits and their source-free error values are also 16 deliberate governed injection contracts. RHI operations normalize their 17 failures into stable RHI classifications; concrete system adapters remain 18 private implementation details. 19 20 Child modules cannot bypass the reviewed root surface: 21 22 ```compile_fail 23 use rhi::features::trade_agreement_attestation::TradeAgreementAttestationPolicy; 24 25 fn bypass(_: TradeAgreementAttestationPolicy) {} 26 ``` 27 28 The reviewed all-features surface is frozen in the 29 [RHI API baseline](contracts/api_baselines/rhi.txt). 30 31 RHI publishes its service kind-0 Profile only through the sealed 32 `radroots_nostr` Profile builder after constructing the strict 33 `RadrootsAuthoredProfile` replacement snapshot. It does not retain a generic 34 kind-0 event-authoring path. 35 36 ## Injected runtime adapters 37 38 `RhiRuntimeAdapters` is the sealed composition boundary for all runtime inputs 39 that must remain replaceable in deterministic tests. It owns distinct injected 40 whole-second wall UTC, process-local monotonic time, and entropy sources; a 41 transport-neutral bounded event source, live subscriber, and publication sink; 42 ordered read-existing credential and independently verified encrypted-identity 43 access; and one private shared join-owning task supervisor. 44 45 Full jitter is measured only in whole milliseconds, is sampled from injected 46 entropy with rejection-sampled multiply-high mapping, is always in the 47 inclusive configured range, and is capped at the exact v1 maximum of 3,600,000 48 milliseconds. Sampling fails closed after sixteen rejected entropy draws, so a 49 bad adapter cannot hang scheduling. Jitter is never derived from wall-clock 50 nanoseconds. Event-authored time remains untrusted input and cannot substitute 51 for an injected observation time or a monotonic deadline. 52 53 Constructing the adapter set performs no clock read, entropy read, identity or 54 credential access, DNS lookup, network operation, or task spawn. Concrete 55 transport handles and the task supervisor remain sealed. The library installs 56 no signal handler, Tokio runtime, logger, or process-exit policy; the final 57 binary checkpoint owns those authorities. The exact machine contract is 58 [`runtime_adapters.v1.json`](contracts/services_hardening/runtime_adapters.v1.json). 59 60 ## Canonical trade-event admission 61 62 `admit_rhi_trade_mutation_event` is the sole accepted-ingest boundary for 63 signed trade mutations. It caps the original UTF-8 event before parsing, 64 measures decoded content, tags, tag elements, aggregate tag bytes, identifiers, 65 and non-authoritative outer extensions before the canonical decoder allocates 66 them, then independently verifies the NIP-01 identifier and Schnorr signature. 67 The promoted Lib contract performs the exact registered-kind, author, 68 canonical content and mutation-ID, and ordered structural-tag validation. 69 70 Observation time is injected. Future skew is an explicit caller-supplied 71 inclusive policy with no implicit default, while old events remain admissible 72 for lineage reconstruction. The sealed accepted value retains the exact 73 bounded input bytes plus the verified event and canonical typed mutation; 74 ordinary Debug output reveals only sizes, kind, authored time, and a redacted 75 identity marker. This pure boundary performs no clock read, network operation, 76 SQLite access, checkpoint update, or dirty-generation change. Its exact 77 machine contract is 78 [`trade_ingest.v1.json`](contracts/services_hardening/trade_ingest.v1.json). 79 80 ## Immutable trade-evidence persistence 81 82 `RhiStateRepositories::persist_trade_evidence` atomically retains three 83 separate immutable facts: one canonical mutation, every distinct valid signed 84 event carrying it, and every accepted configured-source observation. Signed 85 event identity is the verified Nostr event identifier plus its verified 86 signature, so independent valid signatures over the same canonical event are 87 not collapsed. Observation time is the injected admission time and remains 88 distinct from the event-authored time. 89 90 The source observation can be constructed only from a validated RHI 91 configuration and an admitted signed event. Exact replay is idempotent; 92 conflicting durable mutation or signed-event content fails closed; and the 93 three inserts share one SQLx transaction. This operation performs no network 94 I/O and does not advance reconciliation checkpoints or dirty generation. The 95 machine contract is 96 [`trade_evidence_persistence.v1.json`](contracts/services_hardening/trade_evidence_persistence.v1.json). 97 98 ## Bounded relay-source ingestion 99 100 `ingest_rhi_trade_source` resolves one explicit configured `nostr_relay` 101 source and its read-authorized relay, then fetches the exact five trade-mutation 102 kinds under the requested trade's indexed `#d` tag. It uses one absolute 103 configured deadline, pages at no more than 1,000 events, and admits at most 104 4,096 distinct signed-event identities (event ID plus signature) and 8 MiB of 105 original event bytes per attempt. 106 Every returned event still passes the sealed signature, identifier, mutation, 107 tag, trade, and authored-time boundary before it can affect durable state. 108 109 Only exact-target EOSE before the deadline is complete. Cancellation, 110 unavailability, bounded-result exhaustion, partial or malformed results, and 111 unsupported operation remain distinct incomplete outcomes and cannot advance a 112 checkpoint. Checkpoints are scoped by source, selector, evidence-policy digest, 113 and trade; their authored-time plus verified-event-ID cursor uses configured 114 overlap so equal timestamps remain discoverable. One short generation-fenced 115 SQLx transaction persists admitted evidence and an eligible checkpoint. 116 Relevant newly inserted mutation or signed-event evidence advances the 117 per-trade dirty generation; rejection, verified-event replay, repeated source 118 observation, and operational retry do not. Source fetching never occurs inside 119 a database transaction. The exact machine contract is 120 [`trade_source_ingest.v1.json`](contracts/services_hardening/trade_source_ingest.v1.json). 121 122 ## Durable reconciliation jobs 123 124 `RhiReconciliationJobRepository` schedules at most one active job per trade 125 against the exact durable dirty generation and evidence-policy digest. Job IDs 126 are deterministic domain-separated SHA-256 identities, exact scheduling is 127 idempotent, a newer dirty generation atomically supersedes the prior active 128 job, and the configured queue capacity is enforced beneath a fixed 65,536-job 129 hard ceiling. 130 131 Claims and renewals are compare-and-swap transitions over an immutable job 132 identity and monotonic revision. Leases use caller-injected 16-byte owner 133 tokens and integer UTC milliseconds; expired leases can be reclaimed, while 134 an expired final attempt becomes exhausted. Failed attempts persist their next 135 eligible time using caller-injected full jitter bounded by the job's governed 136 exponential backoff. No ambient clock or entropy is read, and no source or 137 network work occurs inside a database transaction. The exact machine contract 138 is 139 [`reconciliation_jobs.v1.json`](contracts/services_hardening/reconciliation_jobs.v1.json). 140 141 ## Bounded reconciliation source attempts 142 143 `RhiReconciliationAttemptPlan` derives one canonical source-request inventory 144 from an unexpired claimed job lease and the exact normalized evidence policy. 145 The attempt, selector, and each source request have domain-separated SHA-256 146 identities. Every request binds the source ID, required/optional authority, 147 trade selector, absolute deadline, lookback, and configured result limits. 148 The claimed job's retained lease, retry, and attempt policy must also equal the 149 exact normalized configuration; queue capacity remains admission authority for 150 new jobs rather than per-attempt identity. The attempt deadline and every 151 source deadline are capped by the retained lease expiry; no implicit clock or 152 deadline is consulted. 153 154 `RhiReconciliationSourceResult` records one stable completion code, explicit 155 start and finish times, and bounded accepted-event count and bytes. Exact EOSE 156 completion must occur before the source deadline, timeout begins at the 157 deadline, unsupported sources cannot report accepted events, and no outcome 158 can be omitted, duplicated, reordered, or appended beyond the configured 159 source inventory. Planning and result validation are pure and perform no 160 SQLite, source, relay, network, filesystem, task, clock, or entropy operation. 161 Cursor derivation, source execution, and durable completion commit remain with 162 their later ordered checkpoints. The exact machine contract is 163 [`reconciliation_attempts.v1.json`](contracts/services_hardening/reconciliation_attempts.v1.json). 164 165 ## Overlap-safe reconciliation replay 166 167 `RhiReconciliationSourceReplayPlan` binds one exact source request to optional 168 sealed prior-cursor evidence, configured overlap, and an inclusive query start 169 under a domain-separated identity. The evidence is sealed to the source, 170 trade, evidence-policy digest, and selector digest, so callers cannot forge or 171 relabel progress. This pure replay model provides no evidence-minting path; the 172 atomic commit boundary below alone constructs it after replay and cursor commit. 173 Initial 174 queries use the configured lookback; resumed queries subtract the configured 175 overlap from the prior authored-time 176 cursor so equal-timestamp events remain discoverable. A cursor becomes 177 eligible only after exact `complete` source evidence, but remains an in-memory 178 candidate that this pure model cannot promote to resumption authority. 179 180 The replay inventory consumes at most the request event limit plus one and 181 bounds all original event bytes before deduplication. It accepts only the 182 request's trade, orders admitted signed events canonically, collapses exact 183 event replay, retains the earliest injected source observation, and rejects 184 conflicting mutation or signed-event identity reuse. Result counts and bytes 185 are derived from the distinct canonical inventory rather than caller claims. 186 It performs no SQLite, source, relay, network, filesystem, task, clock, or 187 entropy operation. Durable scope revalidation, result/completion persistence, 188 and checkpoint advancement belong to the atomic commit boundary below. The 189 exact machine contract is 190 [`reconciliation_replay.v1.json`](contracts/services_hardening/reconciliation_replay.v1.json). 191 192 ## Atomic reconciliation result commit 193 194 `RhiReconciliationAttemptRepository::commit_source_replays` accepts exactly one 195 bounded replay result for every request in a claim-derived attempt. One short 196 SQLx transaction first revalidates the exact live lease, trade dirty generation, 197 evidence-policy digest, and each source-scoped prior checkpoint. It then commits 198 canonical mutations, signed events, first-source observations, the immutable 199 attempt and source-result inventory, a domain-separated digest of every exact 200 ordered persisted fact and provenance value, at most one dirty-generation 201 advance, and only eligible cursor checkpoints as one atomic unit. No source, 202 relay, network, clock, entropy, or task operation occurs inside that 203 transaction. 204 205 Only exact `complete` evidence with a strictly newer candidate advances a 206 checkpoint. Timeout, unavailable, resource-limited, unknown, and unsupported 207 results remain durable but never become progress. Newly inserted canonical 208 mutation or signed-event evidence advances the dirty generation once for the 209 whole attempt; observation-only replay does not. Exact retry of an already 210 committed attempt reconciles idempotently before stale lease or generation 211 fences, while any inventory mismatch fails closed. Sealed source/trade/policy/ 212 selector cursor evidence is minted only after durable commit confirmation. The 213 exact machine contract is 214 [`reconciliation_commit.v1.json`](contracts/services_hardening/reconciliation_commit.v1.json). 215 216 ## Immutable reconciliation manifest 217 218 `RhiReconciliationSourceCommitOutcome::into_evidence_manifest` consumes one 219 sealed, durably confirmed Step 190 outcome and freezes its exact canonical 220 mutation, signed-event, first-provenance, and per-source completion inventory 221 into the shared `radroots.trade.evidence-manifest.v1` encoding. The manifest 222 binds the claimed trade generation and evidence-policy digest. Each source 223 result additionally binds its exact selector digest, detailed completion, 224 timing, cursor inputs, checkpoint eligibility, and Step 190 persisted-inventory 225 digest. Each observation binds the verified mutation and event identities, the 226 SHA-256 of the exact canonical signed-event JSON, and a source/selector/policy/ 227 signature/first-observation provenance digest. 228 229 Sources and observations use the shared canonical ordering, so arrival and 230 insertion order cannot select truth. The explicit whole-second observation 231 time cannot precede any committed source finish, and the explicit closed scope- 232 prerequisite input is included in the immutable bytes. Callers can inspect only 233 the redacted sealed result's identity, counts, canonical bytes, and digest; they 234 cannot construct a manifest from uncommitted replay material or supply its 235 result/provenance digests. Materialization is pure and performs no SQLite, 236 filesystem, source, relay, network, task, clock, or entropy operation. Durable 237 manifest persistence remains deferred to Step 199, and reduction, final 238 coverage/outcome, attestation, and publication retain their later checkpoint 239 owners. The exact machine contract is 240 [`reconciliation_manifest.v1.json`](contracts/services_hardening/reconciliation_manifest.v1.json). 241 242 The Step 192 integration-wave qualification proves that concurrent exact 243 commits converge to one durable attempt and byte-identical manifest, a blocked 244 commit can be cancelled with no authoritative effect and retried, an exact 245 lost-success retry converges after close/reopen, and an infinite replay 246 inventory terminates at configured source count plus one before mutation. The 247 same corpus covers exact source deadlines, incomplete checkpoint exclusion, 248 lease expiry/reclaim, queue and result bounds, stale leases/generations, and 249 durable reopen behavior without adding runtime, scheduler, source, or network 250 authority. 251 252 ## Pure reconciliation reducer 253 254 [`reconciliation_reducer.v1.json`](contracts/services_hardening/reconciliation_reducer.v1.json) 255 binds the promoted shared `radroots.trade.reducer.v1` to one sealed confirmed 256 reconciliation manifest. The manifest privately retains only the bounded 257 canonical mutation material derived from its Step 190 commit; callers cannot 258 inject or replace reducer inputs. Reduction consumes the owned manifest, 259 retains it inside a sealed projection, and binds the shared projection digest 260 to the manifest and evidence-policy digests with a separate domain-separated 261 RHI digest. The projection retains the canonical shared result privately for 262 later checkpoints while exposing only bounded identity, digest, and count 263 evidence. 264 Reduction performs no SQLite, filesystem, source, relay, network, task, clock, 265 or entropy operation. Generation-fenced persistence, reports, attestations, 266 and publication retain their later checkpoint owners. 267 268 [`reconciliation_outcome.v1.json`](contracts/services_hardening/reconciliation_outcome.v1.json) 269 derives one claim-specific evaluation from that sealed projection. 270 Coverage is exactly `Missing`, `Partial`, `ScopeSatisfied`, or `Unsupported`; 271 outcome is 272 exactly `Valid`, `Invalid`, or `Indeterminate`. Missing, partial, unsupported, 273 digest-unavailable, unresolved, ambiguous, or absent-claim evidence is always 274 indeterminate. Only a clean active agreement claim is valid, and only a clean 275 cancelled agreement claim is decisively invalid. Every evaluation retains its 276 projection and exposes exactly one closed stable primary reason code without 277 adding I/O or ambient authority. 278 279 ## Generation-fenced finalization preflight 280 281 `RhiReconciliationAttemptRepository::prepare_finalization` consumes one sealed 282 evaluation plus the exact live claimed lease. The manifest privately retains 283 its Step 190 attempt and job identities without changing canonical manifest 284 bytes or its digest, so an older attempt cannot be relabelled with a reclaimed 285 worker's distinct attempt authority. One bounded read-only SQLite transaction 286 checks the unexpired exact lease, current dirty generation, evidence-policy 287 digest, and immutable committed-attempt row before returning a sealed 288 `RhiReconciliationFinalizationFence`. 289 290 The fence is a preflight capability, not durable commit proof: state may change 291 after it is returned. Step 199 must rerun the same validator inside the final 292 atomic transaction before its first write. This checkpoint writes no manifest, 293 projection, report, signed event, outbox, checkpoint, or job state and performs 294 no source, relay, network, filesystem, task, clock, or entropy operation. The 295 exact machine contract is 296 [`reconciliation_finalization.v1.json`](contracts/services_hardening/reconciliation_finalization.v1.json). 297 298 ## Canonical signed reconciliation attestation 299 300 `build_rhi_signed_evidence_attestation` consumes one sealed Step 195 301 finalization fence and derives the shared canonical RHI evidence report only 302 from its immutable manifest, projection, evaluation, and claim identity. The 303 report issuer is the independently verified encrypted service identity. The 304 optional supersession reference can be derived only from an earlier sealed, 305 verified signed-attestation result, and the shared ordering validator rejects 306 stale or misbound successors. 307 308 The event body and exact kind-3441 structural tags come only from the promoted 309 typed `radroots_event_codec` builder. Authored time and the 32 bytes of Schnorr 310 auxiliary randomness are injected explicitly. The boundary then independently 311 reparses the bounded signed NIP-01 JSON, recomputes its event identifier, 312 verifies its signature and exact plan fields, decodes the typed attestation, 313 reparses the canonical report, and revalidates its exact manifest binding. 314 315 The sealed result owns the finalization fence, canonical report, verified event 316 identifier, exact signed bytes, and the SHA-256 of those bytes. Later 317 persistence must retain those bytes without rebuilding, reserializing, or 318 re-signing them. This checkpoint performs no SQLite, filesystem, relay, 319 network, task, ambient-clock, or ambient-entropy operation. The schema-v7 320 catalog is frozen by Step 198; the generation-fenced write, publication, and 321 job finalization remain with Step 199 and its successors. The exact machine contract is 322 [`reconciliation_attestation.v1.json`](contracts/services_hardening/reconciliation_attestation.v1.json). 323 324 ## Explicit publication authority and durable schema 325 326 `RhiPublicationAuthority::from_config` is the sole public derivation boundary 327 for publication intent. It consumes one complete validated RHI configuration 328 and returns exactly `Required` or `Disabled`. Required authority preserves the 329 explicit ordered write-relay targets, each target's requiredness, the bounded 330 retry policy, and queue capacity under separate domain-separated target-set 331 and complete-authority digests. Disabled authority contains no target or retry 332 state and authorizes no hidden network work. The sealed result exposes no URL, 333 credential, transport, SQLite, clock, entropy, or task authority. 334 335 Schema v7 freezes immutable manifest, projection, report, exact signed-event, 336 and publication-attempt records plus compare-and-swap outbox and target rows. 337 No-update/no-delete triggers protect semantic payload and target identities; 338 the closed target evidence vocabulary distinguishes pending, submitted, 339 accepted, rejected, rate-limited, auth-required, failed, and unknown. This 340 checkpoint defines and verifies the catalog only. Step 199 owns the first 341 atomic finalization write, and Steps 200-203 own claims, relay submission, 342 outcomes, retry, recovery, and wave qualification. The exact machine contract 343 is 344 [`publication_outbox.v1.json`](contracts/services_hardening/publication_outbox.v1.json). 345 346 ## Deterministic durable presence intent 347 348 `RhiPresenceDesiredAuthority::from_config` derives the exact ordered 349 service-profile and application-handler intent from one complete admitted 350 configuration. It binds the verified service public identity, the configured 351 relay-ID order and requiredness, and the bounded presence queue under separate 352 domain-separated target-set and semantic desired-state digests. An independent 353 validator re-derives that authority from the same complete configuration. 354 355 Schema v9 stores only one sealed semantic desired-state snapshot. The first 356 commit creates generation one, exact semantic replay performs no write, and a 357 semantic change advances exactly one compare-and-swap generation. Every commit 358 must still match the latest durable configuration binding. The table stores no 359 relay URL, filesystem path, rendered event, signature, authored time, delivery 360 attempt, or network result, and its triggers reject deletion and ungoverned 361 updates. Rendering, signing, target delivery state, retries, and relay I/O remain 362 separate from this semantic-intent commit. The exact machine contract is 363 [`presence_desired_state.v1.json`](contracts/services_hardening/presence_desired_state.v1.json). 364 365 ## Durable exact-byte presence publication 366 367 `build_rhi_signed_presence_documents` consumes one committed desired-state 368 generation, the independently revalidated complete presence authority, the 369 matching decrypted service identity, caller-injected authored time, and 370 caller-injected Schnorr auxiliary entropy. It builds the kind-0 service profile 371 through the typed `radroots_event` profile plan and cross-checks the kind-31990 372 application-handler plan produced by `radroots_nostr` against the typed 373 `radroots_event` plan. Every signed document is then independently parsed under 374 the bounded NIP-01 wire limits and revalidated for event ID, signature, author, 375 kind, time, ordered tags, and exact content before exposure. 376 377 Schema v10 retains each independently verified exact signed byte sequence, 378 digest, document identity, and complete immutable target inventory. One short 379 SQLx-owned transaction commits those bytes and initial target state before any 380 injected `RhiExactPresenceSink` can observe them. A second short transaction 381 commits `submitted` before remote I/O. The remote await owns no transaction; 382 the first commit borrows rather than consumes its sealed document set, so an 383 unknown commit result can be reconciled by replaying the same retained bytes; 384 the resulting closed outcome, immutable attempt evidence, target schedule, 385 outbox disposition, and lease release are committed together afterward. 386 Cancellation or acknowledgement loss after `submitted` becomes durable 387 `unknown` before the same retained bytes can be retried. Expired work from a 388 superseded desired generation is recorded as `unknown` and the old outbox is 389 superseded without sampling retry entropy, preventing stale leases from 390 blocking the current generation forever. No retry parses, rebuilds, 391 reserializes, or re-signs an event, and no raw relay diagnostic is persisted. 392 The exact machine contract and deterministic signed vectors are 393 [`presence_publication.v1.json`](contracts/services_hardening/presence_publication.v1.json). 394 395 ## Atomic reconciliation finalization commit 396 397 `RhiReconciliationAttemptRepository::commit_finalization` borrows one sealed, 398 independently verified signed attestation and the publication authority derived 399 from the same normalized configuration as the open state host. One short 400 SQLx-owned transaction first reconciles an exact prior success, then reruns the 401 live lease, dirty-generation, policy, committed-attempt, source-inventory, 402 checkpoint, supersession, and publication-capacity fences before its first 403 write. 404 405 The same transaction retains the exact canonical manifest, projection, 406 canonical report, and independently verified signed-event bytes; records the 407 explicit supersession; creates the immutable outbox and ordered target set only 408 when publication is required; and completes the exact reconciliation job. 409 Disabled publication creates no outbox or target row. An exact retry returns 410 `created = false` even after the lease was consumed or expired, while any 411 mismatched durable footprint fails closed. This boundary performs no source or 412 relay I/O, network access, filesystem access, task spawn, ambient clock read, 413 or ambient entropy read. Publication claims and relay submission remain later 414 steps. The exact machine contract is 415 [`reconciliation_finalization_commit.v1.json`](contracts/services_hardening/reconciliation_finalization_commit.v1.json). 416 417 ## Exact committed publication bytes 418 419 `RhiPublicationOutboxRepository::read_committed_publication` joins one immutable 420 schema-v7 outbox to its signed-attestation row in one bounded read-only SQLx 421 transaction. It admits at most 32,768 stored bytes, rechecks the exact outbox, 422 event-identifier, and SHA-256 bindings, and returns a sealed 423 `RhiCommittedPublication`. Repeated reads and reads after a clean close/reopen 424 return the same committed byte string or fail closed. 425 426 The capability is not a relay claim or lease. Its only payload accessor returns 427 the stored bytes unchanged; this path contains no JSON or event parsing, 428 rebuilding, reserialization, signing, relay/network/filesystem work, task 429 spawn, or ambient clock/entropy access. The closed target/attempt evidence model 430 is defined below; durable claims and transitions, relay I/O, retry scheduling, 431 and lease recovery remain with Step 202. The exact machine contract is 432 [`publication_submission.v1.json`](contracts/services_hardening/publication_submission.v1.json). 433 434 ## Bounded publication attempt evidence 435 436 The publication target state is one closed value: pending, submitted, accepted, 437 rejected, rate-limited, auth-required, failed, or unknown. Pending is not an 438 attempt outcome, Accepted is the sole terminal target state, submission alone 439 does not prove relay delivery, and Unknown can be refined only by independent 440 evidence. Attempt outcomes use the same closed vocabulary except Pending and 441 expose no arbitrary result string or upstream diagnostic. 442 443 `RhiPublicationAttemptEvidence` binds the sealed committed outbox identity and 444 exact event digest to a zero-based target ordinal no greater than 31, a 445 one-based attempt number no greater than 100, ordered injected integer UTC 446 milliseconds, and one closed outcome under a domain-separated SHA-256 identity. 447 It is pure bounded evidence rather than claim, transition, or relay authority. 448 Step 202 must revalidate live target, lease, revision, attempt, and exact-byte 449 bindings when it persists Submitted before I/O and later commits an observed 450 outcome. The exact machine contract is 451 [`publication_attempt_evidence.v1.json`](contracts/services_hardening/publication_attempt_evidence.v1.json). 452 453 ## Durable exact-byte publication execution 454 455 `RhiPublicationOutboxRepository` claims one due outbox with an injected 456 nonzero owner and bounded lease only after binding the outbox and complete 457 target inventory to the exact current required-publication authority. It 458 persists the exact target as Submitted before remote I/O and exposes the 459 original committed byte slice only through `RhiExactPublicationSink`. This 460 dedicated boundary deliberately does not pass the payload through the generic 461 typed-event sink: retries never parse, reconstruct, reserialize, or re-sign 462 committed evidence. 463 464 Observed outcomes append one immutable attempt row and compare-and-swap the 465 target, persisted retry schedule, outbox disposition, and lease release in one 466 short SQLx-owned transaction. Full-jitter exponential backoff uses only 467 injected entropy. Cancellation or acknowledgement loss after Submitted remains 468 Unknown; expired-lease recovery appends that conservative evidence before an 469 exact-byte retry or exhaustion. No transaction remains open across relay I/O, 470 and an unknown local commit must be reconciled by exact attempt identity. The 471 exact machine contract is 472 [`publication_execution.v1.json`](contracts/services_hardening/publication_execution.v1.json). 473 474 Step 203 closes this wave with executable crash/reopen, shared transactional 475 failpoint, concurrent-claim, queue-bound, and redaction qualification. Schema 476 v8 first scans every historical reconciliation job and fails closed without 477 repair when a `ready` schedule or `leased` owner/expiry is missing. Only after 478 that scan succeeds does the same governed migration install permanent INSERT 479 and UPDATE state-shape guards. The exact qualification inventory and bounds are 480 [`publication_wave_qualification.v1.json`](contracts/services_hardening/publication_wave_qualification.v1.json). 481 482 ## Existing-state runtime foundation 483 484 `open_rhi_runtime_foundation` opens only an already initialized database from 485 the sealed service-instance intent, discovers its source generation under the 486 retained writer authority, verifies the latest append-only configuration 487 binding, and then resolves the credential before independently opening the 488 encrypted service identity. Missing state is never initialized by ordinary 489 startup. No evidence source, live subscription, or publication sink is 490 contacted before the durable configuration binding is proven. 491 492 The passive readiness snapshot initially proves only existing state, durable 493 configuration, and verified identity. Recovery, source connectivity and 494 subscription, publication recovery, admin and optional operations listeners, 495 and configured presence desired state remain explicitly unsatisfied for their 496 later owning checkpoints. Reading the snapshot performs no filesystem, 497 SQLite, credential, identity, DNS, or network probe. The foundation installs 498 no signals, runtime, logger, or process-exit policy and does not claim the final 499 supervised task graph. Its exact machine contract is 500 [`runtime_foundation.v1.json`](contracts/services_hardening/runtime_foundation.v1.json). 501 502 ## Passive lifecycle status and TCP operations 503 504 `rhi_status_cache` retains exactly one latest immutable RHI lifecycle and 505 detailed-status publication behind a single non-cloneable publisher. Each 506 publication is bounded and validated before it replaces the prior snapshot. 507 Readers clone only passive cache authority; they perform no SQLite, 508 filesystem, evidence-source, relay, DNS, identity, credential, clock, or fresh 509 probe operation. Detailed JSON is reserved for the permissioned Unix-admin 510 surface and contains only the closed service identity, evidence transport, 511 reconciliation, publication, presence, persistence, configuration, build, and 512 stable reason vocabularies. Its exact contract is 513 [`status_cache.v1.json`](contracts/services_hardening/status_cache.v1.json). 514 515 When the validated operations block is enabled, `RhiOperationsServer` exposes 516 exactly HTTP/1.1 `GET /livez`, `GET /readyz`, and `GET /metrics` on its admitted 517 TCP address. Requests read only the latest cached lifecycle/readiness and two 518 fixed bounded metric families; they cannot register another route or reach 519 detailed status. Requests perform no SQLite, filesystem, evidence-source, 520 relay, DNS, identity, credential, clock, or active health probe. The listener 521 is disabled by default and remains a supervisor-owned optional adapter. Its 522 exact contract is 523 [`tcp_operations.v1.json`](contracts/services_hardening/tcp_operations.v1.json). 524 525 ## Hardened v1 configuration contract 526 527 The target service configuration is frozen by 528 `contracts/services_hardening/config.v1.schema.json` and the canonical 529 non-secret `config.v1.example.toml`. It is one strict immutable TOML document 530 with explicit identity, relay, evidence-source, reconciliation, attestation, 531 publication, presence, resource, and retention authority. The evidence fields 532 and maxima consume `evidence_policy.v1.json` without reinterpretation. Only 533 reviewed bounded operational leaves have defaults. Bootstrap profile, 534 instance, repo-local root, and config-path selection are CLI concerns and are 535 not document fields. 536 537 The retired root `config.toml`, transitional runtime loader, JSON state 538 adapter, environment and worker selectors, and prototype smoke/runtime paths 539 are removed. The executable admits one strict CLI invocation and one sealed 540 runtime context, then fails closed until later ordered checkpoints bind each 541 command to its governed state and runtime authority. It never falls back to a 542 prototype execution path. 543 544 `parse_rhi_config_v1` is the strict in-memory admission boundary for the target 545 document. It bounds original bytes before parsing, rejects malformed duplicate 546 or null TOML and unknown fields, validates the bootstrap-selected relay posture 547 and all cross-field relationships, and returns an immutable document with a 548 deterministic bounded redacted effective projection. The projection records the 549 exact `toml` or `safe_default` origin for every leaf and the governed authority 550 behind each safe default. Parsing performs no filesystem, environment, 551 identity, database, clock, entropy, logging, DNS, or network operation. 552 553 ## Hardened v1 command admission 554 555 `parse_rhi_cli_v1_from` parses the bootstrap and closed command tree exactly 556 once. Every invocation explicitly selects `service-host`, `interactive`, or 557 `repo-local`, a validated instance, and optionally an absolute configuration 558 path. Repo-local selection additionally requires one absolute base root and 559 that root is forbidden for the other profiles. Human output is the default; 560 governed JSON output is selected explicitly. 561 562 The command inventory covers daemon run; config init, validate, show, schema, 563 and apply; state init, status, backup, restore, verify, and migrate; service 564 identity init, status, and public export; service status and metrics snapshot; 565 reconciliation status, jobs, and refresh; source listing; trade projection and 566 report queries; publication backlog, targets, and retry; desired-presence 567 inspection, render, and refresh; and doctor. The parser performs no command 568 execution. The admitted invocation projects once into a sealed execution plan: 569 `run` selects daemon authority; config initialization, validation, schema, and 570 apply, exclusive state maintenance, initial identity provisioning, and doctor 571 select offline authority; and the remaining twenty commands map one-to-one to 572 the final twenty permissioned Unix-admin routes. No live command carries an 573 offline or direct-SQLite fallback. Later ordered steps bind each command's exact 574 input and execute the already-selected authority without reparsing arguments. 575 576 Ordinary `run` accepts no identity-generation, identity-path, log-path, 577 database-path, worker, environment-file, or arbitrary path-leaf flag. Identity 578 rekey and replacement are not commands; rotation is a create-new offline 579 artifact plus governed configuration apply. 580 581 ## Bounded active doctor and stable process results 582 583 The doctor runs the governed fifteen checks in exact contract order. Each 584 check has one fixed deadline, required or optional authority, a closed evidence 585 scope, and a safe remediation code. Required checks must pass; required 586 failure, timeout, or an invalid skipped result makes the aggregate `fail`. 587 Optional non-pass makes the aggregate `degraded`, while every passing check 588 makes it `pass`. A timed-out probe is cancelled by dropping its future, and no 589 detached probe work is permitted. 590 591 The compact canonical JSON report is capped at 8,192 UTF-8 bytes. Its summaries 592 come only from the fixed content-free vocabulary and cannot contain paths, raw 593 errors, relay text, identifiers, credentials, or other protected material. 594 Required failure or timeout returns exit code `6`; the complete process-result 595 contract is the closed zero-through-six inventory in 596 [`operator_contract.v1.json`](contracts/services_hardening/operator_contract.v1.json). 597 The executable emits only the stable result code on stderr and never renders a 598 parser, path-resolution, dependency, or internal error. 599 600 ## Unix-admin boundary 601 602 Step 206 bound the seven common RHI routes for detailed status, redacted 603 effective configuration, service-identity status and public export, state 604 status, online backup, and a bounded metrics snapshot to the shared 605 `radroots_service_host` HTTP/1.1-over-Unix server. The public RHI route and 606 document types are closed, response construction admits only bounded compact 607 canonical JSON matching the exact machine model, and public diagnostics retain 608 no path, request, identity, or dependency-owned cause. 609 610 The server projects only the normalized configuration's admitted transport 611 limits, derives `admin.sock` only from the sealed runtime context, acquires the 612 shared writer authority before binding, and uses the shared server's system 613 entropy for absent correlation IDs. Construction does no I/O; binding does not 614 spawn; serving remains a later supervised runtime responsibility. Raw shared 615 routers, listeners, JSON values, and caller-selected socket paths never cross 616 the public RHI boundary. Its historical partial machine contract is 617 [`admin_common.v1.json`](contracts/services_hardening/admin_common.v1.json). 618 619 Step 207 cumulatively activates the thirteen reconciliation, job, source, 620 trade projection/report, publication target/backlog, retry, and presence 621 domain routes. Page sizes stop at 200; query names and duplicates are closed; 622 cursors use canonical base64url without padding and remain authenticated and 623 bound by the handler to the same route, filters, and snapshot. Every decoded 624 `{trade_id}` is exactly 32 lowercase hexadecimal characters. Mutations retain 625 stable operation-ID exact replay and conflicting-reuse rejection, and success 626 still means the handler's contract-defined local effect is durably committed, 627 not relay delivery. The adapter performs no SQLite or relay I/O itself. The 628 Step 208 removes the two never-registered live identity rekey/replace routes, 629 their three mutation-only models, and the unused operator types that could have 630 suggested live provider authority. Identity rotation is only offline create-new 631 envelope plus validated configuration apply and restart. Unix peer authorization 632 remains a transport admission gate and grants neither direct SQLite nor 633 identity-provider mutation authority. Step 209 qualifies the complete 634 20-route/33-model inventory with real Unix-socket original-wire, version, 635 pagination, idempotency, peer-permission, removed-route, and resource negative 636 matrices plus the exact source-locked shared-transport corpus. The cumulative 637 domain contract is 638 [`admin_domain.v1.json`](contracts/services_hardening/admin_domain.v1.json). 639 The offline identity correction is 640 [`admin_identity_offline.v1.json`](contracts/services_hardening/admin_identity_offline.v1.json). 641 The completed admin-wave qualification is 642 [`admin_wave_qualification.v1.json`](contracts/services_hardening/admin_wave_qualification.v1.json). 643 644 ## Sealed service-instance paths 645 646 One validated CLI invocation resolves through `RhiRuntimeContext`, which owns 647 the shared typed `RuntimeContext`, exact common artifacts, the validated 648 `service.identity.ncrypt` encrypted identity artifact path, and the explicit or 649 canonical configuration selection. The service identity is fixed to `rhi`; the instance 650 comes only from `InstanceId`; profile and repo-local-root provenance are the 651 closed `bootstrap_cli` vocabulary. Callers cannot construct or mutate another 652 path set, override artifact names, or obtain a public path report. 653 654 Service-host roots are exactly 655 `/etc/radroots/services/rhi/<instance>`, 656 `/var/lib/radroots/services/rhi/<instance>`, 657 `/var/cache/radroots/services/rhi/<instance>`, 658 `/var/log/radroots/services/rhi/<instance>`, 659 `/run/radroots/services/rhi/<instance>`, and 660 `/etc/radroots/secrets/services/rhi/<instance>`. Interactive roots consume the 661 injected host environment defined by `radroots_runtime_paths`; repo-local uses 662 one explicit absolute base and the same `services/rhi/<instance>` namespace. 663 Path resolution performs no directory creation or filesystem I/O. 664 665 ## Governed SQLite catalog 666 667 RHI owns one `state.sqlite` per service instance. Create-new initialization 668 starts from the shared schema-v1 baseline and immediately applies the pinned 669 schema-v2 configuration migration, schema-v3 immutable trade-evidence 670 migration, schema-v4 source-checkpoint and dirty-generation migration, 671 schema-v5 bounded reconciliation-job migration, schema-v6 immutable 672 reconciliation-result migration, and schema-v7 immutable report, signed-event, 673 publication-workflow migration. Schema v8 adds reconciliation-attempt replay 674 evidence, schema v9 adds durable presence desired state, and schema v10 adds 675 the exact-byte presence outbox, target, and attempt inventory. 676 Version ten contains the six shared immutable service-metadata and 677 migration-ledger objects, the bounded append-only `rhi_config_bindings` table, 678 separate immutable tables for canonical mutations, signed Nostr events, and 679 accepted source observations, and generation-guarded relay checkpoints and 680 per-trade dirty generations with their enforcement triggers and indexes. 681 It also retains immutable attempt, source-result, manifest, projection, report, 682 signed-event, and publication-attempt rows plus compare-and-swap outbox and 683 target state under exact transition and retention triggers. 684 Exact literal SHA-256 values bind both migrations, every schema snapshot, and 685 the schema catalog. RHI validates every identity before it can become database 686 authority. 687 688 The configuration history retains at most 1,024 consecutive generations. Each 689 row stores only normalized configuration and evidence-policy digests, the 690 public service identity, exact contract versions, injected apply time, and 691 bounded build identity. It never stores raw TOML, paths, relay URLs, credential 692 references, or protected identity material. Startup requires the latest row to 693 match the admitted document. `apply_rhi_configuration` obtains exclusive 694 offline authority, verifies the current binding, appends the candidate 695 atomically, treats exact replay idempotently, and explicitly closes state. 696 697 Catalog construction itself performs no filesystem or SQLite I/O and owns no 698 pool, connection, transaction, query, or migration executor. The sealed state 699 host alone executes the governed migrations and typed state transactions. 700 Evidence manifests, reports, attestations, publication state, and final job 701 completion remain reserved for their later owning checkpoints. 702 703 The sealed RHI state-host lifecycle now reserves and initializes a missing 704 canonical database only through an explicit create-new operation. Ordinary 705 writable and immutable inspection modes open existing state only, validate the 706 exact schema and migration identities, and retain mutually exclusive shared 707 authority until explicit idempotent close. Missing state is never initialized 708 by an open operation. No raw host, pool, connection, transaction, executor, or 709 path escapes the RHI wrapper. 710 711 One sealed RHI state-metadata capability now binds that lifecycle to the exact 712 service and instance, nonzero source generation, `RDRH` SQLite application ID, 713 schema version, creation time, fully normalized configuration digest, 714 contract-defined evidence-policy digest, expected service public identity, and 715 configuration/state/admin/status/provider contract versions. Its fields are 716 immutable; ordinary Debug and errors redact paths, identities, generations, 717 and digests. 718 719 The governed encrypted-file identity boundary accepts only the shared 720 version-2 `radroots_secrets` envelope, binds its authenticated context to the 721 service role, expected public key, payload schema, and separately named 722 wrapping-credential reference, and releases a zeroizing identity only after 723 the derived public key matches configuration. Offline provisioning is 724 create-new and caller-supplied; ordinary startup never generates an identity, 725 legacy envelopes are rejected, and RHI state backups contain no envelope, 726 wrapping credential, or plaintext identity. 727 728 The separately governed wrapping-credential resolver derives exactly one 729 validated artifact name from the admitted identity binding and resolves it only 730 beneath the same runtime context's canonical instance secrets root. It accepts 731 only an existing 32-byte, owner-controlled, single-link regular file for 732 service-host and repo-local profiles. It never accepts caller paths or bytes, 733 creates credentials or directories, consults environment or process arguments, 734 or falls back to an adjacent envelope sibling. The former prototype identity 735 and adjacent-key storage APIs are not part of the crate surface. 736 737 The wave-two composition proof binds configuration, runtime paths, immutable 738 state metadata, the encrypted identity, and its separately resolved credential 739 to one service instance. It proves that state initialization and existing-only 740 open do not persist the identity secret, credential, encrypted-envelope wire 741 material, or credential reference in `state.sqlite`. The envelope and 742 credential remain excluded from the state-backup contract. That earlier 743 wave-two boundary proof did not itself execute a backup; the governed 744 resilience boundary below now owns the actual backup and recovery mechanics. 745 746 Explicit state initialization validates runtime identity, build evidence, and 747 the complete migration/schema catalogs before invoking the runtime-path 748 directory plan. That plan alone may provision the exact interactive 749 `services/rhi/<instance>` suffix; service-host deployment roots and suffixes 750 must already exist. The shared service-SQLite initializer owns the one 751 transaction and exposes only its sealed typed SQLx executor. Existing writable 752 and inspection opens never provision directories or create missing state. 753 754 RHI's state surface is partitioned into twenty-one distinct non-forgeable typed 755 repository capabilities bound to one already-opened `RhiStateHost`. Their 756 closed topology covers source results, cursors, completions, admitted signed 757 events, canonical mutations, provenance, dirty generations, reconciliation 758 jobs and attempts, immutable manifests/projections/reports, supersession, 759 signed attestation events, publication outbox/targets/attempts, desired 760 presence, and presence outbox/targets/attempts. Each capability has one exact backing-table identity and an 761 append-only, compare-and-swap, or immutable write class. It exposes no raw 762 pool, connection, transaction, SQL, path, or cloneable write authority. 763 Schema migration and verification, remaining repository behavior, 764 backup/restore, service task ownership, and admin routing remain owned by their 765 later ordered checkpoints. 766 767 RHI now composes the shared SQLx-owned resilience boundary without exposing a 768 second database authority. A writable `RhiStateHost` can capture one governed 769 online backup, and either host mode can run an explicit bounded integrity 770 inspection. Offline verification returns a sealed exact-inode proof; staging 771 retains exclusive writer authority; finalization uses the shared durable 772 marker and atomic replacement protocol; and the next writable existing-state 773 open reconciles interrupted restore evidence before exposing a host. Read-only 774 inspection never performs recovery. Callers inject all times, manifest bytes 775 and digest, and the positive backup-size limit. RHI adds no SQLite dependency, 776 raw connection, background runtime, implicit deadline, or direct file-copy 777 authority. 778 779 ## Failure-resilience qualification 780 781 The machine-readable 782 [`failure_qualification.v1.json`](contracts/services_hardening/failure_qualification.v1.json) 783 contract freezes the Step 214 evidence corpus for resource and backlog bounds, 784 disk and durable-state behavior, corruption and malformed history, 785 cancellation, outage recovery, and safe errors. Every RHI entry names an 786 executable component test, while shared SQLite durability, capacity, 787 corruption, migration-history, cancellation, backup, close, and restore 788 evidence is bound to the exact retained Lib source lock. SQLx remains the sole 789 high-level SQLite authority; no production failpoint or environment-selected 790 test path is introduced. 791 792 This checkpoint is deliberately component-scoped. The actual-process and 793 bounded-soak qualification remains Step 215 ownership, native release 794 artifacts remain Step 216 ownership, and promotion and parent-pin alignment 795 remain Step 217 ownership. Nix, OCI, signing, publication, and deployment are 796 deferred and unclaimed. 797 798 The Step 215 799 [`process_qualification.v1.json`](contracts/services_hardening/process_qualification.v1.json) 800 contract closes wave `130-c` by binding that component corpus to the actual 801 RHI executable. It exercises offline bootstrap and required-dependency outage, 802 the complete supervised task graph against loopback relay sessions, eight 803 concurrent read-only configuration-validation processes, and 32 clean database 804 reopen-and-verify cycles. The live daemon is interrupted, joined, reaped, and 805 checked for socket cleanup. Every child process has a fixed deadline and 806 bounded captured output. The test surface adds no production failpoint, 807 environment selector, detached worker, ambient network dependency, or later 808 release authority. 809 810 ## Standalone native release contract 811 812 The capsule owns a private `cargo xtask native-release` generator and the 813 machine-readable 814 [`native_release.v1.json`](contracts/services_hardening/native_release.v1.json) 815 predecessor and the forward 816 [`native_release.v2.json`](contracts/services_hardening/native_release.v2.json) 817 contract. From one exact clean committed revision, a caller-supplied positive 818 deterministic epoch, and an executable ELF64 binary for one governed GNU/Linux 819 target, the generator creates one external immutable artifact directory. It 820 contains the binary archive, a vendored offline source archive, the non-secret 821 configuration example and schema, the standalone systemd unit, exact source 822 lock, license and notices, CycloneDX SBOM, unsigned provenance input, artifact 823 manifest, and sorted SHA-256 checksums. 824 825 Generation is bounded, deterministic, collision-only, mode checked, and 826 durability ordered. It scans exact tracked source, the selected binary, copied 827 package inputs, and generated documents for governed protected-value patterns, 828 then records that protected material and OCI content are absent while binding 829 the qualified Nix posture. The source-locked third-party vendor graph is 830 represented separately by checksums, SBOM, and notices. The generator does 831 not sign, tag, publish, deploy, or write artifacts into the source tree. The standalone 832 `scripts/release-acceptance.sh` surface exercises the native Cargo contract; 833 when invoked by the parent monorepo it is itself run through extbuild. 834 SBOM component references are domain-separated hashes of framed Cargo 835 name/version/source/checksum identity, so they neither disclose a checkout path 836 nor vary when the same exact source is built from another directory. 837 838 The standalone Linux systemd boundary is frozen by 839 `contracts/services_hardening/systemd_qualification.v1.json` and checked by 840 `scripts/verify-systemd.sh`. The instance unit uses the canonical service-host 841 paths, fixed unprivileged account, restrictive directory modes and umask, 842 fixed restart delay, bounded stop behavior, empty capabilities, no environment-based secret 843 input, and the reviewed filesystem, kernel, namespace, process, and address- 844 family protections. The Linux-only verifier requires systemd 252 or newer, 845 runs syntax verification, and rejects an offline security exposure above 3.0. 846 Type `simple` remains deliberate: readiness is the cached CLI/admin contract, 847 not `sd_notify`. Compatibility-sensitive `MemoryDenyWriteExecute` and syscall 848 filters remain deferred to the Step 229 integration wave rather than being 849 enabled without real-binary evidence. This qualification does not install, 850 enable, start, stop, or deploy a production service. Native artifact qualification 851 remains Step 216 ownership, and promotion remains Step 217 ownership. 852 853 Validate the standalone crate through extbuild: 854 855 ```text 856 cargo extbuild doctor 857 cargo extbuild run -- ./scripts/verify-boundaries.sh 858 cargo extbuild run -- ./scripts/verify-supply-chain.sh 859 cargo extbuild run -- ./scripts/release-acceptance.sh 860 cargo extbuild run -- cargo fmt --all --check 861 cargo extbuild run -- cargo check --workspace --all-targets --locked 862 cargo extbuild run -- cargo test --workspace --all-targets --locked 863 cargo extbuild run -- cargo clippy --workspace --all-targets --locked -- -D warnings 864 cargo extbuild run -- env RUSTDOCFLAGS=-Dwarnings cargo doc --workspace --no-deps --locked 865 ``` 866 867 The flake exposes the RHI package, application, checks, and development shell 868 for `aarch64-darwin` and `x86_64-linux`, plus the NixOS module and unsigned OCI 869 derivation for `x86_64-linux`. Run Nix and narrower ad hoc Cargo commands 870 through `cargo extbuild run --` from this repository root. 871 872 ## Copyright 873 874 Except as otherwise noted, all files in the `rhi` distribution are 875 876 `Copyright (c) 2025 Tyson Lupul` 877 878 ## License 879 880 This repository is licensed under AGPL-3.0-or-later. See LICENSE.