Jazz 2.0.0-alpha.53 baseline evidence
Date: 2026-07-15
Repository commit under test: 00c7f18
Host: macOS 26.5.1 (25F80), Apple silicon
Runtime: Deno 2.9.0, V8 14.9.207.2, TypeScript 6.0.3
Browser: Playwright Headless Chrome 150.0.0.0
Package: jazz-tools@2.0.0-alpha.53
Tarball SHA-1: d8e6f902498c13234da9cf02e530880bab183c4e
Tarball integrity:
sha512-GSAt9axXPaZY3g0bZxEPeAmq/
The npm tarball and deno.lock agree on version and integrity. The package does not publish a
gitHead. Jazz's main branch at 3384730e1c4509524b38c52fc9102fc6753411aa was inspected only for
context and is not represented as the source commit for this package.
Repeatable commands
deno check spikes/jazz2-baseline/*.ts spikes/jazz2-baseline/src/*.ts
deno task spike:jazz2:build
deno task spike:jazz2:dev
deno task spike:jazz2:cloud
deno task check:secrets
Browser procedure (using playwright-cli; equivalent DevTools actions are acceptable):
- Start
deno task spike:jazz2:dev --port 4177 --strictPort, open the printed URL, and snapshot. - Add
retained-alpha53-control; wait until the UI saysconfirmed local; reload and verify the row remains. - Get the row ID from
li[data-note-id]and callglobalThis.__LOFI_JAZZ2_PROBE__.update(id, "after-update"); verify the subscribed list and durability state change, then reload again. - Open a second tab at the same origin, add
multitab-follower-write, and verify it appears in both tabs. - Set the browser context offline, add
offline-local-write, wait for local confirmation, restore the network, and verify both tabs converge without reloading. - Start
deno task spike:jazz2:cloud --port 4178 --strictPort, addcloud-global-alpha53, and wait until the UI saysglobal write confirmed. - Save browser storage state to ignored
.playwright-cli/, load it in a fresh browser context, open the cloud URL, and verify the cloud row downloads. The state file contains the bearer identity and must never be committed or printed.cloud-identity-state.json
The cloud task publishes the spike schema to the configured Jazz application. It projected only the public app ID and server URL to the client. The test retained one note in that application; no credential value is recorded here.
Results
| Control | Result | Evidence |
|---|---|---|
| Deno type-check | pass | Exact npm pin resolved through deno.json and deno.lock. |
| Deno production build | pass | Vite transformed 371 modules without a user-facing Node command. |
| Persistent-driver boot | pass after compatibility fix | Chrome reported OPFS, SharedWorker, MessageChannel, and Web Locks; Jazz opened its persistent driver. |
| Immediate local write | pass | Subscription rendered the row before network confirmation. |
| Query and update | pass | subscribeAll returned the row; Db.update changed it, reached local durability, and survived reload. |
| Local durability | pass | WriteResult.wait({ tier: "local" }) resolved. |
| Reload retention | pass | The row remained after a full page reload. |
| Offline write | pass | Browser network state was offline; a row rendered and reached local durability. |
| Multi-tab | pass | A second tab wrote through the follower path and both tabs received two rows. |
| Managed-cloud durability | pass | WriteResult.wait({ tier: "global" }) resolved against the configured Jazz server. |
| Clean second cloud client | pass | A second browser context with the same restored identity and no copied OPFS data received the cloud row. |
| Server-secret build scan | pass | 57 files, including 27 nested build artifacts, scanned against both available server secrets. |
| Physical devices | not tested here | Owned by #4 and #8. |
The original run recorded screenshots named
output/ and
output/; those artifacts are not present in this
checkout, so they are not cited as retained evidence here.
Compatibility findings
- Deno's npm layout puts
jazz-wasmundernode_modules/. Jazz resolves the WASM to an absolute path, while Vite initially allows only the nested spike root. The browser received HTTP 403 until the Vite configuration allowed the repository root. This fix is required for the nested Astro prototype too..deno - With the raw vendor command on a clean first local run, Jazz writes
VITE_JAZZ_APP_IDinto the spike's ignored.env. Vite restarts while starting and Deno/Vite 8 failed withListen method has been called more than once without closing.A rerun started in 102 ms. The lofi task runner now pre-seeds a stable internal app ID; a clean wrapped first run started in 103 ms without a restart. The raw failure is retained because the integrated prototype must keep this edge. - A Vite configuration restart can change the generated local server URL while a persistent browser
broker is alive. Jazz then raised
IncompatibleBrowserBrokerConfigurationErrorand required a page reload. The prototype must keep the runtime singleton stable and make reload recovery explicit. - The plugin's TTY-only local server banner prints its generated admin secret. lofi cannot expose that banner unchanged under DX-ENV-01.
BrowserAuthSecretStoreuses localStorage and documents a non-atomic check-then-write on the first concurrent visit. First-run multi-tab identity creation needs lofi coordination or a documented limitation.- The browser console emitted Jazz WASM
CatalogueWriteDeniedwarnings while both local and global application-row waits succeeded. This is non-blocking for the baseline but must stay visible during #5/#6; lofi must not suppress it without proving that it is harmless catalogue traffic.
Runtime topology and transport
The exact tarball's persistent-browser path uses a SharedWorker broker to elect one leader tab. The
leader owns the module worker that runs the persistent WASM/OPFS path; follower tabs attach through
message ports. The upstream application-data transport is a Rust-owned WebSocket opened by the
runtime. The package's sync-transport.js explicitly says the earlier HTTP/SSE path was removed.
Schema publication by the development plugin remains an HTTP control-plane operation and is not the
application-data sync transport.
Public API inventory
| Area | Exact alpha.53 surface | M1 interpretation |
|---|---|---|
| Schema | schema.table, scalar/json/enum/ref/array columns, defineSchema, defineApp |
Directly supported; keep the vendor schema in schema.ts. |
| Query | typed where, select, include, orderBy, limit, offset, graph hops/gather; Db.all, one, subscribeAll |
Directly supported; reactive binding must reconcile subscription deltas. |
| Mutation | insert, restore, upsert, update, delete, batch, transaction, local/global WriteHandle waits |
Directly supported; lofi adapts status/error presentation. |
| Migration | typed defineMigration, add/drop/rename operations and tables; CLI create/push workflow |
Supported but not exercised by this minimal schema; author workflow remains post-M1. |
| Permissions | typed definePermissions, per-operation always/never/where, creator, relation, session and allowed-to conditions |
Directly supported; the control scopes rows to the local-first identity. |
| Identity | namespaced BrowserAuthSecretStore; local secret, JWT, cookie session; auth state/listener and local-first proof |
Local-first identity directly supported; lofi owns first-run coordination and wording. |
| Recovery phrase | RecoveryPhrase.fromSecret / toSecret with typed validation errors |
Direct bearer-secret conversion; UX/security validation belongs to #8. |
| Passkey backup | BrowserPasskeyBackup.backup / restore, explicit RP ID, typed errors |
Direct backup/restore primitive, not conventional login; device validation belongs to #8. |
| Persistence | persistent or memory driver, OPFS database name, local durability wait, storage deletion | Persistent path supported; capability/termination/device matrix belongs to #4. |
| Sync control | server URL, per-write global wait, disconnect / reconnect |
Core supported; connection-state claims remain unavailable. |
Desired lofi surface disposition
| Desired lofi surface | Disposition | Basis |
|---|---|---|
Application schema in schema.ts |
directly supported | Jazz's typed relational schema is already concise. |
| One runtime per browser realm | adapted | Cache one Jazz Db and own HMR disposal outside product UI. |
| Reactive list/query binding | adapted | Wrap subscribeAll and reconcile deltas for framework identity stability. |
| Local create/update/delete | directly supported | Synchronous mutations plus local durability waits. |
| Retained/global write status | directly supported | WriteHandle.wait at local and global tiers. |
| Storage capability and boot diagnosis | instrumented | Browser capability probes plus persistent-driver success/failure. |
| Sync configured state | directly supported | Complete validated public configuration pair. |
| Live sync connection state | unavailable | No public state/listener in this pin. |
| Pending write count | unavailable | No public pending-operation API in this pin. |
| Mutation rejection UX | adapted | onMutationError and rejected waits feed lofi diagnostics. |
| Local-first recovery phrase | adapted | Direct primitive; lofi must provide bearer-secret warnings. |
| Passkey backup/restore | adapted | Direct primitive; lofi must stabilize RP ID and device UX. |
| PWA shell/update lifecycle | outside Jazz | Astro/service-worker layer owns application assets and updates. |
Observability inventory
| Claim | Public alpha.53 evidence | Decision |
|---|---|---|
| Persistent storage requested | DbConfig.driver: { type: "persistent" } |
Report requested mode and boot failure honestly. |
| Local durability confirmed | WriteHandle.wait({ tier: "local" }) |
Report per-write confirmation. |
| Cloud durability confirmed | WriteHandle.wait({ tier: "global" }) |
Report per-write confirmation. |
| Sync configured | Presence of a validated server URL | Report configured, never infer connected. |
| Manual offline control | Public Db.disconnect() / Db.reconnect() |
Expose only for tests/diagnostics; follower restrictions require care. |
| Auth state | Db.getAuthState() / Db.onAuthChanged() |
Suitable for truthful identity wording. |
| Mutation rejection | Db.onMutationError() and rejected write waits |
Surface impact and action. |
| Live transport connection | No public listener/state found | Do not claim connected/disconnected from configuration. |
| Pending operation count | No public API found | State unavailable; do not estimate. |
| Active subscriptions | Internal diagnostic API only | May guard development tests, not product UI. |
Bundle observation
The control build emitted a 9,799.43 kB raw Jazz WASM asset (3,134.95 kB gzip). M1 does not set a bundle budget, but #4 must measure installed cold-start/offline behavior rather than assuming the asset is harmless.
Gate decision
Go for the Preact and Astro/Deno integration spikes using this pin and the lofi-owned runtime edge. The edge already prevents the clean-first-run restart and preserves the Vite filesystem allowance. Do not graduate M1 until the integrated runtime owns singleton/HMR lifecycle and the public command avoids the vendor secret-printing banner. #4 and #8 remain independent gates for physical-device durability and recovery semantics.