myc

Self-custodial remote signer for Radroots apps
git clone https://radroots.dev/git/myc.git
Log | Files | Refs | README | LICENSE

README (36463B)


      1 # mycorrhiza
      2 
      3 This is the README for `myc` which provides a Nostr remote signer for
      4 standalone and application-embedded clients.
      5 
      6 ## Public API boundary
      7 
      8 The library exposes one curated crate-root API. All implementation modules are
      9 private, and public errors use Myc-owned stable classifications with redacted
     10 diagnostics and no raw dependency-owned source chain. The shared runtime-path,
     11 service-SQLite, and storage identity values that appear in signatures are
     12 intentional governed contract types; raw SQLx, provider, transport, Serde, and
     13 task authority never crosses this boundary.
     14 
     15 The runtime foundation is sealed and cannot be forged or reached through a
     16 child module:
     17 
     18 ```compile_fail
     19 use myc::runtime_foundation::MycRuntimeFoundation;
     20 
     21 fn forge(_: MycRuntimeFoundation) {}
     22 ```
     23 
     24 The reviewed all-features surface is frozen in the
     25 [Myc API baseline](contracts/api_baselines/myc.txt).
     26 
     27 Status publication and cached snapshots can be obtained only through the
     28 validated factory and its sealed handles:
     29 
     30 ```compile_fail
     31 use myc::{MycStatusPublisher, MycStatusSnapshot};
     32 
     33 let _publisher = MycStatusPublisher {};
     34 let _snapshot = MycStatusSnapshot {};
     35 ```
     36 
     37 The native package, artifact, and dependency-trust boundary is frozen by
     38 `contracts/services_hardening/native_release.v3.json`. Linux x86_64 and
     39 aarch64 are the only admitted native artifact targets. `cargo xtask
     40 native-release` consumes an exact prebuilt target binary from a clean Git head
     41 and deterministically writes or checks the complete binary/source archive,
     42 systemd, configuration, source-lock, SBOM, notices, checksum, manifest, and
     43 unsigned provenance inventory outside the source tree. The source archive
     44 vendors the exact locked Cargo graph and proves an offline metadata read before
     45 packaging. Signing credentials and parent-owned human documentation are never
     46 inputs.
     47 
     48 The standalone Linux systemd boundary is frozen by
     49 `contracts/services_hardening/systemd_qualification.v1.json` and checked by
     50 `scripts/verify-systemd.sh`. The instance unit uses the canonical service-host
     51 paths, fixed unprivileged account, restrictive directory modes and umask,
     52 fixed restart delay, bounded stop behavior, empty capabilities, no environment-based secret
     53 input, and the reviewed filesystem, kernel, namespace, process, and address-
     54 family protections. The Linux-only verifier requires systemd 252 or newer,
     55 runs syntax verification, and rejects an offline security exposure above 3.0.
     56 Type `simple` remains deliberate: readiness is the cached CLI/admin contract,
     57 not `sd_notify`. Compatibility-sensitive `MemoryDenyWriteExecute` and syscall
     58 filters remain deferred to the Step 229 integration wave rather than being
     59 enabled without real-binary evidence. This qualification does not install,
     60 enable, start, stop, or deploy a production service.
     61 
     62 The canonical service source lock binds the exact active public Lib cohort,
     63 Cargo lock, verified Lib source archive, toolchain, feature profile, and
     64 service contract versions. Source-lock v3 binds the public flake lock to the
     65 same exact Lib revision as Cargo and records qualified Nix material for only
     66 macOS aarch64 and Linux x86_64. The Linux-only NixOS module and unsigned OCI
     67 derivation are build outputs; signing, tags, publication, deployment, and
     68 production activation remain unclaimed.
     69 
     70 ## Hardened v1 configuration contract
     71 
     72 The target service configuration is frozen by
     73 `contracts/services_hardening/config.v1.schema.json` and the canonical
     74 non-secret `config.v1.example.toml`. It is one strict, immutable TOML document
     75 with explicit identity, relay, authorization, rate, and discovery authority.
     76 Only reviewed bounded operational leaves have defaults. Bootstrap profile,
     77 instance, repo-local root, and config-path selection are CLI concerns and are
     78 not document fields.
     79 
     80 The hardened CLI parser admits the common command tree in one parse. It
     81 requires explicit `--profile <service-host|interactive|repo-local>` and
     82 `--instance <validated-instance-id>` selectors, requires an absolute
     83 `--repo-local-root` only for `repo-local`, and accepts only an optional absolute
     84 `--config` path. Its exact command inventory is `run`; `config
     85 init|validate|show|schema|apply`; `state init|status|backup|restore|verify|migrate`;
     86 `identity init|status|export-public`; `status`; and `doctor`. Identity rotation
     87 is an offline create-new/config-apply lifecycle and is intentionally absent
     88 from the live CLI and Unix-admin inventories.
     89 The process binary uses only this parser and consumes its sealed execution plan
     90 exactly once. Every command reaches its governed config, state, identity,
     91 Unix-admin, doctor, or daemon authority. `run` installs the authoritative
     92 bounded daemon graph; no admitted command can return success through a
     93 prototype or unavailable-operation fallback.
     94 
     95 The selected absolute config path is opened no-follow through its retained
     96 parent descriptor. The loader requires a regular, single-link,
     97 effective-user-owned file with no group/other-write permission, caps bytes
     98 before parsing, and revalidates device, inode, length, and parent identity after
     99 the read. Config initialization consumes bounded non-secret TOML from stdin and
    100 uses create-new `0600` persistence plus file and parent synchronization. Secret
    101 identity provisioning is a separate fixed 117-byte zeroizing stdin document;
    102 secret arguments, environment values, JSON strings, and trailing bytes are not
    103 accepted.
    104 
    105 One binary-owned Tokio runtime is created from the validated fixed thread
    106 limits for each asynchronous command process; there is no CPU-derived default
    107 or library-owned runtime. Existing-state commands discover actual metadata
    108 through the retained shared intent. Offline backup writes the exact canonical
    109 manifest bytes to stdout without a trailing newline, so direct redirection
    110 preserves the bytes bound by its digest. Restore derives expected backup identity
    111 from the trusted manifest digest rather than requiring the damaged live
    112 database to open, and exclusive commands retain the writer-authority boundary.
    113 Deployment directory provisioning remains outside the service executable.
    114 
    115 The parsed invocation is projected once into a sealed execution plan. `run`
    116 selects daemon authority; config, exclusive state/identity provisioning, and
    117 doctor select offline authority; state/identity/service inspection and live
    118 mutations select the permissioned Unix-admin authority. Only explicitly
    119 read-only status, backup, and public-identity operations may fall back when a
    120 later executor proves the daemon writer lock is free. No live plan carries
    121 SQLite authority.
    122 
    123 The active doctor boundary executes the exact 13-check operator inventory in
    124 contract order under fixed per-check deadlines. Check implementations retain
    125 their filesystem, SQLite, provider, bind, network, relay, and clock authority;
    126 only closed pass/fail/skipped observations cross into the report builder. The
    127 builder enforces required-check semantics, returns exit 6 for required failure
    128 or timeout, and emits at most 8,192 bytes of compact canonical JSON using only
    129 fixed summaries and remediation codes. Raw errors, paths, relay URLs,
    130 credentials, public keys, and arbitrary detail strings cannot enter the report.
    131 A pass requires every machine-listed scope facet. Probe futures own their work,
    132 must stop safely when dropped at deadline, and may not detach later mutation.
    133 The production adapter composes secure path and disk inspection, writer-lock
    134 and SQLite authorities, exact schema and outbox checks, provider opening and
    135 Describe verification, validated bind/network policy, and bounded required-
    136 relay reads. It never publishes a relay event. Clock skew remains the sole
    137 optional `Skipped` check until a trusted time source is governed.
    138 
    139 The service status boundary uses the shared service-host lifecycle contract
    140 behind one Myc-owned non-clone publisher and cloneable passive readers. Each
    141 publication validates the lifecycle transition and encodes the complete
    142 bounded `service_status_v1` payload before atomically replacing the single
    143 retained immutable snapshot. Repeated reads return that exact cached value and
    144 perform no SQLite, provider, relay, credential, DNS, clock, filesystem, or
    145 fresh-probe work. Connection counts use the closed pending/active/denied/
    146 expired vocabulary, identity health uses the fixed transport/user/discovery
    147 roles, failed publication preserves the last valid snapshot, and detailed
    148 status remains local to the permissioned Unix-admin surface. Status reason
    149 codes use a closed twelve-value vocabulary; arbitrary strings cannot enter the
    150 cached response.
    151 
    152 The optional TCP operations adapter consumes that same supervisor publication
    153 through a second passive bounded projection and delegates the transport to the
    154 source-locked service-host server. It exposes exactly HTTP/1.1 `GET /livez`,
    155 `GET /readyz`, and `GET /metrics`; every other method, path, or query is
    156 unrouteable. The two Prometheus families are the cached phase and cached
    157 readiness bit with only the closed phase label. Requests perform no SQLite,
    158 filesystem, provider, relay, credential, DNS, or fresh-probe work; the shared
    159 transport still reads its monotonic deadline clock.
    160 Detailed status, configuration, paths, identities, connection/audit data, and
    161 all mutations remain on the permissioned Unix-admin surface. The listener is
    162 disabled unless the validated configuration explicitly enables and binds it,
    163 and its parser floor, headers, response, concurrency, deadline, and idle bounds
    164 remain enforced by the shared server.
    165 
    166 Process outcomes use one exact seven-value vocabulary with exit codes 0
    167 through 6. Diagnostics are compact single-line JSON on stderr; result data is
    168 reserved for stdout, and Myc never writes log files. The structured record
    169 admits only the closed level, event, result, lifecycle, task-failure, and signal
    170 codes. It accepts no caller text, path, SQL, raw cause, identity, relay URL,
    171 credential, secret, or decrypted content. Every public Myc error remains a
    172 crate-owned source-free classification, so ordinary `Display`, `Debug`, and
    173 whole-chain traversal cannot bypass redaction. Current binary dispatch reports
    174 invalid input as exit 2 and service dependency unavailability as exit 3. The
    175 Myc runtime owns one sealed, bounded critical-task graph over the shared supervisor:
    176 task error, panic, join failure, unexpected cancellation, or critical success
    177 before cancellation coordinates shutdown, joins every task, and maps to the
    178 fixed nonzero process result. Tasks receive only a cooperative cancellation
    179 observer; task names and handles remain internal. The binary owns signal
    180 installation. The graph uses one configured absolute graceful-shutdown deadline
    181 for mutation rejection, ingress and operations drain,
    182 recoverable-work persistence, network and SQLite close, and socket close; it
    183 adds no hidden second cleanup budget.
    184 
    185 `parse_myc_config_v1` caps original bytes before decoding, checks the schema
    186 header before closed contract admission, rejects duplicate, null, unknown, and
    187 semantically inconsistent input, and returns an immutable document plus a
    188 deterministic redacted effective-configuration projection. Every projected
    189 leaf records whether it came from the document or one of the exact governed
    190 default authorities. Ordinary errors and `Debug` output contain no source
    191 text, paths, credentials, relay URLs, or identity values.
    192 
    193 The prototype environment loader, `.env` example, environment selectors,
    194 implicit command/profile selection, compatibility aliases, and arbitrary leaf
    195 flags have been removed. Bootstrap now resolves a sealed runtime context from
    196 the validated CLI profile and typed instance ID through the source-locked
    197 `radroots_runtime_paths` authority. Config, state, cache, logs, run, secrets,
    198 `config.toml`, `state.sqlite`, `state.lock`, and `admin.sock` are derived under
    199 the exact `services/myc/<instance>` namespace. The service contains no local
    200 host-environment resolver, worker namespace, ambient selector, or implicit
    201 path default. An explicit absolute `--config` may select the document to read
    202 without changing the canonical common artifact inventory.
    203 
    204 ## Governed state boundary
    205 
    206 Create-new initialization reserves the shared schema-v1 metadata and migration
    207 ledger, retains exclusive writer authority, applies the exact Myc schema-v2
    208 through schema-v12 migrations, binds the normalized configuration, expected
    209 identity roles, and policy versions through a sealed typed repository, and
    210 explicitly closes the host before reporting success. Existing writable open can
    211 resume any exact v1 through v11 prefix or admit the current v12 catalog;
    212 read-only inspection requires the current catalog and exact latest Myc binding.
    213 
    214 Schema v10 adds an append-only configuration-binding history capped at exactly
    215 1,024 generations. Generation 1 is seeded only after the v10 migration commits,
    216 including for an upgraded v9 database, while the immutable original birth
    217 record remains unchanged. `apply_configuration` is admitted only through an
    218 exclusive writable host and independently validates the retained current and
    219 candidate documents before one atomic append. A changed identity expires live
    220 sessions and pending challenges; permission narrowing expires only sessions
    221 whose retained grants are removed. Removing or changing a relay that is still
    222 referenced by nonterminal delivery work fails closed, while safe relay additions
    223 remain admissible. Exact replay returns the retained generation without another
    224 append or revocation, including after an ambiguous caller result. Future startup
    225 must present the latest normalized config and public-identity binding. The
    226 history stores only digests, public identities,
    227 closed contract versions, injected application evidence, and safe build
    228 identity; it stores no credentials, provider envelopes, paths, or relay URLs.
    229 
    230 Schema v11 adds the bounded admin-operation journal. It binds each mutation's
    231 validated operation ID to its fixed route and canonical request digest, retains
    232 at most 128 unresolved Prepared records and 4,096 completed responses, caps a
    233 replayed response model at 8,192 bytes, and prunes only a bounded expired
    234 completed prefix before admission. The journal stores no request body, path,
    235 correlation ID, credential, bundle path, or secret. Completed responses use an
    236 explicit retention policy whose admitted range is 1 through 31,536,000,000
    237 milliseconds; the governed operating value is seven days.
    238 The admin response transport admits at least 8,382 UTF-8 bytes so the maximum
    239 retained model plus the maximum safe correlation identity always fits its
    240 canonical success envelope.
    241 
    242 Schema v12 adds immutable response authority for a connect request awaiting
    243 explicit approval. Myc signs and atomically retains the exact
    244 `pending_connection` response with its initial delivery job before relay
    245 publication, without recording a false terminal operation completion. Exact
    246 replay and delivery use only the retained signed bytes, and a later terminal
    247 response cannot conflict with the pending authority.
    248 
    249 The Step 159 provider and delivery boundary is sealed inside the crate. Both
    250 governed provider kinds execute only fully bound operations, and every result
    251 is independently verified before it becomes authority. Protected blocking
    252 work is joined, local-signer calls use the hardened Unix-admin client, and no
    253 raw provider client, secret, callback, or dependency-owned error crosses the
    254 public API.
    255 
    256 Relay publication uses only the exact source-locked
    257 `radroots_transport_nostr` adapter. Preparation validates the exact committed,
    258 signature-verified event bytes without network I/O. The delivery worker then
    259 persists Submitted immediately before execution. Accepted, rejected,
    260 transport-failed, and unknown acknowledgements remain distinct; cancellation
    261 or lost acknowledgement after Submitted is durably unknown, and retries never
    262 alter the committed bytes. Provider or relay work never occurs inside a SQLite
    263 transaction. The secure command executor and production daemon graph use these
    264 same provider, relay, and exact-byte delivery boundaries.
    265 
    266 The production `run` path owns the exact five-role bounded graph:
    267 `admin_server`, optional `operations_server`, `relay_ingress`,
    268 `provider_dispatch`, and `delivery_outbox`. It creates no task per request or
    269 relay. Required relay subscriptions and provider handshakes complete before
    270 Ready; bounded reconnect publishes Unready when a required dependency is lost,
    271 while optional operations loss publishes Degraded. NIP-46 dispatch verifies,
    272 decrypts, admits, authorizes, executes providers outside transactions,
    273 re-encrypts in the verified request context, signs through the transport provider,
    274 and atomically commits completion, exact response bytes, immutable targets,
    275 and initial outbox state. Completed replay never re-executes a provider.
    276 
    277 Schema v8 adds immutable NIP-46 operation-completion evidence. The Step 147
    278 integration checkpoint binds each durable request to its stable operation and
    279 correlation identities, terminal connect authority or exact active session,
    280 safe completion reason, and any independently verified inner signed-event
    281 bytes and digest. Logout revocation and completion insertion share one
    282 transaction, exact replay returns the stored decision, and failed transactions
    283 expose neither effect. Protected provider output is never persisted. This is an
    284 integration component, not the final production response boundary: Step 148
    285 must compose it with the outer signed response bytes, immutable relay targets,
    286 and initial outbox state in one transaction before RCLD-RSHR-080 can be
    287 promoted to `master`.
    288 
    289 Schema v9 closes that production boundary. `commit_nip46_response` admits only
    290 an independently signature-verified, canonical kind-24133 response bound to the
    291 original client and exact provider signing operation. One SQLite transaction
    292 commits the Step 147 completion, exact response bytes and SHA-256 identity,
    293 immutable configured relay targets, pending delivery job, and zero-attempt
    294 target state. Exact replay returns only the retained response bytes; partial
    295 legacy completion state and mismatched replay fail closed. Provider execution
    296 and relay I/O remain outside the transaction.
    297 
    298 Step 149 closes the repository-owned delivery recovery boundary without
    299 claiming the final daemon task graph. New jobs can be created only by the
    300 atomic signed-response or discovery commit and are rejected at the configured
    301 active-outbox ceiling. Attempt resolution persists caller-injected,
    302 attempt-cap-bounded full jitter; restart recovery scans fixed 128-job cursor
    303 batches, revalidates exact signed source bytes and bounded attempt histories,
    304 recovers only expired leases, and idempotently promotes proven desired
    305 discovery. It performs no relay I/O and creates no task, clock, or entropy
    306 authority. Explicit desired/current offline NIP-05 export re-reads verified
    307 state, works through read-only inspection, and returns canonical compact
    308 `names` plus NIP-46 discovery JSON without hosting it.
    309 
    310 The implemented v1 Myc administration adapter registers the exact 19-route
    311 inventory and validates every request and response against all 32 model
    312 references in `contracts/services_hardening/operator_contract.v1.json`. It
    313 reuses the hardened Lib HTTP/1.1-over-Unix server for original-wire duplicate
    314 and null rejection, percent-decoded bounded path parameters, peer admission,
    315 deadlines, concurrency, body limits, and effective correlation IDs. The Myc
    316 boundary additionally rejects unknown or missing model fields, invalid query
    317 types, noncanonical response JSON, unsafe URLs and identifiers, and response
    318 model drift. Raw shared-host routers and JSON values never cross the public
    319 API.
    320 
    321 The domain handler receives compact canonical model bytes plus the durable
    322 operation ID. A successful mutation means its contract-defined local effect
    323 and operation audit are committed; it does not claim relay submission or
    324 delivery. Identical operation-ID reuse must return the original committed
    325 result, different-byte reuse returns `operation_id_conflict`, and pagination
    326 cursors remain authenticated to the same route, filters, and snapshot. Unit 13
    327 seals that handler boundary inside the production `MycAdminServer`,
    328 projects the exact admitted admin transport limits, and binds only the
    329 canonical permissioned `admin.sock` through the shared host authority. The raw
    330 router, listener, entropy source, and cancellation token remain private. The
    331 existing sole status publisher feeds both detailed local status and the
    332 optional passive three-route TCP operations server, while doctor continues to
    333 accept only its exact injected 13-check probe inventory. Unit 14 supplies the
    334 secure CLI/config bootstrap and concrete doctor probes. Unit 15 alone owns task
    335 spawning, provider/relay wiring, readiness, reconnect, and phase-aware
    336 shutdown.
    337 
    338 The transport capability and admitted request remain non-forgeable outside
    339 the crate:
    340 
    341 ```compile_fail
    342 use myc::{MycAdminRequestDocument, MycAdminRouter};
    343 
    344 let _request = MycAdminRequestDocument {};
    345 let _router = MycAdminRouter {};
    346 ```
    347 
    348 The public Myc repository exposes no raw pool, connection, transaction-control
    349 handle, path, or SQL. Binding and request-admission mutations execute only
    350 inside the shared `ServiceSqliteTransaction` runner. Provider and relay work
    351 cannot occur inside that transaction boundary. The v2 binding table, v3
    352 request/dedup tables, and v4 connection, permission, request-decision, and
    353 authorization-challenge tables and guards are checksum-pinned service-owned
    354 schema objects. Schema v5 adds checksum-pinned audit-sequence, safe operation
    355 audit, request-audit binding, and bounded rate-window objects. Schema v6 adds
    356 checksum-pinned publication-job, target, attempt, transition-guard, and
    357 no-delete objects. Schema v7 adds desired/current discovery state, exact signed
    358 NIP-89 event bytes, deterministic NIP-05 projection inputs, and their delivery
    359 binding.
    360 
    361 The earlier JSON signer store, JSONL audit log, separate signer/audit/outbox
    362 SQLite databases, prototype import/backup adapter, independent migration
    363 directories, and their runtime/operability consumers have been removed. The
    364 only authoritative service-state database is the canonical `state.sqlite` and
    365 the only writer authority is its retained `state.lock`; there is no backend
    366 selection, compatibility reader, prototype importer, or secondary migration
    367 engine.
    368 
    369 The side-effect-free signer-provider contract admits exactly `encrypted_file`
    370 and `local_signer` assignments for the explicit transport, user, and optional
    371 discovery roles. It freezes the seven-operation capability vocabulary, exact
    372 role requirements, stable provider-instance/operation/correlation identities,
    373 absolute deadlines, bounded semantic input and untrusted output, local-signer
    374 resource limits, and logical credential references. Construction derives from
    375 the already admitted v1 configuration, exposes no provider path or secret in
    376 ordinary Debug, and performs no filesystem, credential, socket, clock, task,
    377 or cryptographic work. Envelope execution, credential resolution, Unix-socket
    378 transport, and independent result verification remain later checkpoints.
    379 
    380 The encrypted-file provider now uses the source-locked `radroots_secrets` v2
    381 context-bound envelope behind a sealed Myc boundary. Offline provisioning
    382 requires explicit identity, data-key, envelope-nonce, and wrapping-nonce
    383 material; verifies the derived public key before persistence; and creates one
    384 owner-only envelope without overwrite. Existing reads are bounded, no-follow,
    385 single-link, owner-only, context/reference checked, and independently verify
    386 the decrypted public key against the configured role identity. Protected
    387 material is zeroizing and absent from diagnostics. The service-state backup
    388 inventory remains exactly `state.sqlite`: encrypted identity envelopes,
    389 wrapping credentials, and plaintext identity material are excluded. Canonical
    390 credential artifact resolution remains Step 133 and ordinary run never
    391 provisions an identity.
    392 
    393 Wrapping credentials now resolve only from the shared validated
    394 `ServiceCredentialArtifactName` beneath the sealed runtime context's canonical
    395 instance secrets root. The resolver accepts no path or credential bytes and
    396 reads only an existing exact 32-byte, euid-owned, single-link artifact through
    397 descriptor-relative no-follow admission. Service-host deployments inject or
    398 mount that fixed file; repo-local developers provision it offline. Interactive
    399 resolution is unsupported, and TOML, environment, process arguments, adjacent
    400 envelope files, ordinary run, and state backup neither carry nor create the
    401 credential.
    402 
    403 Local-signer calls use the source-locked hardened Lib administration client for
    404 strict HTTP/1.1 JSON over the configured Unix socket. One fixed
    405 `/v1/provider/operation` endpoint carries a closed internally tagged operation
    406 and result plus exact provider instance, role, operation/correlation IDs,
    407 absolute deadline, expected identity, capability, and contract version. The
    408 validated binding supplies body, deadline, and per-client concurrency limits.
    409 Transport success remains sealed and semantically untrusted until independent
    410 Step 135 verification; cancellation does not prove the signer had no effect,
    411 and signing is never publication. No TCP, browser origin, or child process is
    412 part of this boundary.
    413 
    414 Independent provider verification uses injected completion time and rejects a
    415 late result before semantic exposure. It rebinds the configured role,
    416 instance, identity, operation/correlation IDs, deadline, capability, NIP peer,
    417 direction, and version. Describe/public-identity results must match the
    418 configured identity and limits; signed Nostr events must preserve the exact
    419 canonical unsigned fields, pass event-ID and Schnorr verification, and retain
    420 the exact verified canonical response bytes; NIP-04 and NIP-44 ciphertext must
    421 have canonical protocol shape and exact padding length where the plaintext is
    422 known. NIP-44 v2 plaintext is admitted only through its exact 65,408-byte
    423 implementation ceiling. Verified output remains sealed and redacted, and
    424 neither verification nor signing constitutes publication.
    425 
    426 The obsolete prototype provider tree has been removed. Myc ships no account
    427 keyring, managed-account selector, plaintext or adjacent-key file adapter,
    428 child-process signer, implicit host identity, generic remote-session signer,
    429 or legacy logging/client wrapper. Its removed production dependencies and
    430 Tokio process capability are absent from the locked graph; the active typed
    431 provider contract, encrypted envelope, credential resolver, local-signer
    432 transport, and independent verifier are the only provider boundaries.
    433 
    434 The existing-only runtime foundation owns the writable state host, retained
    435 provider capabilities, and a shared Lib task supervisor. Encrypted-file
    436 identities open only in synchronously joined one-shot startup tasks;
    437 local-signer clients perform no construction-time I/O and remain unready until
    438 their later governed handshake. A passive closed prerequisite snapshot keeps
    439 state, providers, recovery, required relays, admin, and optional operations
    440 conditions explicit without claiming the later status cache or final daemon
    441 task graph.
    442 
    443 Signer-request admission validates bounded client, request, event, method,
    444 canonical request, injected operation entropy, and injected time evidence
    445 before storage. Stable domain-separated operation and correlation identities
    446 bind the logical client request to its persisted entropy evidence. Event
    447 identity and logical request identity retain distinct durable deduplication
    448 records, so an exact replay is idempotent while event or request reuse with
    449 different normalized content records a conflict without retaining the
    450 decrypted request bytes. Replay and conflict counters are bounded and
    451 survive explicit close and reopen; retention remains owned by its later state
    452 checkpoint.
    453 
    454 Connection admission consumes an already-admitted `connect` operation and an
    455 explicit policy generation. Trusted admission creates an active connection;
    456 explicit approval creates a pending connection that can transition once to an
    457 operator-approved or operator-denied terminal decision; direct policy denial
    458 records a durable decision without creating a connection or approval workflow.
    459 Requested and granted permissions are closed, bounded, and independently
    460 bound. Authorization challenges are issued only for a non-connect operation
    461 bound to an active connection, use an operator-owned canonical URL plus
    462 injected entropy and time, and transition once to authorized or expired.
    463 Exact retries return the original durable identity or terminal state, including
    464 after explicit close and reopen.
    465 
    466 Connection admission uses one bounded global window plus one configured relay
    467 window, so arbitrary client keys cannot create persistent subjects before a
    468 connection exists. Challenge creation and authorization use distinct stable
    469 connection-scoped windows. Exact saturation creates no connection, decision,
    470 challenge, or authorization transition beyond the accepted bound, and a
    471 retained rate rejection is replay-stable. Safe audit records preserve exact
    472 typed operation/correlation bindings and use closed category, outcome, and
    473 reason vocabularies; snapshot pagination is bounded and Debug output redacts
    474 identity. Explicit bounded compaction is correlation-idempotent and retires
    475 only expired rate-window and old safe-audit evidence. It never removes schema
    476 history, metadata, connections, decisions, permissions, or challenges.
    477 
    478 Delivery admission copies the exact normalized write-relay inventory,
    479 required-target flags, acknowledgement policy, retry ceiling, backoff, and
    480 attempt deadline into one immutable publication job. Target leases and attempt
    481 records are advanced only through the shared transaction runner; relay I/O is
    482 never awaited while a transaction is open. Exact retries are idempotent, stale
    483 leases recover through injected time evidence, and an acknowledgement whose
    484 outcome is not known remains `unknown` rather than being relabeled as failure
    485 or delivery. This checkpoint binds an artifact digest and precommit identity;
    486 the exact committed signed-event bytes and discovery projection are owned by
    487 their subsequent state checkpoints.
    488 
    489 Discovery desired state is committed atomically with signature-verified,
    490 canonical NIP-89 event bytes, deterministic NIP-05 projection inputs, the
    491 immutable relay targets, and the initial delivery job. The desired generation
    492 may advance independently, while current generation advances only after the
    493 corresponding desired job has proven the configured delivery policy. Restart
    494 reads return the same committed event bytes and projection inputs; publication
    495 and hosted NIP-05 responses remain later runtime concerns and never run inside
    496 the SQLite transaction.
    497 
    498 Explicit state initialization validates runtime identity, build evidence, and
    499 the complete migration/schema catalogs before invoking the runtime-path
    500 directory plan. That plan alone may provision the exact interactive
    501 `services/myc/<instance>` suffix; service-host deployment roots and suffixes
    502 must already exist. The shared service-SQLite initializer owns the one
    503 transaction and exposes only its sealed typed SQLx executor. Existing writable
    504 and inspection opens never provision directories or create missing state.
    505 
    506 Writable hosts expose Myc-bound online-backup and active-integrity operations.
    507 Backup verification retains the exact admitted member inode, and
    508 offline staging derives the same runtime paths, database identity, migration
    509 catalog, and schema catalog from sealed Myc evidence. Finalization returns no
    510 open host; the next writable open alone reconciles durable recovery evidence.
    511 Read-only hosts cannot capture backups, and any live host prevents offline
    512 restore authority. Cancellation, explicit close, and cleanup behavior remain
    513 owned by the source-locked shared SQLx host; Myc maps every public failure to a
    514 stable source-free classification.
    515 
    516 ## Executable qualification
    517 
    518 The Step 161 process qualification is frozen by
    519 `contracts/services_hardening/process_qualification.v1.json`. It runs the
    520 actual `myc` executable under fixed deadlines, bounded captured output, eight
    521 concurrent inspection processes, 32 deterministic reopen iterations, and one
    522 64 MiB crash fixture. External process termination exercises interrupted
    523 backup and pre-marker restore boundaries without adding a production
    524 failpoint, hidden command, environment selector, feature, or detached test
    525 worker. An interrupted backup preserves the live database and leaves explicit
    526 collision evidence. An orphan restore stage prevents admission until an
    527 operator removes the owned test fixture, while a durable replacement marker is
    528 reconciled only by the next governed writable process open.
    529 
    530 The executable corpus composes with the exact Myc component-level atomicity,
    531 backlog, saturation, recovery, property, and adversarial tests and the
    532 source-locked shared SQLx initialization, transaction, backup, close, marker,
    533 restore, and `SIGKILL` failpoint corpus named by that contract. Qualification
    534 adds no runtime authority and makes no RCLD promotion, parent-alignment, Nix,
    535 OCI, signing, publication, or deployment claim.
    536 
    537 ## NIP-46 runtime contract
    538 
    539 Myc listens for encrypted kind-24133 requests on the exact configured relay
    540 inventory. The signer transport identity authors and encrypts
    541 protocol responses; the separate user identity is returned by
    542 `get_public_key` and signs user events. Client-supplied connect metadata is a
    543 bounded, display-only hint and never changes approval, authentication, or
    544 permissions.
    545 
    546 The public approval default is `explicit_user`. Trusted and denied clients,
    547 permission ceilings, allowed signing kinds, auth challenges, relay switching,
    548 and delivery policy are represented only by the strict v1 TOML contract. A
    549 successful `logout` publishes its acknowledgement before
    550 revoking the session. Failed acknowledgement delivery remains recoverable on
    551 restart, while requests from a revoked session remain unauthorized until a new
    552 connect is approved.
    553 
    554 Myc rejects invalid signatures, wrong recipient tags, empty request IDs,
    555 malformed ciphertext, and duplicate event delivery before dispatch. Runtime
    556 state and audit output do not log client private keys or raw connection URIs.
    557 Signer-authored protocol responses use the checked generic-event boundary from
    558 `radroots_nostr`. External custody commands receive canonical unsigned-event
    559 JSON only after typed-authoring policy succeeds, and Myc accepts their result
    560 only when the author and event id match the exact request and the complete
    561 NIP-01 event verifies. Caller-supplied NIP-46 `sign_event` payloads remain a
    562 separate low-level interoperability boundary and receive the same exact-result
    563 integrity checks without acquiring a typed product-authoring claim.
    564 The production external-command executor drains stdout and stderr concurrently,
    565 enforces bounded output, applies one end-to-end timeout, kills and reaps timed
    566 out helpers, and releases Myc's multi-thread Tokio worker while waiting.
    567 Helper-provided stderr and protocol error text are never copied into operator
    568 errors.
    569 
    570 The default Cargo feature profile is `service-host`. Validate the standalone
    571 crate through extbuild:
    572 
    573 ```text
    574 cargo extbuild doctor
    575 cargo extbuild run -- ./scripts/verify-boundaries.sh
    576 cargo extbuild run -- ./scripts/verify-supply-chain.sh
    577 cargo extbuild run -- ./scripts/release-acceptance.sh
    578 ```
    579 
    580 After building one of the two admitted Linux targets, create and then
    581 byte-check an external release directory with explicit deterministic evidence:
    582 
    583 ```text
    584 cargo extbuild run -- cargo xtask native-release --mode write --target <aarch64-unknown-linux-gnu|x86_64-unknown-linux-gnu> --binary <absolute-binary> --output <absolute-new-directory> --source-date-epoch <positive-u32-seconds>
    585 cargo extbuild run -- cargo xtask native-release --mode check --target <same-target> --binary <same-absolute-binary> --output <same-absolute-directory> --source-date-epoch <same-seconds>
    586 ```
    587 
    588 The flake exposes the Myc package, application, checks, and development shell
    589 for `aarch64-darwin` and `x86_64-linux`, plus the NixOS module and unsigned OCI
    590 derivation for `x86_64-linux`. Run Nix and narrower ad hoc Cargo commands
    591 through `cargo extbuild run --` from this repository root.
    592 
    593 ## Copyright
    594 
    595 Except as otherwise noted, all files in the `myc` distribution are
    596 
    597 `Copyright (c) 2026 Tyson Lupul`
    598 
    599 ## License
    600 
    601 This repository is licensed under AGPL-3.0-or-later. See LICENSE.