New:Introducing Socket Scanning for VS Code Marketplace Extensions.Learn more →
Get Started

@xyo-network/sdk-protocol-core

Package Overview
Dependencies
Maintainers
5
Versions
18
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@xyo-network/sdk-protocol-core

Foundation SDK barrel for XYO Protocol 2.0 (protocol, core payload plugins, manifest, sdk-utils)

latest
Source
npmnpm
Version
8.0.3
Version published
Weekly downloads
2.1K
-35.11%
Maintainers
5
Weekly downloads
 
Created
Source

logo

@xyo-network/sdk-protocol-core

npm license

Foundation SDK core monolith for XYO Protocol 2.0 — protocol, core payload plugins, manifest, and sdk-utils. The public @xyo-network/sdk-protocol package re-exports this package.

Core implementation

This package owns the implementation modules. @xyo-network/sdk-protocol is the public compatibility facade; consumers normally import from that facade or the @xyo-network/sdk umbrella. The core compiles in toolchain monolith mode from xy.config.ts; the facade re-exports its public modules.

import { asSchema, PayloadBuilder } from '@xyo-network/sdk-protocol'

Payload schema contracts

This section defines schema naming, payload structure revisions, and hash selection for XYO and applications on XYO Layer 1. The SDK validates syntax and explicitly supported revisions; the application still owns its field semantics, authorization, compatibility policy, and historical replay rules. This documents the current source contract; no package publication, deployed-network activation, or automatic upgrade of older consumers is implied. Tightened validation needs a compatibility review before rollout to an existing ingestion or replay path.

Schema identifiers

schema is a stable type-family identifier, not a URL or a structure-version string. Its exact grammar is:

[a-z0-9]+(?:\.[a-z0-9]+)*

The entire string must match. Only ASCII lowercase a–z, digits 0–9, and single dots between nonempty segments are allowed. Reject uppercase, Unicode, hyphens, underscores, whitespace, URL punctuation/escaping, empty segments, and leading or trailing dots. Do not normalize an invalid identifier into another one. Create constants with asSchema(name, true); makeSchema(name) also validates the literal before producing its schema.

Valid identifiersInvalid identifiers
com.example.market.resultscom.example.market.results-view
network.xyo.payloadnetwork.xyo.Payload
com.example.sensor2.readingcom.example..reading, com.example.café

The base syntax does not require three segments or establish ownership. SchemaNameValidator, and PayloadValidator with its default schema-name factory, also retain their existing minimum of three segments: asSchema('local', true) can pass while default payload validation rejects that name. This update does not loosen that existing acceptance requirement.

Public application identifiers should use a controlled reverse-domain namespace; network.xyo.* is reserved for XYO protocol authors, and com.example.* is for examples. Domain-authority resolution additionally requires at least three segments and verifies the exact reversed domain. A domain containing a hyphen cannot simply be copied into this grammar: removing - changes the domain and may name somebody else's authority. Use a valid namespace you actually control; do not invent a domain-normalization mapping. See the Domain Schema Authority specification.

New identifiers MUST NOT encode a payload structure revision with suffixes such as .v1, .v01, or .1; these are syntactically valid but are a design anti-pattern. Use $version for structure revisions. A subject's API/product version is a separate, explicitly named data field such as apiVersion. Existing published identifiers remain historical contracts: do not rename them, reinterpret their suffixes, or dual-read unrelated shapes without an explicit migration.

Payload structure version

$version is reserved client metadata identifying the payload's structure contract. It is optional. Absence in the original payload permanently means 1.0.0; malformed values are errors, not another spelling of absence.

encoded = major * 1_000_000 + minor * 1_000 + patch

Each component is an integer from 0 through 999; the encoded value is an integer from 0 through 999_999_999. 1.2.3 is 1_002_003, and the absent default is 1_000_000. Strings, null, negative values, fractions, non-finite numbers, and out-of-range values are invalid. This is a numeric three-component version; it does not encode SemVer prerelease or build labels. Do not switch to radix 10,000.

import {
  asSchema, DefaultPayloadVersion, encodePayloadVersion,
  getPayloadVersion, PayloadBuilder,
} from '@xyo-network/sdk-protocol'

const schema = asSchema('com.example.sensor.reading', true)
const payload = new PayloadBuilder({ schema })
  .fields({ temperatureCelsius: 21 })
  .meta({ $version: encodePayloadVersion({ major: 1, minor: 2, patch: 3 }) })
  .build()

getPayloadVersion(payload) // 1_002_003; validates, does not mutate
getPayloadVersion({ schema }) === DefaultPayloadVersion // true; no field inserted

PayloadVersionZod, isPayloadVersion, asPayloadVersion, toPayloadVersion, encodePayloadVersion, and decodePayloadVersion implement this numeric contract. Reading or validating an omitted default MUST NOT inject $version into an existing object: explicit and omitted 1.0.0 have the same effective revision but different root hashes. Choose the emitted representation at creation time.

Definitions, closure, and compatibility

Every published (schema, effectiveVersion) definition is frozen: its fields, types, constraints, semantics, and unknown-field policy cannot silently change. Freezing a contract is separate from closing its objects:

  • Closed object: undeclared fields are rejected. Declare supported metadata deliberately; closure also needs an explicit rule for nested objects.
  • Open object: extra fields may be accepted according to the definition's extension policy. Preserve them when forwarding/hashing. Acceptance does not authorize an old reader to execute semantics it does not understand.
  • Frozen definition: immutable for that revision, whether open or closed. A sender cannot relax it by adding a self-declared $frozen or $locked flag.

JSON Schema expresses object closure through additionalProperties; in Zod choose strict or loose objects deliberately. Default z.object parsing can strip unknown fields; that is neither strict rejection nor faithful preservation of an open payload. Verify hashes over the original representation before any projection.

An open definition can already permit additional, ignorable data without a new revision. Changing the published definition or assigning new operational meaning is a contract revision. Never change units, defaults, or effects behind an existing field name: use explicit stable names such as dollarCost and centsCost.

Assess compatibility in both directions, including stored history:

ChangeNew reader accepts old payloads?Old reader accepts new payloads?
Add optional fieldUsually; check formerly allowed unknown valuesOnly if its extension policy and semantics permit it
Add required fieldNo, when old data lacks itDepends on old closure and semantics
Widen a field's accepted typeYes, for that fieldNo for newly permitted values
Narrow a field's accepted typeNo for removed valuesYes, for that field
Remove a field or change its meaningDepends on requiredness/closure; meaning must stay explicitDepends on requiredness/closure; may break behavior

Use a major revision for a change that breaks a promised reader/writer contract; use a minor revision for compatible additions; use patch revisions for compatible clarifications/corrections. Optionality, open objects, or a type widening alone do not prove compatibility. Retain exact historical definitions, and document which revisions each receiver accepts. Never try older validators until one accepts malformed or unsupported data.

Typed validation and metadata

Validate identifier, supported effective version, and shape together:

import * as z from 'zod/mini'
import { zodIsFactory } from '@ariestools/sdk'
import {
  asSchema, encodePayloadVersion, PayloadZodLooseOfSchema,
} from '@xyo-network/sdk-protocol'

const ReadingSchema = asSchema('com.example.sensor.reading', true)
const ReadingVersion = encodePayloadVersion({ major: 1, minor: 2, patch: 3 })
const ReadingPayloadZod = z.extend(
  PayloadZodLooseOfSchema(ReadingSchema, ReadingVersion),
  { temperatureCelsius: z.number() },
)
const isReadingPayload = zodIsFactory(ReadingPayloadZod)

PayloadZodOfSchema, PayloadZodStrictOfSchema, and PayloadZodLooseOfSchema take an optional second argument containing one supported version or an array; the default is only 1.0.0, not every version. A version list is appropriate only when the same shape and semantics cover every listed revision. Otherwise dispatch explicitly to separate definitions. Generic payload validation checks version syntax, not a product's supported-version policy.

isPayloadOfSchemaType also checks the version policy but remains a tag/version check, not a field-shape validator. Use a full typed guard at trust boundaries. PayloadVersionZodForVersions and isPayloadVersionSupported support custom validators without making an unknown version valid.

Do not call omitMeta or omitClientMeta before selecting/validating a version: they remove $version. A metadata-stripped projection is not evidence that the original payload omitted the field. Verify the original hash first, retain the original revision, and remove only explicitly handled metadata when a closed body parser requires it. Parser defaults or stripping must not alter the bytes whose identity is being verified.

Root hashes are the application default

Use PayloadBuilder.hash(payload) for virtually all application identities, references, commitments, cache keys, and deduplication. It is the root hash (_hash), includes client metadata such as $version and $sources, and excludes storage metadata (_*). Use it for new $sources references and for commitments that must bind a particular payload representation. Do not replace it with JSON.stringify plus a native digest.

PayloadBuilder.dataHash(payload) (_dataHash) excludes all metadata, including $version, $sources, and $signatures. It deliberately groups representations with the same data. Use it only when a specific protocol requires that projection; it does not bind a payload's version or provenance. Never assume _hash and _dataHash are interchangeable just because they match on a metadata-free example.

A BoundWitness signs its own data hash, excluding its $signatures to avoid a circular signature dependency. Normally attached child payloads are committed through root hashes in payload_hashes, so the parent signature can authenticate the child's $version. A reference containing only a data hash cannot do that. A standalone BoundWitness's own $version is not authenticated by its own signatures; only a verified outer root-hash commitment or trusted protocol context can supply that authority. An unbound version label MUST NOT choose weaker signature, authorization, closure, or consensus rules.

Cache definitions by (schema, effectiveVersion) and validation results by the root hash plus the applicable validation/authorization policy. A data-hash-only lookup may collect variants, but must not substitute one versioned representation for another. Existing SDK/storage/protocol contracts that use data hashes are not automatically migrated by this guidance.

Schema-definition payloads and rollout scope

network.xyo.schema has an existing ordinary version field using the same radix-1,000 encoding. It describes the contract identified by definition.$id. Its outer $version instead describes the structure of the network.xyo.schema envelope itself. These are different levels; do not rename, copy, or reinterpret one as the other. Omitted described-contract versions use the same 1.0.0 baseline when applying this policy; retain the original serialized definition.

SchemaCache validates the complete network.xyo.schema payload before compiling an authoritative or legacy alias definition. This includes the supported outer $version and numeric format of the described contract's ordinary version. Validation preserves the original payload without inserting an implicit version.

The existing SchemaCache and domain publication map remain name-keyed; this implementation does not make them select exact (schema, version) definitions. They do not supply an immutable multi-version registry or consensus-wide compatibility proof. Resolve/pin exact definitions and retain historical revisions in application policy; version-aware authority discovery is separate follow-up work. Likewise, publishing these helpers does not deploy them to existing chains or make legacy Statement Graph, Event Kit, ordinal, or exchange data-hash contracts root-hash contracts. Preserve shipped identifiers and hash algorithms until an explicit coordinated migration is implemented and verified.

Cloudflare workerd secp256k1

The elliptic/workerd subpath supplies the SDK's secp256k1 operations from a statically imported WebAssembly.Module, as required by Cloudflare Workers:

import { initializeEllipticWorkerd } from '@xyo-network/sdk-protocol-core/elliptic/workerd'

const cryptoReady = initializeEllipticWorkerd()

Await cryptoReady before using Account signing or verification APIs. The backend is installed once into the shared Elliptic singleton and cannot be replaced after initialization. The packaged libauth Wasm artifact is SHA-256 pinned and includes its upstream MIT license.

Install

Using npm:

npm install @xyo-network/sdk-protocol

Using yarn:

yarn add @xyo-network/sdk-protocol

Using pnpm:

pnpm add @xyo-network/sdk-protocol

Using bun:

bun add @xyo-network/sdk-protocol

License

See the LICENSE file for license rights and limitations (LGPL-3.0-only).

Credits

Made with 🔥 and ❄️ by XYO Foundation

FAQs

Package last updated on 09 Oct 2026

Related posts