Skip to content

feat(platform-node): a second host over better-sqlite3 + run the conformance TCK against it (spike) - #277

Merged
prisis merged 2 commits into
alphafrom
advisor/234-platform-node-spike
Aug 1, 2026
Merged

feat(platform-node): a second host over better-sqlite3 + run the conformance TCK against it (spike)#277
prisis merged 2 commits into
alphafrom
advisor/234-platform-node-spike

Conversation

@prisis

@prisis prisis commented Aug 1, 2026

Copy link
Copy Markdown
Member

Stacked on #229 (base advisor/229-platform-honesty) — it validates that 229's contract fixes generalize, and builds on the cleaned contract. GitHub retargets this to alpha when #229 merges. Review after #229.

What

Turns portability from a claim into a tested property: PLATFORM_MATRICES held exactly one entry (platformMatrixIds()'s own comment: "both hold exactly cloudflare, which is why nothing has noticed"). This stands up a real second host — @lunora/platform-node (5 contract adapters + composition root over better-sqlite3 and an in-process socket registry) — and runs the existing conformance TCK against it.

Headline result: the contract generalizes

Honest node capability matrix

NODE_CAPABILITIES added to @lunora/platform (rates every feature Cloudflare rates — enforced by a same-key-set test), registered as node in codegen's PLATFORM_MATRICES. This is the first time the fail-closed gate has run against a mostly-unsupported/emulated matrix: verified end-to-end that gatePlatformFeatures(usage, "node") flips browser/container off with platform_unsupported_feature diagnostics while leaving kv/scheduler on, and that { "target": "node" } resolves through the real registry (no platform_unknown_target).

Findings (the deliverable) — plans/234-node-host-findings.md, 7 classified

  • 2 host-bugs — both in the existing node:sqlite reference host, found by contrast: a write-only durableAttachments map (dead code hidden by a blanket lint exemption) and a text-sniffing ("select") read/write heuristic weaker than better-sqlite3's Statement.reader.
  • 3 contract-under-specsShardDirectory.jurisdiction has zero real callers (five packages reimplement the check against the raw CF type instead); "durable survives host recycling" doesn't distinguish in-process recycle from process restart; ShardKvStore.put's "structured-clonable" pins no wire format (three hosts, three serializers).
  • 1 TCK gapdatabaseSize has no conformance coverage on any host.
  • Each is sized for its own follow-up plan with a proposed fix location; left unfixed here per the spike's "don't patch the engine to pass" rule.

Two edits flagged for your judgment (both documented)

  • scripts/api-snapshot.js: platform-node excluded from the API-surface guard until it graduates past spike stage (no lunora dev/deploy wiring yet, surface still moving) — alongside the other experimental packages. api:check is 43/43 with this.
  • packages/config invariant test: registering node broke a strict-equality invariant (deployTargetIds() === platformMatrixIds()) that only ever held because both were [cloudflare]. Relaxed to the one dangerous direction — every deploy driver must have a matrix (else codegen emits an un-gated surface) — while allowing the benign codegen-gateable-but-not-yet-deployable case that node legitimately is. Reasoning is inline + in the findings doc.

Verification

platform-node 40, platform 11, codegen 11, config 16; full regression across the 6 affected packages + api:check (43/43), dist:check, lint:package-json, prettier, eslint all green. Out of scope (follow-ups): lunora dev wiring, a real deploy driver.

Plan: plans/234-*.md.

🤖 Generated with Claude Code

Stand up @lunora/platform-node — a Node host over better-sqlite3 plus
an in-process socket/directory/scheduler registry — and run the
existing @lunora/platform and @lunora/shard-engine conformance TCKs
against it (38/38 pass). Register NODE_CAPABILITIES honestly rated
per feature, wire a `node` target into codegen's PLATFORM_MATRICES,
and exercise the fail-closed capability gate against a matrix that is
mostly unsupported/emulated.

Registering `node` exposed that @lunora/config's driver-registry
invariant conflated "codegen can gate this target" with "the CLI can
deploy to this target" — narrow that test to the direction that
actually matters (every deploy driver needs a matrix; the reverse no
longer holds now that a dev/test-only host exists).

Every place construction needed something the contracts didn't
promise is classified in plans/234-node-host-findings.md, including
two latent bugs found by contrast in the existing node:sqlite
reference host and an architecture gap where ShardDirectory's
jurisdiction contract member has no real caller in the codebase.
@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

🗂️ Base branches to auto review (2)
  • main
  • alpha

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: c89f5a7f-12b7-42d6-8045-9f06519bccf7

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Thank you for following the naming conventions! 🙏

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Thank you for confirming the Contributor License Agreement! 🙏

@prisis prisis changed the title feat(platform-node): a second host over node:sqlite + run the conformance TCK against it (spike) feat(platform-node): a second host over better-sqlite3 + run the conformance TCK against it (spike) Aug 1, 2026
…an't fire on a closed DB and timers/handles don't leak

Nothing previously closed the better-sqlite3 handle or cleared pending
timers: a caller that set a future alarm and then closed the database
hit an uncaught TypeError from inside a setTimeout callback (a crash
that never touches the caller's own try/catch), and the composition
root plus the conformance host's cleanup both leaked the alarm and
scheduler timers, keeping the process alive well past teardown.

- Guard the alarm callback on `database.open` so a closed connection
  can never take a `.run()` again.
- Give createNodeShardHost/createNodeSchedulerHost a `dispose()` that
  clears their own timers (and, for the shard host, closes the DB).
- Add NodePlatform.close()/[Symbol.dispose] composing both disposers,
  and route the conformance host's cleanup() through the same path
  instead of a bare `database.close()`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Base automatically changed from advisor/229-platform-honesty to alpha August 1, 2026 10:56
@prisis
prisis merged commit 6a1664b into alpha Aug 1, 2026
4 checks passed
@prisis
prisis deleted the advisor/234-platform-node-spike branch August 1, 2026 10:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant