@xyo-network/xl1-statement-graph-protocol
v0.7.1
Published
Canonical protocol logic for the XYO Statement Graph — identities, atomic Claim admission, per-hash deployment filters, the normative append-only claim fold, and vocabulary-neutral view helpers. Pure and environment-neutral: no chain I/O.
Keywords
Readme
@xyo-network/xl1-statement-graph-protocol
Canonical protocol logic for the XYO Statement Graph (see the repository WHITEPAPER). Pure and environment-neutral — no chain I/O; the SDK package bridges real XL1 types onto the abstract shapes here.
- Identities (§6.2, D8):
eventKey,claimKey,appliedKey,normalizeAddress— keys and gate comparisons always normalize; record-field casing is a fold option. - Acceptance gates (§6.1):
evaluateAcceptance+extractStatementEventsover an abstract{txHash, block, txIndex, signers, elevatedHashes, items}transaction — exact Claim elevation, source-in-signer-set, and all-or-nothing object co-commitment. Missing one named hash rejects the whole Claim; firstIndex declared-schema selection, opt-in per-entry strict mode (ambiguity rejection, body-schema equality), andindexedSchemaPolicyfiltering run only after that atomic gate. Generic extraction can report a missing explicitly elevated body as unresolved; the finalized SDK prevents that state by requiring the same-block carrier first. - Strict body-schema equality (§6.1, strict gate revision 1, since 0.7.0): under
StrictModeOptions.requireBodySchemaEquality, an object body that is not a plain record (an array,Map,Date, buffer, or no verified body at all) drops the entry asobject-body-unverifiable, and a plain record whoseschemais not a string equal to the declaration (missing,null, a number, an object, or present only as$schema/_schema) drops it asobject-schema-mismatch. Releases through 0.6.0 let a body without a string schema pass. The default profile is unchanged. A scan declares which strict profile and revision it ran under in the replay contract'sgateProfile(schemas package; the SDK enforces it on resume). - The normative transition + fold (§6.3, D7):
reduceClaimEntryis the pure, total, per-entry mutation-point surface for long-running indexers;foldStatementsdelegates to it while adding(block, blockEventOrdinal)ordering, duplicate suppression, watermark resume, and atomic per-event fan application. Identity is(source, subject, objectHash);subjectis preserved without implying consent or authority. Append-only:firstBlock/firstEventHashfreeze at materialization, redundant claims advance onlylastBlock, anddeclaredObjectSchemais first-wins. - Enforced fold preconditions (§6.6, since 0.7.0): before sorting,
foldStatementschecks the position of every event and of a resume seed's watermark. Ablock,blockEventOrdinal.txorblockEventOrdinal.eventthat is not a safe non-negative integer throws aTypeError(… has an ordinal-less or malformed position …; the fold requires D7 positions).Number.isSafeIntegeris the only upper bound, so aMAX_SAFE_INTEGERsentinel seed stays valid, and a seed watermark's block may also be-1(nothing consumed yet, as webble seeds from aprocessedThrough: -1checkpoint). A different inclusion at the fold's current watermark position throwsstatement event position collision at block B tx T event E: <txHash>:<eventHash>. Releases through 0.6.0 skipped it, so the event that survived depended on input order. The fold sorts its input, so a full fold checks every position, but an event before a resume seed's watermark is skipped without an identity check, because a seed carries no earlier positions. An inclusion is recognized by its(txHash, eventHash)alone and is assumed to carry the same content, which content addressing guarantees for extracted events; the same inclusion repeated at its own position still applies once and counts inskippedAtOrBelowWatermark. At a resume seed's watermark a tie is skipped when its key is in the seed'swatermarkGroupEventKeys, and throws otherwise. Callers that build events by hand must give each distinct inclusion its own D7 position. Refusing this input is not a fold-version change. - Object self-healing (§5.1):
resolvePureObject+recomputableObjectHash(body-free point queries over deterministic parameterized objects).withPureObjectBodies(transaction, bodies, options)(since 0.7.0) applies self-healing to strict extraction: only whenoptions.strict.requireBodySchemaEqualityis set, it adds{schema}as the verified body of every non-statement item that has no body and whose hash isH({schema})under that item's declaration, so a correctly declared pure object passes strict equality without a datalake. Otherwise, or when nothing is pure, it returns the input map unchanged; when it adds bodies it returns a read-only view over the input map, not a copy, so do not mutate the input while using it. Call it beforeextractStatementEvents, which never synthesizes a pure body itself; the SDK scan and the engine'sapplyStatementTransactionboth do, so the two paths agree. - View helper (§6.4/§14):
indexClaimsByReferencedHash— the vocabulary-neutral lexicon-negation index seam (caller supplies the extractor). Semantic views stay consumer-side (I6).
Verified by the shared fold conformance catalog (hand-derived from the whitepaper, SHA-256-pinned in the schemas package) plus fast-check properties for permutation invariance, seed equivalence, replay idempotency, and fan-out ≡ N-single-claims equivalence — in both Node and real Chromium.
License
LGPL-3.0-only © XY Labs / XYO Foundation
