Skip to content

Cleanup - #2

Merged
expede merged 7 commits into
mainfrom
cleanup
Sep 3, 2026
Merged

Cleanup#2
expede merged 7 commits into
mainfrom
cleanup

Conversation

@expede

@expede expede commented Sep 3, 2026

Copy link
Copy Markdown
Member

Mostly pushing functionality down into the wasm package, and reusing them here

Tie-collapse at the top serial deduplicated on document alone, so two
records naming the same document with different g= keys read as agreeing
duplicates and selection picked a generation arbitrarily. A rotation
caught mid-flight is a contest: the one-shot RRset rule has no lineage
evidence to order the generations, so it must refuse rather than pick.
This matches the reference verifier (best_of_document treats a
non-unique undominated set as contested) and the canonical
classifyRecords export will inherit exactly this behaviour, so adopting
it now prevents a verdict flip reading as a regression later.

HostnameBinding gains an optional contested flag; the directory renders
it as the contested status. Found by the demo app fixing the same gap in
its own copy after the onomancy session confirmed the reference
semantics; the new test is a candidate conformance vector.
parseRecord now refuses what the canonical parser refuses: a g= that
does not decode to exactly 32 bytes (the same lax bug class the demo
fixed writer-side), and records over 255 characters. parseRecord is
exported so vectors can drive it.

tests/ vendors the shared ONO0 conformance vectors (rev 2, authored by
keyhive-todo-app-demo; provenance sha in the header): all 36 applicable
vectors pass, including the three deferral vectors added after running
rev 1 against canonical semantics exposed that the demo's resolver had
no skew deferral at all - a live vulnerability their 37/37 self-
agreement could never have found, since both TS copies shared the gap.
The u64-adjacent vector now carries an explicit nowMs; the boundary
vector pins <= as selecting. nextSerial vectors are publisher-side and
out of scope here.
The ratified grammar (specs/serialization.md) requires decoders to
reject a key field that does not decompress, even where it is never
verified against: a 32-byte string that cannot denote a key is not the
canonical encoding of anything, and parsers that disagree about whether
such a record exists diverge on every selection it feeds. Both
downstream TS parsers had the gap - 29/29 vector agreement was
agreement on it - found by onomancy's reference harness rejecting the
shared fixtures, whose fill(32,k) keys were mostly not points.

The check is RFC 8032 decompression in bare BigInt, because this
library imports only React: no crypto dependency, and WebCrypto import
is async where this parser is sync. Verified against the reference
validity table for all seventeen fill fixtures (now a permanent test),
and the live brooklynzelenka.com record still parses.

Vendors conformance vectors rev 3 (point-valid fixtures, two non-point
parse vectors, nowSeconds boundary note): 39/39, no skips. Rev history:
rev 1 caught this parser's lax g= and 255 limit; rev 2's canonical
referee caught the demo's missing deferral; rev 3's reference harness
caught point validity in both parsers and in the fixtures themselves.
Each round's bug was invisible to the previous round's process.
Adversarial review round two, against the point-validity batch.

atob is forgiving - unpadded input and nonzero trailing bits in the
final character decode identically - so one record had many spellings:
a parser differential against the reference decoder (which requires
canonical padding and rejects set trailing bits), and a phantom-contest
vector inside this library, since the tie-set keys on the g= spelling
and two spellings of one key read as a rotation. base64ToBytes now
round-trips through btoa and rejects non-canonical spellings, making
key and spelling bijective, which fixes both at one site.

The ratchet remembers the highest serial ACCEPTED; a contested set was
refused. Admitting its serial made a zone that heals a rotation without
bumping the serial read replayed forever on stale chains. Gated.

Also: the sqrt(-1) adjustment constant is hoisted (was ~175us
recomputed on half of valid points), isCurvePoint returns false on
wrong-length input instead of throwing, Ono0Record is exported beside
parseRecord, OnomancyRuntime documents that custom implementations MUST
set contested (it is the only carrier of same-document rotation ties),
and the replay-preempts-contested ordering is documented as deliberate.

The mathematics itself survived review: 6318-case differential fuzz
against an independently written checker, zero divergences.
Mutation testing proved two blind spots: a wire-order-first document
selection passed all 39 tests (expected.document was never asserted),
and a truncated vector file passed vacuously. The runner now asserts
the selected document identity via the meta's alias map, pins the rev 3
per-kind vector counts, asserts deferred against its documented
default-zero rather than only when present, no longer drops a '0'
clock to a falsy check, and passes the clock as BigInt end to end
(OnomancyRuntimeOptions.now may now return bigint) instead of losing
precision near 2^64.

New pins, each verified to fail against a mutant dist: non-canonical
base64 spellings are malformed not aliases; x=0 with the sign bit set
is rejected (the one RFC 8032 rule the fill(k) table cannot reach);
a contested serial does not enter the ratchet. Also a stale-dist
warning for local runs, and the test header no longer claims dist is
React-free (it is not; the isolation gate allows exactly React).
Copilot AI lite review requested due to automatic review settings September 3, 2026 06:07

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

It includes a broad refactor of binding/runtime behavior plus new exported utilities and dependency/API shifts that warrant final human validation.

Pull request overview

This PR “pushes functionality down” into the @inkandswitch/onomancy Wasm-backed module (notably ONO0 parsing/record selection), and promotes previously app-local directory/namestore utilities into the library so consumers share one set of rules.

Changes:

  • Migrate TXT record parsing / RRset selection / deferral / contest rules to @inkandswitch/onomancy@0.3.0, updating the runtime and verified-directory mapping accordingly.
  • Promote shared directory utilities (flat namestore writes, directory composition, reverse-binding designation combinator) into src/ exports.
  • Add/expand behavior-pin tests and a hermetic ONO0 conformance-vectors suite; update the component-test app for the flat layout and injected helpers.
File summaries
File Description
tests/verified-directory.test.mjs Updates behavior pins and adds new contested/ratchet regression tests.
tests/ono0-conformance-vectors.jsonl Adds shared ONO0 parse/classify/nextSerial conformance vectors (rev 4).
tests/namestore.test.mjs Adds tests for promoted namestore helpers, reverse-binding combinator, and composed publish behavior.
tests/conformance-vectors.test.mjs New hermetic test runner that replays ONO0 vectors at module and runtime-mapping levels.
tests/automerge-directory.test.mjs New pins ensuring reserved keys are refused and non-entry shapes are skipped.
src/onomancy/verified-directory.ts Carries contested bindings through, avoids ratcheting contested serials, and uses shared bareId.
src/onomancy/runtime.ts Replaces local RRset parsing/selection with onomancy.classifyRecords + docAnchorBytes mapping.
src/onomancy/reverse-binding.ts New designation combinator requiring reverse-binding certificate claims (injected check).
src/onomancy/index.ts Updates exports/types for new runtime surfaces and reverse-binding utilities.
src/index.ts Promotes compose/namestore exports and re-exports bareId.
src/directory/namestore.ts New shared helpers for flat namestore writes with reserved-path refusal and legacy cleanup.
src/directory/compose.ts Moves to local types import and changes publish to attempt both writes via allSettled.
src/directory/automerge-directory.ts Adds entry-id and entry-shape filters and expands reserved-key guarding to .well-known/*.
pnpm-lock.yaml Locks @inkandswitch/onomancy to 0.3.0 and updates lockfile entries accordingly.
package.json Bumps package version and adds @inkandswitch/onomancy>=0.3.0 peer/dev dependency.
apps/component-test-app/src/onomancyStub.ts Updates stub to supply classifier + anchor decoder while still faking only resolution.
apps/component-test-app/src/nameResolution.ts Switches name parsing to onomancy Name and updates namestore walk for flat layout + migration fallback.
apps/component-test-app/src/localDirectory.ts Removes the localStorage directory implementation (no longer used).
apps/component-test-app/src/App.tsx Removes local fallback directory and uses promoted bindEdge for flat namestore writes.
apps/component-test-app/package.json Bumps app dependency on @inkandswitch/onomancy to 0.3.0.
Review details

Files not reviewed (1)

  • pnpm-lock.yaml: Generated file

Suppressed comments (1)

src/directory/compose.ts:70

  • The comment says "failures surface together", but the implementation rethrows only the first rejection reason and drops any additional failures (e.g., if both publishes reject). Either aggregate errors (e.g., AggregateError) or adjust the comment to match the current behavior.
  • Files reviewed: 19/20 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread apps/component-test-app/src/nameResolution.ts Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Brooklyn Zelenka <hello@brooklynzelenka.com>
@expede
expede merged commit e43c3c3 into main Sep 3, 2026
1 check passed
@expede
expede deleted the cleanup branch September 3, 2026 06:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants