@xyo-network/event-kit-node
Node.js 26+ durability adapters for Event Kit. The repository pins Node 26.9.0:
createFilesystemCursorStore— publisher cursor for the wake publisher actorcreateFilesystemPublisherOutbox— durable pending-wake slot for retry stabilitycreateSqliteWakeReceiver— atomic durable inbox/queue over one private FULL/WAL SQLite databasecreateSqliteWakeQueue— standalone fencedWakeQueueovernode:sqlitecreateFilesystemWakeQueue/createFilesystemWakeInbox— coordinated SQLite authority with inspectable JSON projectionscreateSqliteBestEffortInbox/createBestEffortSnapshotWorker— persistent bounded hint security/coalescing and independent snapshot workmigrateReceiverStore/migrateIdOnlyReducerCheckpoint— explicit stopped-owner offline migration and reports
Handshake clients
Import @xyo-network/event-kit-node/handshake for the Phase 3 control-plane
surface. That subpath exports:
- synchronized finalized-replay readers and XL1 publication composition;
- publisher and subscriber clients for declaration, discovery, encrypted subscription/grant publication, challenge, acceptance, and revocation; and
- filesystem stores for replay checkpoints, mutation intents, publication journals, publisher encryption-key custody, and endpoint-challenge decisions.
Generated on-chain handshake mutations use a caller-supplied 16-byte
lowercase-hex operation ID.
createFilesystemHandshakeMutationIntentStore atomically binds the first
request to its exact random service/key, grant, ciphertext, or acceptance
artifacts. An exact retry loads that winner before consulting mutable chain
state; changed input under the same scoped operation ID fails closed.
Records and directories are private (0600/0700). Publisher service intents
retain the encryption private key until it can be copied idempotently into key
custody. Subscriber intents retain ciphertext and a request fingerprint, not
endpoint or challenge-secret plaintext.
createFilesystemFinalizedStatementPublicationJournal then binds the logical
mutation to its chain, Claim source, ordered object/attachment hashes, and exact
signed transaction. Restart resumes from the highest durable phase and may
rebroadcast only that evidence; it never rebuilds or re-signs an ambiguous
publication.
The handshake subpath deliberately does not load the wake queues, inbox,
outbox, or node:sqlite. A clean packed consumer typechecks and executes it
without SQLite coupling. There is one unversioned source-aware contract.
Service publication requires sources and maxPositionsPerWake; subscription
publication requires source and fromPosition. Authorization remains pinned
to the XL1 session independently of source positions. Removed schema suffixes,
block-range fields, and profile selectors have no compatibility aliases.
Resident publisher
@xyo-network/event-kit-node/publisher-runtime exports the SQLite publisher
authority/stores, persistent runtime, real D-005 discovery, bounded transports,
native REST gateway/datalake composition, and XL1/Ethereum/UTC source readers.
It uses the shared periodic actor lifecycle; the CLI owns process interrupts,
provider cleanup, and probes. Importing the module does not open a database;
opening publisher state loads node:sqlite explicitly.
Logical wake creation and pending outbox persistence co-commit. Durable admission receipt, contiguous publisher cursor, and outbox clear co-commit independently for each subscriber. Process death and ambiguous responses resend the same body with a fresh real wallet JWT. Publisher progress is admission progress, not completed receiver compute. See the runbook for ownership, crypto custody, retry/cancellation rules, transport limits, and the remaining hosted/Sequence gates.
status().deliveryDiagnostics reports fixed failure phase/reason counters and
the latest received HTTP status and bounded Retry-After delay. These counters
cover only the current process and survive a successful retry; they are neither
lost-notification counts nor durable receipts. The existing failures field
remains the current streak and clears on a matching acknowledgment. Malformed
200/202 content never counts as a delivery. Error text and response bodies are
excluded from diagnostics.
Durability model
The 2026-10-05 remediation replaces split identity/enqueue commits with one transaction over scoped wake and token bindings, a stable receipt, exact authorized work, lease state and completion. Duplicate token binding/expiry extension is atomic. FULL/WAL SQLite coordinates objects and processes on one local host; a bounded 100 ms busy wait fails visibly under unresolved contention. Retrying retains logical identity.
The filesystem adapter uses the same authority in receiver.sqlite. Private
pending/ and inflight/ JSON files are projections, published exclusively with
link and synced directories. They do not decide admission or lease ownership.
Missing projections can be repaired; corrupt or mismatching bytes stop processing
and remain available for inspection. Claims validate shape and canonical hash
against committed authority. Completion removes the retained body while keeping
the stable identity/receipt tombstone; stale files cannot resurrect completed work.
repairProjections() scans active work and filesystem references explicitly.
Owned directories/files are 0700/0600, with owner, regular-file and symlink
checks. Unsafe existing custody is refused instead of chmodding unrelated paths.
Publisher cursor/outbox replacement remains single-writer rename, with file
and publication-directory syncs. Read, parse, state and sync failures propagate;
retained retry bytes/IDs are never replaced because a read failed.
Legacy stores are refused before journal-mode mutation. Use the offline migration runbook on stopped-owner copies; retain backup, inventory and quarantine evidence. The new source format is intentionally incompatible with old writers and runtime dual readers are absent.
Queue providers
All three providers assign a fresh lease fence on each claim. ack()/release()
compare the current entry/state/token atomically. A stale or opposite completion
throws StaleWakeLeaseError; repeating the same successful operation is inert.
Recovery requires recoverInflight({ consumersStopped: true }) after every
consumer sharing the store has stopped. The assertion is an operator contract,
not a liveness detector. Startup alone does not establish quiescence.
Expanded shared conformance covers stale/repeated completion and successor
preservation. Independent-object/process admission races, real SIGKILL boundaries,
private custody and signed HTTP tests supplement it. Provider clauses requiring
reopen/cross-writer support remain explicitly skipped for memory.
Application effects remain at least once. Fence queue state and separately make external effects idempotent or atomically commit effects/checkpoints in their owner.
node:sqlite is built in, so this adds no dependency. It does not emit an
ExperimentalWarning when loaded on the pinned Node 26.9.0 runtime.
Boundary
Current recovery evidence covers local objects/processes and copied fixtures, not host-loss, storage hardware failure, restore or cross-machine qualification. Historical core Gate 5 evidence remains scoped to its original artifacts. See the remediation plan for current checks and measured performance/retention costs. The on-chain publisher roadmap qualifies a single VM in Phases 4-7; a coordinated multi-VM deployment needs a transactional shared store, leases, and fencing and is roadmap Phase 8.