@xyo-network/event-kit-xl1
XL1 chain adapters for Event Kit.
createXl1FinalizedHeadSource— reads the finalized XL1 head for publisher filters and for the receiver's grant-freshness checkpublishFinalizedStatements— publishes Statement Graph claims through explicit content-write, independent-readback, inclusion, and finality boundariespreparePublisherService,prepareWakeSubscription,prepareWakeSubscriptionAcceptanceand the fiveprepare*Revocationfunctions — the exact handshake Claim statements and attachments, without a signer, session or I/O; the matchingpublish*functions publish exactly these
const gateway = await new GatewayBuilder().name('local').rpcUrl(RPC).build()
const headSource = createXl1FinalizedHeadSource({ viewer: gateway.connection.viewer })
The result satisfies both the publisher's FinalizedHeadSource and the
receiver's TrustedFinalizedHeadSource — structurally identical ports, declared
locally so this package depends on neither.
Finalized Statement Graph publication
publishFinalizedStatements accepts separate datalake writer and reader ports.
Production callers should supply independently constructed clients pointed at
the same shared public datalake.
const result = await publishFinalizedStatements({
attachments: [challenge, response],
bodyReader: dataLakeViewer,
bodyWriter: dataLakeRunner,
journal,
operationId,
runner,
signer,
statements,
viewer,
})
The candidate operation:
- prepares and validates the canonical Statement Graph transaction;
- requires exactly the challenge/response bodies named by claimed acceptance objects, then inserts and independently reads them back;
- builds and signs the XL1 transaction and journals its exact evidence;
- verifies that signing changed only signatures/continuity metadata and did not alter the signer, Claim source, payloads, order, or transaction intent;
- writes the exact signed transaction content to the writer;
- verifies that exact signed transaction content through the independent reader before broadcasting;
- broadcasts the already-signed transaction;
- observes concrete transaction inclusion; and
- independently observes that inclusion becoming finalized.
The returned result contains the transaction hash, Statement Graph event hashes, attachment hashes, inclusion evidence, and finalized block. Bounded polling options control inclusion/finality observation.
FinalizedStatementPublicationJournal.load and save form the durability
boundary. The first signed record atomically binds the chain ID, Claim source,
operation ID, ordered event and attachment hashes, and exact signed transaction.
Later records commit content-written, content-verified, broadcast,
included, and finalized. A restart validates that binding and resumes the
highest phase. An uncertain broadcast may rebroadcast the exact signed evidence;
it never rebuilds or re-signs the transaction. A finalized retry returns the
same evidence without publishing again.
Operational callers should use the filesystem journal exported by
@xyo-network/event-kit-node/handshake or another atomic implementation. The
package's memory journal is a structural test fixture only.
The public handshake publication helpers accept the single unversioned service, subscription, and challenge contract. Publication enforces the session's pinned XL1 authorization chain and matching service/subscription identity before any write. The same-Claim service/grant/subscription fan and finalized acceptance attachments are unchanged. Ethereum blocks and interval ticks are source positions only; their grants and acceptance lifecycle still belong to XL1.
Why it validates rather than forwards
Both sides treat this number as trusted: the publisher decides which range to emit, and the gate computes grant lag from it. So the reading is checked, not passed through.
- A head that is not a nonnegative JSON safe integer is rejected here, rather
than surfacing later as an opaque
grant-view-invalid. - A head lower than one already observed is rejected by default. Finalized
heights are immutable, so a regression means the endpoint was rolled back,
swapped, or is lying — failing closed beats admitting against a rewound view.
Disable with
rejectRegression: falseonly when a caller genuinely tolerates it.
Evidence
Offline specs cover the validation and regression guard. Live specs under
src/spec/api-local/ run against a real local XL1 chain booted by the
api-local vitest project: the head reads conforming, advances through real
block production, and never regresses.
Separate offline publisher specs verify publication phase ordering, refusal to broadcast after independent datalake verification fails, exact acceptance attachment binding, refusal of signer-mutated transaction content, bounded polling until finalized evidence appears, lossless safe block conversion, and exact agreement between inclusion and finality evidence. Those focused specs mock the XL1 transaction and datalake helpers.
The accepted Gate 2 live handshake in
@xyo-network/event-kit-statement-graph calls the same
publishFinalizedStatements helper with a real apiLocal XL1 runner/viewer and
separately constructed XL1 SDK REST writer/reader clients. Their endpoint is a
filesystem-backed datalake server running in a child process. With Statement
Graph 0.5.0, xyo-chain 5.3.0, and XL1 protocol/SDK 5.4.0, that run places
subject-bearing Claims in the elevated payload slot, passes consensus
validation, and scans the Claim bodies from finalized block carriers.
Run them with pnpm test:live from the repository root. They are opt-in — the
default suite stays offline.
The finalized-head adapter and elevated-Claim publication path are qualified against the local dev chain. The datalake is still a loopback test process rather than a hosted network service. These package-level tests do not qualify a hosted shared public datalake, Sequence, Mainnet, Proxmox, multi-VM operation, or production delivery; the public CLI has separate local and packed-consumer evidence under roadmap Gate 3.
Handshake body preparation
Each high-level handshake publisher now prepares its Claim and then publishes
what it prepared. The prepare* functions expose that first half: given the
authorization chain ID, the canonical source address that will sign, and the
handshake objects, they return the exact statements, attachments, Claim,
Claim hash, subject and object identities. They apply every binding check the
publisher applies, need no signer or session, and perform no I/O.
const prepared = await prepareWakeSubscription({
chainId, source: controller, encryptionKey, grant, service, subscription,
})
// prepared.statements and prepared.attachments are what publishWakeSubscription sends.
Preparation is not authority. It accepts a Mainnet chain ID because it writes
nothing; every publish* function still runs the ordinary network write check
and refuses Mainnet. A manual canary composition passes prepared bodies to the
owning Mainnet host below, which applies its own packet, ledger and terminal
gates. Equal preparation inputs always yield the same Claim hash.
Manual Phase 7 canary host
The Node-only @xyo-network/event-kit-xl1/mainnet-canary entry exports
inspectMainnetCanaryPacket, inspectMainnetCanaryStage, prepareMainnetCanaryLedger,
admitInteractiveMainnetCanaryStage and publishInteractiveMainnetCanary. It is separate from ordinary CLI/network
selection,which continue to reject Mainnet. The neutral publication API also
rejects Mainnet without the host's private nonserializable permit. No issuer
is exported. See the owning interlock contract.
A complete strict review packet binds the canonical chain,public identities, HTTPS endpoint and SDK resource endpoints,artifact/Phase0–6/recovery/funding approval evidence,validity,expected transaction count,aggregate ceilings,cleanup reserve and each exact publication/fee/script intent. Preparation creates one private SQLite ledger and immutable initialization marker. Missing authority must be restored; opening a process cannot reset counters. No real packet is created by a synthetic test fixture.
The manual host reads packet-bound typed approval from a real terminal before opening signer resources and fresh transaction-hash-bound typed approval before every broadcast attempt. CI,unattended input,ordinary CLI flags,JSON approval objects and caller acknowledgement callbacks grant no authority. Reservations survive failures/restarts/ambiguous submissions; signed evidence and publication phases remain exact. Funding and live Mainnet broadcasts remain separately human-authorized. Package/offline fixture qualification is not a live canary.
A root packet may opt in to reviewed stage packets with stages: { max, until }.
inspectMainnetCanaryStage parses a stage against its root, and
admitInteractiveMainnetCanaryStage appends it to the root's ledger after its own
typed terminal approval. Stages add operations, or refresh the fees and validity of
an unreserved operation whose Claim is unchanged. They never change identity,
endpoints, evidence or ceilings, which stay in the root. Publish a staged operation
by passing its defining stage to publishInteractiveMainnetCanary. See
staged canaries.