Findings custom-formatter-bytes-walked (ruling depth-walk-covers-library-msgpack: the owner skips the walk when the definition carries a formatter; the grey 0x91 image round-trips, plain and codec stay bounded; README says so) and wide-length-unpinned (bin32/str32/ext32 of 65539 bytes and array32/map32 of more than 65535 children before a chain at and past the limit). The same tests pin the inspector refusing to recover a stamp from a past-limit payload. Not yet built.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Finding inspector-recover-unwalked: one decodeBoundedPayload (walk, then decode) serves both the stamp recovery and the preview, so a payload past the limit is never decoded by either.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Kills the survivors of the first mutation sweep (fixext2 skip, 0xc1, the fixarray/fixmap/fixstr upper bounds, map16 and map32 child counts).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The C# cases and the TS assertions are here; the vector file is written from the reference in the next commit, so the
slot-nil tests of both runtimes fail at this commit.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
checkPayloadDepth is an iterative header walk run by decodeDocumentPayload before the formatter and by
encodeDocumentPayload on the formatter's bytes; the two plain-decode inspection doors call it first. The plain
formatter's encoder depth is set above the limit so the walk decides. Tests: the C# bounds vectors, the walk's
header and scalar rules, the owner, the inspector, the legacy version inference, and the mesh network doors;
test:pack:ts denies decoder-shaped exports by enumerating the packed entries.
Builds and passes untested at this commit (verification runs on Yggdrasil next).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The packed-consumer smoke now fails if the document entry exports it, at run time and at compile time.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Held to tests/vectors/slot-nil/reads.msgpack, written by the C# reference (SlotNilVectorTests): every accepted row
rewrites to the reference's bytes, nil in an int slot is refused. 94a26431c000c0 round-trips byte-identical.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The cultcache-ts README, the DocumentPayload comment (comment only) and the cultmesh-browser README say plainly what the
opaque type guarantees and what it does not; documentPayloadBytes is the escape for bytes.
All commits build.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The put is a union on `decoded`: true carries the document read through the registry's definition, false carries the
opaque DocumentPayload, so the owner read on the undecoded branch compiles without a cast (compile fixture in
payload-type.test.ts) and the three test casts are gone. A store holding a foreign parsing record, a matched record that
does not parse and a matched record that parses must return the last, which kills the survivors on the schema-matched
second find in resolveCultMeshStoreDocumentRecord.
All commits build.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The put handler no longer plain-decodes such a payload, and does not refuse it either: five
existing server tests put through an empty registry, a catch-all server is a capability a general
library keeps, and the payload type already stops a plain read. CultMeshRudpDocumentPut.payload
documents the two cases; a handler that holds the definition reads it with decodeDocumentPayload.
Builds in every package; suites run at the end of the pass.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
DocumentPayload is an opaque object type over the same runtime Uint8Array, keyed by a string
property, and types CultCacheEnvelope.payload, CultNetRawDocumentRecord.payload and
CultMeshRealtimeFrame.payload. decodeDocumentPayload(definition, payload) and
encodeDocumentPayload(definition, value) are the only reader and writer; documentPayloadFromBytes
and documentPayloadBytes are the two named escapes at the edges where bytes enter and leave.
resolveDocumentFormatter leaves the package index. The cache, cultnet replication, the mesh read
paths, the provider command (now a CultCache document), and the browser's decodeCultNetPayload
(definition required, cultcache-ts/document entry) all go through the owner.
Compile-fail fixtures per payload-carrying package pin the type with expect-error lines.
check-typescript-tests-wired.mjs fails when a test file is run by no script; cultcache-ts now
runs dist-test/test/*.test.js, and the portability workflow runs the check and the cache suite.
Builds in every package (tsc, src and tests); the suites run once, at the end of the pass.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The two payload-decode-owner text-scan tests go, as do the string-schemaId overloads and
branches of the cultMeshDocumentFrom* functions and statics, decodeCultMeshPayload,
decodeCultNetRawDocumentPayload, toUint8Array, replication's second decodeDocumentValue, and the
undefined branch of decodeDocumentPayload. decodeDocumentPayload now requires the definition and
also runs its schema (the one reader). A publication binding names a definition, never a bare
schema id; the RUDP put handler refuses a schema with no registered definition instead of
plain-decoding it. Builds in every package; tests not yet rerun.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Soul passes cultlib-gaps:verdict:cut-union-bounds-rs.s1, .s2 and .s3.
Low residuals deferred to follow_ups depth-vectors-nest-every-container
and rust-past-limit-record-handling; encode-stack-safety stays open.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The lifecycle brake, signed daemon health and runtime authority records check
an exact positional array length before decoding, so they have no undeclared
slot to skip; they return to the plain decoder. The media records have no
length check and their derive skips undeclared trailing slots, so all five
are held by the test.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Document payloads decoded with rmp_serde::from_slice in provider_session,
media_stream_wire, idunn_lifecycle_brake, provider_health_contracts,
runtime_authority_contracts and the CultNet message decode in contracts.rs now
decode through the one depth decision. The duplicated schema-v0 branch in
decode_cultnet_message_from_slice is deleted.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Delete the apply_raw_snapshot_documents extraction (no production change in cultmesh-rs remains):
the test serves a snapshot over loopback RUDP and pulls it through the node. Two at-limit documents
land; a document one level past the bound is refused with PayloadTooDeep and the store file is
byte-identical afterwards. Supersedes the seam test of 735654f0, which this commit removes.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The previous commit's union_parity.rs did not compile (mixed_past was removed from its definition but
not from the case list). a5c0f876 does not build its tests; this commit does.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
pull_rudp_catalog_snapshot hands its documents to apply_raw_snapshot_documents (the network-free
seam); the test feeds it a payload one level past the bound and checks nothing reaches the store.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
replication's document_record_from_envelope and the service identity credential read no longer
call rmp_serde::from_slice on a stored payload, so the 256 bound holds there too.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Both raw write doors run the one check_payload_depth that decode_payload runs first, before any
store is touched; decode_payload is public so envelope readers elsewhere decode through the same
helper. Tests: union arms, maps and arrays at 256 and 257 through both doors, a batch that stages a
valid entry beside a deep one persists neither, the read vectors enter by a store file written
behind the cache.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The tree walk counted only list, tuple and dict, so a codec whose tree used deque,
mappingproxy or another abc container was unbounded. Every Mapping, Sequence and Set
that is not text or bytes now counts. RecursionError from a user encode or decode,
and from the JSON decoder, reaches the caller as itself with its traceback; only
msgpack's StackError (raised by depth alone) is mapped to the depth refusal.
All commits build.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Pins ext-key-class-arity (fixext 1, timestamp, ext 8) and the nil-slot refusal at the
derive's own seam. Builds.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The guard test counted its package root from the compiled layout and failed under tsx and for a one-file src; it now walks up to
the package.json. The browser's non-messagepack refusal and the cache's codec-and-formatter refusal are pinned by message.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Mutation survivors of the first run: the unwrap_or(usize::MAX - k) fallbacks were equivalent
mutants, so a truncated header now returns None through the one helper. Child counts and long
lengths (map16/32, array16/32, str/bin/ext 16 and 32 bit) are tested with skipped bytes that
read as containers when a skip stops short. Builds.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The RUDP put handler and the browser payload reader decoded a codec document with plain msgpack. cultcache-ts now
exports decodeDocumentPayload (definition or plain), the RUDP server reads a put through the registry's definition,
and decodeCultNetPayload takes the formatter. cultmesh-ts and cultmesh-browser no longer depend on @msgpack/msgpack:
frames and commands use cultnet-ts/wire, and a test per package scans src and the manifest. The envelope probe fixture
now runs the plain record first and last. Not yet built or tested on this commit; the verify job follows.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Removes the equivalent continue in the walk (the stack only ever holds containers).
Pins the exact refusal text on the RecursionError and StackError paths, both sides,
and that the validator receives the written and the decoded value. Every commit builds.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Wrap, Floor and Ceiling fixture arms; bounds-outcomes.msgpack looped through the raw decoder
for arm-key and nil-slot classes and through the cache for depth; put of the 257 chain refused
with the cache and store unchanged; 2 MiB debug thread decode/encode at 256 and refusal at 257
and 100000; iterative walk on 256 KiB; header-width and scalar-width seams; derive names D, S,
A, E, ArmKey compile.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
check_payload_depth walks MessagePack headers iteratively and refuses the first container past
MAX_PAYLOAD_DEPTH (256); decode_payload is the only payload decode (get, get_all,
get_all_with_keys, finish_prepared_entry, envelope validation), so write is refused through
finish_prepared_entry. Derive: nil arm slots refused naming union and key, ext arm keys classed
non-integer, generated generics and local items prefixed (types named D, S, A, E, ArmKey now
derive), slot keys capped at 65535 at definition, SlotRecord requires a hidden method only the
derives emit, DatabaseEntry/CultSlots expansions are functions the type/schema/generics refusals
are unit-tested through. Tests follow in the next commit; this commit builds.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
DatabaseEntryField validates its key in one place (0..MAX_SLOT_KEY, no bool), so
database_entry_field, direct construction and field tuples share the rule. A record
shorter than its declared slots no longer refuses a missing slot: the slot is nil
and its default applies, as the C# reference reads it. define_union refuses True
and False as arm keys, each pinned alone. Every commit builds.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Iterative container count over the decoded and the encoded tree (MAX_PAYLOAD_DEPTH,
CultCachePayloadDepthError); msgpack StackError and RecursionError map to the same
refusal. Union decode names an out-of-Int32, non-integer or nil-slots arm as the
reference does. Fixture arms Wrap, Floor, Ceiling; loop over bounds-outcomes.msgpack.
Pins the bool arm-key refusal's callers in the vector loop only; every commit builds.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Soul holds at cultlib-gaps:verdict:cut-union-derive-rs.s2; depth and remaining Lows move to union-bounds-rs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
cultmesh-ts reads document payloads through resolveDocumentFormatter at its five plain-msgpack sites; WireFloat carries a signalling flag and the float32 leaf refuses it; slots() refuses a key above 65535 at definition. The C# vector writer gains the 2^24+1 reads row and float32-nan.msgpack, whose committed files land in the next commit: this commit does not build its tests (union-parity numeric vectors, row count 160 and float32-nan.msgpack are absent).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An odd kept value just past exact pins the tie rule (the Stryker survivor). The excess <= 0 guard was equivalent to the
general path for the only values that reach it, so it is deleted.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>