Commit graph

833 commits

Author SHA1 Message Date
Meta Vens
5dbc0c29f5 Bound the RUDP receive path and refuse hostile sequences
Clears the cultnet half of the retained debt. The two unported commits from the
retiring GameCult/cultnet-rs lineage were not portable as patches: this lineage
had reworked the same receive path with sequence domains and ACK horizons, and
applying them raised nine conflicts that would have reverted that work. Most of
what they added already existed here by another route -- received-sequence
history, fragment-set count and reassembly bytes are all bounded already. So
the gaps were taken rather than the patches.

Three were real. The per-channel maps grew without limit, and a peer picks its
own channel ids, so ordered and sequenced channel tracking is now capped at 64
each. The out-of-order hold buffer grew without limit, and a peer picks its own
send order, so it is capped at 1024 frames and 4 MB; sizes are computed from the
buffer rather than tracked in counters, which cannot drift.

The fourth was the sharpest. remember_received ran before the duplicate
early-return, so a single forged packet far past the current highest advanced
the receive state beyond every sequence still in flight and starved the
session. Such a packet is now refused without being remembered.

Reliable sequence exhaustion aborted the process through expect(). The capacity
gate that already guards the send window now also refuses when the sequence
space cannot cover the request, and allocation saturates rather than panicking
so no future path can reintroduce the abort.

Five tests cover the bounds and both refusals. cultnet-rs passes 103,
cultcache-rs 48, cultmesh-rs 7, and the TypeScript-Rust RUDP interop lanes pass
5 of 5 with the hardened peer, so legitimate traffic is unchanged.

The parity ledger now records what this actually leaves owed: these are
refusals, not wire-format changes, so the interop lanes stay green whether or
not the other four runtimes match. The gap will not announce itself.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 00:57:07 +02:00
Meta Vens
eb74ead837 Restore cross-runtime schema recovery and prove staging cleanup
Taking the standalone body as the CultCache base dropped a0b31b8, and it was a
real regression rather than a missing convenience. A record whose catalog entry
is absent -- written by another runtime, or older than the catalog it was
stamped against -- made decode_store_snapshot fail, and one such record failed
the entire pull. Recovering the type from the payload is what "across runtimes"
meant in that commit's title.

Restored in full: the payload is a MessagePack array whose first field is the
schema version, so the schema name is recoverable from the record itself; the
registry now also indexes schema name to entry type and refuses a name claimed
by a second type; and pull resolves a persisted type that is either a
registered type or a recovered schema name. The stale schema id is preserved on
the envelope rather than rewritten.

743eaa5's durability half needed no code. The standalone lineage reached the
same place independently through crash-atomic single-file snapshots and
abandoned staging cleanup, and its cleanup carries the same protections: only a
candidate named for this exact store plus a canonical UUID is removed, and
anything that is not a regular file is skipped. Untested, though, which is how
a careful deletion rule quietly becomes a careless one. Now asserted: an
abandoned canonical candidate is removed while a non-UUID lookalike, a bare
.tmp suffix, and another store's candidate all survive, and the committed
snapshot still reloads.

48 tests pass. This clears the cultcache half of the retained debt from b672fb7.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 00:45:48 +02:00
Meta Vens
fd676ce74d Finish the sequence-domain split in Python and Kotlin
Separating the reliable and lossy sequence domains landed in Rust, TypeScript
and C# on a branch. The Python and Kotlin halves were written at the same time
and left uncommitted in the worktree, so three runtimes spoke the new contract
and two spoke the old one -- the exact cross-runtime disagreement this
repository exists to prevent.

Both were already complete and implement the same three rules as the others:
ordered delivery requires reliability, sequenced channels carry their own
per-channel counters with latest-wins delivery, and duplicate suppression is
gated on packet.reliable so lossy datagrams are remembered nowhere.

Python also gains the three tests Rust, TypeScript and C# each received and it
did not: lossy packets cannot create reliable ordered gaps, unreliable
sequenced delivery is scoped to its channel, and unreliable ordered delivery is
rejected. Python passes 141.

Kotlin is committed unverified. This machine has no JVM or Gradle, and the
package carries no runtime-local test file, so its only gate is the interop
lane in CI. The change mirrors the four runtimes proven here line for line, but
mirroring is not evidence and CI is the witness.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 00:40:05 +02:00
Meta Vens
85bc4c71b5 Align the replay-window test with the reliable sequence domain
Separating the sequence domains gated duplicate suppression on packet.reliable
in Rust, TypeScript and C# alike, so lossy datagrams are remembered nowhere and
a replayed one is delivered again. That is the intended contract -- lossy
traffic is fire-and-forget and its history is bounded by not existing -- but
replay_history_is_bounded_and_idle_hub_sessions_expire still asserted the old
behaviour with a lossy packet and had been left failing on the branch.

The three tests the change added in each runtime cover ordered-requires-
reliable, per-channel sequenced scope, and lossy gaps. None covers the bounded
replay window, which was this test's real subject, so removing the assertion
would have dropped the only coverage of a security property.

The lossy assertion now states the new contract, and the reliable domain gets
its own replay check: 4,100 acknowledged reliable sends, then the oldest
replayed and rejected by the window.

Rust 151, C# 148, TypeScript 48, Python 138 all pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 00:36:36 +02:00
Meta Vens
8d3025816d Align RUDP reliability tests with sequence domains 2026-09-04 00:33:23 +02:00
Meta Vens
0736ae4824 Separate RUDP reliable and lossy sequence domains 2026-09-04 00:33:16 +02:00
Meta Vens
ca9895c06a Wire AGENTS.md into Claude Code memory
Claude Code reads CLAUDE.md, not AGENTS.md, so this repo's doctrine was
invisible to it. This one-line import makes the existing AGENTS.md load
without duplicating or renaming it. Codex is unaffected.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 00:33:01 +02:00
Meta Vens
4c0dc07ba5 Make the Rust suite green and stop silently ignoring packages
exact_reliable_acks_clear_more_than_one_ack_window_of_fragments has been
failing on main. It was not a defect: send_many returned 32 packets where the
test expected 40, and 32 is exactly CULTNET_RUDP_RELIABLE_SEND_WINDOW_PACKETS.
The reliable send window landed and this test kept asserting the pre-window
behaviour, so a test whose name is about crossing an ack window had stopped
crossing one. It now asserts that a window's worth leaves immediately, that
the remaining eight fragments queue, and that acknowledgements promote them
until every fragment is delivered -- the same loop packages/cultnet-rs/tests
/cultnet.rs already uses for this contract.

All three Rust crates are green: 46, 95 and 7.

The NuGet packages rule hides every language package until one is named in
the re-include list, and cultmath, cultmesh-browser and cultmesh-kotlin were
never added. Nothing is currently lost -- every source file in them is
tracked -- but any new file added to those three would have been dropped in
silence. cultmesh-rs hit this on the way in.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 00:01:17 +02:00
Meta Vens
62ac7e3483 Record the unported RUDP hardening as owed work
Exact acknowledgement receipts landed; bounded session memory and hostile
sequence rollover rejection did not. Until they do, this runtime accepts
sequence and reassembly input the retiring lineage rejects, so its repository
cannot be deleted yet.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 23:14:45 +02:00
Meta Vens
9f822b7578 Expose exact RUDP acknowledgement receipts
Ported from GameCult/cultnet-rs 9dcb88d into CultLib, where the wire contract
belongs. Ghostlight's committed idunn_health.rs imports
CultNetRudpReliableSendStatus to hold an Idunn process write lease current,
and the symbol existed only in the standalone lineage, so nothing could
consume this contract from its canonical home.

Three reconciliations were needed because both lineages reworked RUDP
independently since the 014f998 copy-in:

- reset_peer_state: kept this lineage's version, which also resets the
  sequence and fragment counters and clears queued_reliable, and folded in
  only the imported change that matters -- rotating session_scope so a peer
  reset invalidates outstanding receipts. The imported body also cleared
  highest_delivered_sequenced_by_channel, a field the sequence-domain work
  renamed away here.
- channel_send_options is a free function in this lineage, not a method.
- The imported guard rejected reliable channels with an expiry. This lineage
  has no reliable-expiry concept at all -- the only mentions of expiry in the
  file arrived with this patch -- so every reliable channel is already
  non-expiring and the guard reduces to the reliability check. A comment
  marks where to restore the expiry half if expiry is ever added.

94 tests pass. The one rudp_server_hub failure is pre-existing and reproduces
on clean origin/main.

The other two standalone RUDP commits are deliberately not ported. Bounding
session memory and rejecting hostile sequence rollover rebuild the receive
path -- stale-sequence rejection, per-channel tracking caps, reassembly and
ordered-buffer byte accounting -- in the same code this lineage reworked with
sequence domains and ACK horizons. Merging them changes wire-observable drop
and reassembly behavior, which needs the cross-runtime interop harness to
validate, not a local build.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 23:14:30 +02:00
Meta Vens
67cbb4ea36 Give the Rust CultMesh runtime a home
The only Rust CultMesh implementation in existence was 1,363 lines inside
Ghostlight's vendor directory. It was in no library repo and no standalone
repo, so it had never been checked against the browser, Kotlin, and
TypeScript CultMesh bodies it must interoperate with.

It is not a duplicate of the facade in cultnet-rs. That one is the small
surface the parity table claims for Rust: peer cards, authority leases,
endpoint parsing. This is the stream and session layer -- node, document
sets, RUDP document publication, stream descriptors, negotiation, stream
catalog, and shared-memory frame rings -- which the same table lists under
Rust's "Not claimed". A consumer grew the unclaimed surface because there was
nowhere else to put it.

Its path dependencies already matched this layout and it builds against
CultLib's cultnet-rs unchanged, so it does not depend on the forked RUDP
extras. Seven runtime-local tests pass, and CI now runs them.

The parity table gains no claim from this. The Rust row says plainly that no
interop lane exercises the stream surface, and expansion work records that
runtime-local tests are not a parity claim. Landing code is not evidence.

packages/cultmesh-rs needed an explicit .gitignore re-include; the NuGet
packages rule hides every language package until one is added by name.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 23:09:45 +02:00
Meta Vens
a539d4fb1c Return the Idunn and Odin authority contracts to CultLib
The standalone GameCult/cultnet-rs holds six modules CultLib never received:
runtime_authority_contracts, service_identity, provider_health_contracts,
idunn_deployment_brake, idunn_lifecycle_brake, and snapshot_query. They own
Idunn Expected incarnations, dual-proved runtime activation, process write
leases, service-signed presence health, and Odin topology correlation -- the
wire contracts every GameCult daemon must agree on.

They belong here because wire parity conformance lives here and nothing
outside it is checked for cross-runtime agreement. Held as source to be
copied, this contract already forked: Ghostlight vendors it at e542225 while
its own authority map names f4ab237, and the two disagree on whether Present
may coexist with a disagreement. One copy makes them exclusive; the other
separates presence from readiness and gates through into_undisputed_present.
A single owner under the parity harness is the fix; re-vendoring is not.

None of the six touch RUDP, so they land without disturbing the protocol
core. rudp.rs remains genuinely forked -- 140 hunks between the lineages,
with reliable windows and ACK horizons on this side and bounded session
memory, exact acknowledgement receipts, and hostile rollover rejection on the
other. That reconciliation needs the cross-runtime interop harness and is not
attempted here.

Adds ed25519-dalek, zeroize, and the Windows Foundation/Cryptography features
the credential paths require. 96 tests pass. The two rudp_server_hub failures
are pre-existing on this base and reproduce at 230ace6 untouched.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 22:56:59 +02:00
Meta Vens
b672fb7a37 Return the Rust CultCache engine to CultLib
packages/cultcache-rs forked from GameCult/cultcache-rs at the 5c69bfc
monorepo import and the two lineages then diverged in both directions. The
standalone repo took 28 commits of engine work CultLib never saw: typed SoA
projection, atomic heterogeneous batch publication, single-entry and
conditional batch CAS, a transactional keyed redb backend with serialized
cross-process opens, lockless provider snapshot reads, RAII read-only shared
snapshots, snapshot-fenced replace/append, crash-atomic single-file snapshots,
compaction fences, portable and canonical byte fields, and unified retained
storage authority. That body is 3,714 lines with 48 tests against CultLib's
1,554 with 18.

CultLib is the canonical home because wire parity conformance lives here and
nothing outside it is tested for cross-runtime agreement. A runtime-specific
core-stack repo cannot hold the engine every other runtime must agree with.

The standalone body lands as the base rather than merging 28 commits backward.
It is already proven against a CultLib-derived cultnet-rs: Ghostlight vendors
exactly this pairing and compiles. Here, cultcache-rs passes 46 tests and the
cultnet-rs RUDP gate passes 20 with no source change.

Retained debt, not carried forward: a0b31b8 recovered schema-stamped records
missing catalog entries (SchemaStamped, infer_schema_name,
infer_schema_version_from_payload) and 743eaa5 hardened snapshot replacement
(SnapshotReplacementStage, CommittedSnapshotDurabilityUncertain, stale
candidate cleanup, with_exclusive_lock_using_unlock). Their tests were
white-box against internals this body does not have. The standalone
independently made single-file snapshots crash atomic and cleaned abandoned
staging files, so the durability guarantee is probably held under other names
-- probably is not proven. Re-establish both as black-box tests against the
new API before the standalone repo is retired.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 22:56:59 +02:00
Meta Vens
334e60f192 Recover authority-bound CultMesh and atomic generations 2026-08-26 19:01:24 +02:00
Meta Vens
63d6094c94 Clarify CultMath and CultGeometry ownership 2026-08-26 17:47:06 +02:00
Meta Vens
5b2c36329d Add CultGeometry isosurface extraction 2026-08-26 17:37:22 +02:00
Meta Vens
ea88cfcd05 Move CultMath into the CultLib monorepo cultmath-core-rs-v0.1.2 cultmath-unity-v0.1.2 cultmath-v0.1.2 2026-08-26 17:35:51 +02:00
Meta Vens
75c180782a Acknowledge retransmits across RUDP horizons 2026-08-23 19:15:22 +02:00
Meta Vens
ed273e6865 Keep large RUDP test receiver alive 2026-08-23 19:05:54 +02:00
Meta Vens
fda51fad50 Acknowledge reliable RUDP windows cumulatively 2026-08-23 19:00:33 +02:00
Meta Vens
a2e3d3fa35 Bind reliable windows to the RUDP ACK horizon 2026-08-23 18:54:18 +02:00
Meta Vens
b7949d31f2 Tolerate UDP reset advisories during RUDP polling 2026-08-23 18:46:35 +02:00
Meta Vens
289b792284 Exercise RUDP reliability in fleet CI 2026-08-23 18:43:17 +02:00
Meta Vens
21ce4f0ec6 Repair CultNet interop workflow setup 2026-08-23 18:42:07 +02:00
Meta Vens
f4dabfefb0 Bound RUDP reliable transmission windows 2026-08-23 18:35:49 +02:00
Meta Vens
5cefa0db00 Resolve CultMesh URI RUDP bootstraps in TypeScript 2026-08-22 03:25:02 +02:00
Meta Vens
4f6e95bb3d Carry editable field authority in CultMesh bindings 2026-08-22 00:05:57 +02:00
Meta Vens
3cec5463b2 Fence body commits by demand generation 2026-08-19 14:27:22 +02:00
Meta Vens
21fd4e07eb Version hot-body demand generations 2026-08-19 14:10:13 +02:00
Meta Vens
73ab8b65e1 Reconcile live subscription authority 2026-08-19 13:55:03 +02:00
Meta Vens
eaf1189cc1 Project subscription records per peer 2026-08-19 13:24:51 +02:00
Meta Vens
0a885afce7 Authorize database subscription records 2026-08-19 12:12:52 +02:00
Meta Vens
b9cbd7561d Gate cache hydration and preserve legacy generations 2026-08-19 02:36:49 +02:00
Meta Vens
72153a46a2 Seal cache transactions and expose coherent generations 2026-08-19 02:17:38 +02:00
Meta Vens
e80383c33f Make CultCache transactions atomic to observers 2026-08-19 01:44:17 +02:00
Meta Vens
81ca92fe40 Keep CultCache readers on one committed generation 2026-08-19 00:56:37 +02:00
Meta Vens
eea8248877 Make CultCache page commits content-addressed 2026-08-19 00:11:20 +02:00
Meta Vens
8a203c165f Publish atomic CultCache Unity package 2026-08-18 23:44:51 +02:00
Meta Vens
cc89aae4a0 Make CultCache directory commits generation-atomic 2026-08-18 23:42:15 +02:00
Meta Vens
7a6f0be21f Bind CultMesh application ingress to session identity 2026-08-18 23:08:59 +02:00
Meta Vens
99458dbb57 Ship authenticated remote transports in Unity package 2026-08-18 20:23:27 +02:00
Meta Vens
c194bd4cc8 Harden CultMesh route fallback and secure onboarding 2026-08-18 19:41:03 +02:00
Meta Vens
f622ee1b24 Authenticate CultMesh authority routes and replay operations 2026-08-18 19:02:46 +02:00
Meta Vens
6835ea4c10 Make Eve onboarding prove packaged authority routes 2026-08-18 17:39:59 +02:00
Meta Vens
6c848bd6c0 Bind CultMesh authority identity to physical routes 2026-08-18 17:21:58 +02:00
Meta Vens
21163d83fa Make CultMesh identity and route recovery explicit 2026-08-18 10:42:33 +02:00
Meta Vens
b542f4b644 Publish the actual CultLib Unity 1.0.46 runtime 2026-08-18 10:24:20 +02:00
Meta Vens
c75051017d Make CultMesh session identity explicit 2026-08-18 07:26:55 +02:00
Meta Vens
d4d24385d1 Prove clean .NET Eve package onboarding 2026-08-18 06:33:40 +02:00
Meta Vens
22bb9afaa4 Use one CultMesh node in Eve onboarding 2026-08-18 06:23:26 +02:00