Native Swift SDK exploration + Phase 0: pin the conformance seam - #225
Merged
Conversation
…ge core Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Extends the protocol conformance corpus beyond the L0+L1 interop kernel: - replication/ (L2): version-handshake negotiation, the umbrella version bundle, node-sync catch-up filtering, and the byte-exact signed Yjs envelope (Ed25519 over BLAKE3(update ++ utf8(JSON(meta))), meta in declaration order — the cross-language landmine, now spec'd). - authz/ (L3): authorization expression-AST evaluation (allow/deny/and/or/ not/roleRef/PUBLIC/AUTHENTICATED + the and(allow,not(deny)) deny-wins composition), mirroring evaluator.ts. Generated and drift-guarded by the existing runtime conformance.test.ts (now 24 vectors). Spec pointers + the envelope insertion-order rule added to L2/L3. Part of exploration 0210 (native Swift SDK / portable core), Phase 0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A runnable Swift sibling of the Python reference kernel (the Apple-platform proof for exploration 0210, Phase 0). Independently derives the same did:key, canonical JSON, and BLAKE3 change hash, and verifies TypeScript-signed changes — 18/18 checks pass (Swift 6.3, macOS). CryptoKit for Ed25519, the pure-Swift nixberg/blake3-swift for BLAKE3, base58btc + canonical JSON inline. Surfaces a concrete Apple-platform finding: CryptoKit's Ed25519 uses randomized nonces, so it verifies TS signatures but does NOT re-sign them byte-for-byte (validates the 'crypto gaps on Apple' risk in 0210). Reference material, not in CI (like the Python kernel). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Marks the 'pin the seam' phase done in the exploration's checklists (L2/L3 vectors, Swift reference kernel, canonical-JSON/envelope spec, CI drift guard) and adds the changelog fragment. Phases 1-3 (Swift JSC engine, Rust xnet-core, multi-language fan-out) remain open. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Contributor
|
Preview removed for PR #225. |
crs48
added a commit
that referenced
this pull request
Jun 21, 2026
…227) ## What & why Completes the user-facing vision of [exploration 0210](docs/explorations/0210_[_]_NATIVE_SWIFT_SDK_AND_PORTABLE_MULTI_LANGUAGE_CORE.md): **a real, runnable native Swift SDK** where you *define schemas in Swift, write and query the database in Swift, and bind results into a SwiftUI re-rendering loop* — no JavaScript, no React. It builds directly on the conformance-pinned protocol kernel landed in [#225](#225), so identity (`did:key`), canonical change hashes, and per-property LWW convergence match the TypeScript reference. `swift run xnet-demo` runs it end-to-end; **14 tests pass** including the shared golden vectors. ## What's in `swift/XNetKit/` | Layer | File | | --- | --- | | Schema DSL (`Schema { text(…); select(…) }` → `SchemaIRI`) | `Schema.swift` | | Signed change log + per-property LWW materialization | `Change.swift`, `Node.swift`, `NodeStore.swift` | | `Sendable` `Predicate` + fluent `Query` | `Query.swift` | | `liveQuery` subscribe contract + `@Observable LiveQueryModel` | `LiveQuery.swift` | | `did:key` + Ed25519 (CryptoKit), BLAKE3, canonical JSON | `Identity/Crypto/JSONValue.swift` | | End-to-end demo | `Sources/xnet-demo/main.swift` | ```swift let Task = Schema(name: "Task", namespace: "xnet://xnet.fyi/") { text("title", required: true); select("status", options: ["todo","doing","done"], default: "todo") } let store = NodeStore(identity: Identity()) let t = store.create(Task, ["title": "Ship it", "status": "todo"]) let todo = store.query(Query(Task, where: .equals("status", "todo")).ordered(by: "title")) // SwiftUI: List(LiveQueryModel(store, Query(Task)).rows) { Text($0["title"]?.stringValue ?? "") } ``` ## Hardened by an adversarial review A multi-agent review found **6 confirmed issues, all fixed and locked with tests**: 1. Object keys now sort by **UTF-16 code unit** (matched JS; Swift's default scalar sort diverges for astral-plane keys). 2. **Integer-valued doubles** serialize like JS (`10000000000000000`, not `1e+16`). 3. `JSONValue.compare` now handles doubles/bools/mixed numerics (was silently `.orderedSame`). 4. `schemaId`/`createdAt` resolved **order-independently** (earliest-by-lamport), not by append order. 5. `@Observable` `rows` mutation wrapped in `MainActor.assumeIsolated`. 6. Dropped an **unsound `Cancellable: Sendable`** and the cross-isolation `AsyncStream` teardown. ## Scope (honest status) This is the **native-authoring slice**. It took the *native-runtime* route rather than the exploration's recommended JSC-embedded engine — trading 100% TS parity for a pure-Swift, dependency-light core. **Not yet included** (tracked in the exploration's checklists): live hub sync (`URLSessionWebSocketTask`), persistent storage (GRDB/SQLite), E2E encryption (libsodium XChaCha20), Keychain identity custody, full client-side authz enforcement, and Swift-6 strict-concurrency (`actor` store). One Apple constraint surfaced earlier holds: CryptoKit Ed25519 is randomized (verifies but doesn't re-sign byte-for-byte). ## Verification - `cd swift/XNetKit && swift test` → **14 passed** (conformance + store + live-query + canonicalization). - `swift run xnet-demo` → identity → schema → signed writes → query → 5 reactive renders → LWW convergence. - The package lives at top-level `swift/` (outside the pnpm workspace), so it doesn't touch TS CI; changelog fragment included. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
Explores making XNet a first-class citizen of native Apple development (and, long-term, Kotlin/.NET/C++), then implements Phase 0 — "pin the seam", the foundation every later phase depends on.
The exploration (
0210) maps the kernel↔runtime fault line, surveys prior art (Automerge+UniFFI, Ditto, PowerSync, yrs), and recommends a phased dual-track: ship Swift fast on an embedded JavaScriptCore engine behind a native Swift API, then extract a Rustxnet-corekernel via UniFFI. Users write only Swift; the shared engine is swappable because the seam is the conformance-pinned protocol.Phases 1–3 (the JSC engine, the Rust core, multi-language fan-out) are large, multi-quarter efforts and remain open. This PR delivers the self-contained, fully-verifiable Phase 0.
What's implemented (Phase 0)
conformance/vectors/replication/) — version-handshake negotiation, the umbrella version bundle, node-sync catch-up filtering, and the byte-exact signed Yjs envelope (Ed25519 overBLAKE3(update ++ utf8(JSON(meta))), withmetain declaration order — a cross-language landmine now spec'd in L2 §4).conformance/vectors/authz/) — authorization expression-AST evaluation (allow/deny/and/or/not/roleRef/PUBLIC/AUTHENTICATED+ theand(allow,not(deny))deny-wins composition).packages/runtime/src/conformance.test.ts(now 24 vectors, L0–L3).conformance/reference/swift/) — the Apple-platform sibling of the Python kernel. An independent Swift implementation reproduces the same did:key, canonical JSON, and BLAKE3 hashes and verifies TS-signed changes: 18/18 checks pass on Swift 6.3 (CryptoKit +nixberg/blake3-swift, base58/canonical-JSON inline).A real finding
The Swift kernel surfaced a concrete Apple-platform constraint that validates the exploration's "crypto gaps on Apple" risk: CryptoKit's Ed25519 is randomized — it verifies TS signatures correctly but cannot reproduce them byte-for-byte. Documented in the Swift README and the exploration's risks.
Verification
pnpm exec vitest run --project runtime packages/runtime/src/conformance.test.ts→ 24 passed.cd conformance/reference/swift && swift run VerifyVectors→ 18 passed, 0 failed.pnpm turbo run typecheck --filter=@xnetjs/runtime→ green.🤖 Generated with Claude Code