Skip to content

chore(release): version packages#281

Open
github-actions[bot] wants to merge 1 commit into
mainfrom
changeset-release/main
Open

chore(release): version packages#281
github-actions[bot] wants to merge 1 commit into
mainfrom
changeset-release/main

Conversation

@github-actions

@github-actions github-actions Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.

Releases

@xnetjs/core@0.1.0

Minor Changes

  • #284 d6d0470 Thanks @crs48! - Add shared dependency-free helpers to @xnetjs/core and unify the SSRF guard.

    @xnetjs/core now exports clamp, clamp01, formatBytes, and the
    literal-host SSRF guard (assertPublicUrl, validateExternalUrl, SsrfError),
    replacing several behaviour-identical copies that had drifted across packages —
    including byte formatters that silently capped at megabytes and a regex-based
    URL guard that missed private ranges (CGNAT, IPv4-mapped IPv6, NAT64, the
    fe81::–fe8f:: link-local block, and the trailing-dot bypass).
    @xnetjs/plugins now delegates its outbound-action SSRF check to the canonical
    guard while keeping its ActionSsrfError contract; @xnetjs/react byte
    displays no longer cap at megabytes.

@xnetjs/data@0.1.0

Minor Changes

  • #328 f626e50 Thanks @crs48! - Add the account/device ledger schemas (explorations 0149 + 0243, Phase 2 foundation):
    AccountRecord, DeviceRecord, RecoveryRecord, and RevocationRecord. A stable
    account subject owns a set of records describing which devices may act as the account,
    which recovery methods exist, and which keys are revoked (with status + epoch for
    revocation), so the cloud billing binding can later pin to the account root instead of
    a single device DID.

    Ships with deterministic ids (accountRecordId / deviceRecordId / …) and the pure
    authorization resolution the hub will enforce — resolveActiveDevices and
    isDeviceAuthorized ("is this device currently authorized for this account?"). The
    records are authorization-exempt at the schema level because access is controller-
    signed and epoch-gated (hub-enforced), not a per-node role cascade; signing enforcement
    and the binding migration are follow-ups.

  • #329 df76bef Thanks @crs48! - Add account/device ledger operations (explorations 0149 + 0243, Phase 2): pure
    builders that turn a ledger intent into the deterministic node to upsert —
    createAccountRecord, admitDeviceRecord, revokeDeviceRecord /
    revokeSubjectRecord (which bumps the account epoch), plus accountState to resolve
    the current epoch and the set of devices that may currently act as an account. These
    are the rules the store/hub wiring and the content-key re-wrap will call; keeping them
    pure makes device admit/revoke unit-testable on its own.

  • #277 4658b8f Thanks @crs48! - Materialized views can now coexist with read authorization. Each
    materialization is stamped with a reload-stable authorization fingerprint
    (subject + grant-state version), so a view is authorized once at refresh and
    served from the persisted cache without per-row re-checks — while any grant
    change forces an authz-changed re-materialization. The cached id list can
    never serve a row a revoked viewer may no longer read. Adds a nullable
    auth_fingerprint column to node_query_materializations (schema v7, applied
    to existing databases via a defensive column guard) plus optional
    setNodeReadAuthorizer / getAuthorizationStateVersion storage-adapter seams.

  • #278 4aec093 Thanks @crs48! - Fix the cold-start boot stall and silent registry persistence failure (exploration 0227).

    Workspace presence Y.Docs (presence-*) are now in-memory only — never
    cold-loaded from yjs_state nor persisted back — so presence-doc warming no
    longer head-of-line blocks the landing read queries on the single SQLite worker
    at boot. NodePoolConfig gains isEphemeral and largeDocWarnBytes options.

    The sync registry now persists its tracked-node set through a new FK-free
    app-state key/value (getAppState/setAppState on the storage adapter, backed
    by sync_state) instead of yjs_state, fixing a SQLITE_CONSTRAINT_FOREIGNKEY
    (787) that silently prevented the registry from ever persisting.

  • #331 37d4462 Thanks @crs48! - Add account/device content-key re-wrap to computeRecipients (exploration 0243, P2.3).
    A new optional expandDeviceRecipients dependency lets each DID recipient expand to
    every currently active device of the account it belongs to, so a user's content is
    decryptable on all their devices: admitting a device (a DeviceRecord) makes it a
    recipient on the next recompute, and revoking it removes it from future re-wraps.
    Build the function from ledger records with the new deviceRecipientExpander. When the
    dependency is omitted, recipients are exactly the resolved DIDs (no behavior change),
    and an identity that belongs to no account expands to only itself — so an unrelated DID
    never gains access to another account's data.

  • #283 e531d0d Thanks @crs48! - Extend the map layer-source model for richer GIS layers (exploration 0230).

    MapLayerSource gains two new kinds — raster (an XYZ imagery/topo tile
    overlay) and pmtiles (a self-hosted vector tileset referenced by BlobStore
    content id) — and the reserved query kind now carries an optional where
    filter and tooltip property keys. MapBasemapId adds a key-less satellite
    basemap. All additive; existing inline-GeoJSON maps are unaffected.

Patch Changes

@xnetjs/identity@0.1.0

Minor Changes

  • #339 4fb460a Thanks @crs48! - Wire social recovery ("trusted guardians") into the UI (exploration 0243) — xNet's
    Apple-recovery-contacts analogue. Settings → Account can split a recoverable identity
    into 3 guardian share codes (any 2 recover it), and onboarding gains a "Recover with
    guardian shares" path that reconstructs the identity from enough codes on a new device.
    @xnetjs/identity adds serializeShare / parseShare for the copy-pasteable
    xnet-share:… codes. Recovery is entirely user-to-user; the cloud is never involved.

  • #320 d7a87da Thanks @crs48! - Add recoverable-identity primitives so a lost passkey no longer means lost data
    (exploration 0243, Phase 1). A recovery phrase now deterministically reproduces the
    same DID and the same X25519 encryption key on any device — which is what gates
    access to end-to-end-encrypted data — so typing the phrase restores your workspace
    without any custodial escrow.

    New exports from @xnetjs/identity:

    • generateRecoveryPhrase() / validateRecoveryPhrase() — mint and check phrases
      against the recovery wordlist (now exported as RECOVERY_WORDLIST); defaults to a
      24-word (~144-bit) phrase.
    • recoveryPhraseToBundle() / didForRecoveryPhrase() / createRecoverableIdentity()
      — derive a full key bundle (or just the DID) from a phrase; identical on every
      device.
    • sealRecoveryPhrase() / openRecoveryPhrase() — encrypt a phrase at rest so it can
      be re-shown later behind a passkey gate.

    These are pure (no WebAuthn/storage); the IdentityManager and onboarding wiring land
    in a follow-up.

  • #322 fc3aa1d Thanks @crs48! - Add opt-in recoverable identities to the IdentityManager (exploration 0243, Phase 1).
    A recoverable identity is born from a recovery phrase and gated by a passkey, so it can
    be rebuilt on any device by typing the phrase — without weakening the default, which
    stays the stronger PRF-derived identity that stores nothing at rest.

    New IdentityManager methods:

    • createRecoverable() — mint a new identity from a fresh phrase, enroll a gating
      passkey, and return the phrase to show once.
    • importRecoveryPhrase(phrase) — adopt an identity from a phrase on a new device
      (lost passkey), reproducing the same DID and X25519 key.
    • exportRecoveryPhrase() — reveal the phrase behind a passkey gate (Settings "view
      phrase"); returns null for non-recoverable identities.
    • isRecoverable() — whether the stored identity has a saved phrase.

    The sealed phrase is persisted alongside the encrypted bundle (storeIdentity gains an
    optional recovery arg). Also exports enrollRecoverableIdentity.

  • #335 5da8d92 Thanks @crs48! - Add the privacy-preserving recovery-escrow primitive (exploration 0243, P3.1). Escrow
    lets a user recover without keeping a long recovery phrase, but without letting the
    cloud read their data alone
    : sealEscrow/openEscrow encrypt the recovery backupKey
    under a user-held PIN (plus serializeEscrow/deserializeEscrow for the opaque blob the
    cloud KMS-wraps). Recovery then needs both a verified WorkOS session (the cloud's KMS
    factor) and the PIN (the user's factor). A new @xnetjs/cloud/escrow module holds the
    cloud half (EscrowStore, injected KmsWrapper, and enable/disable/recover with
    session-gating — escrow is absent unless enabled and unreachable without a verified
    session). The fully-custodial "cloud can recover from the login alone" variant is
    deliberately not built; it needs an explicit product decision (see the design note).

  • #337 b327f99 Thanks @crs48! - Add social-recovery ("guardians") methods to the IdentityManager (exploration 0243) —
    the Apple-ADP "recovery contacts" analogue, built on the Shamir secret-sharing already
    in seed-recovery.ts. createGuardianShares(config) splits a recoverable identity's
    phrase into totalShares shares of which any threshold reconstruct it (prompting for
    the passkey to read the phrase); recoverFromGuardianShares(shares) reconstructs the
    phrase from enough shares on a new device, reproduces the same DID, and enrolls a local
    passkey. Recovery is entirely user-to-user — the cloud is never involved, so it stays
    zero-knowledge and non-coercible by construction.

  • #333 ddf47b9 Thanks @crs48! - Surface synced-passkey recovery in onboarding (exploration 0243, P1.4). The
    IdentityManager gains recoverViaSyncedPasskey(), which discovers an xNet passkey
    synced from another device (iCloud Keychain / Google Password Manager), unlocks it
    (same PRF → same DID), and stores it locally — returning null when none is available so
    the caller can fall back to the recovery phrase. The import screen now leads with a
    "Use a synced passkey" option (new USE_SYNCED_PASSKEY onboarding event), giving
    same-ecosystem users a phrase-free return path.

Patch Changes

  • Updated dependencies [d6d0470]:
    • @xnetjs/core@0.1.0
    • @xnetjs/crypto@0.1.0

@xnetjs/plugins@0.1.0

Minor Changes

  • #291 acbf801 Thanks @crs48! - AI assist now defaults to a "scaffold" mode that keeps you the author — the model
    proposes and cites, you write and own — as a guard against LLM deskilling
    (Humane Internet Charter §Agency). Every assistant turn is tagged with
    ai-generated provenance and the mode it was produced under, and a new
    composeAssistSystemPrompt helper appends the cognitive-debt guard in scaffold
    mode. draft mode (the model writes finished prose) must be opted into
    explicitly via assistMode: 'draft'.

  • #349 1a44c5d Thanks @crs48! - Connector detection now reports the in-tab AI tiers as available only when they
    can actually run, fixing a chat composer that stayed disabled with no
    explanation. webllm is gated on a new ConnectorEnv.hasWebLLMEngine probe (in
    addition to WebGPU) so it's never advertised without a host-supplied engine, and
    the default prompt-api probe now reads LanguageModel.availability() and
    treats only 'available' as ready (mere API presence with a 'downloadable'
    model no longer counts). Adds promptApiAvailability() (raw state, for offering
    a download gesture) and downloadPromptApiModel() (gesture-driven, monitored
    download), plus the PromptApiAvailability and LanguageModelMonitor types.

  • #316 2a638ec Thanks @crs48! - The managed XNet Cloud AI provider (ManagedProvider) now supports streaming.
    It implements stream() over the new /ai/chat/stream SSE endpoint — yielding
    text deltas as they arrive and reporting the live budget from the terminal event —
    and its capabilities now advertise streaming: true. A pre-stream 402 or an
    ai_budget_exceeded event surfaces as a typed AiBudgetError, same as the unary
    path. Non-streaming callers are unaffected.

  • #293 3c8a6a6 Thanks @crs48! - Add the Right to Leave service (Humane Internet Charter §Exit): leaveWithEverything
    bundles your whole workspace, your portable did:key identity, and a re-import
    README into one archive, and deleteDay tombstones remote copies and (optionally)
    wipes the local master — emitting only an anonymous account.left signal. Leaving
    takes everything and loses nothing, with no confirmshaming.

Patch Changes

  • #284 d6d0470 Thanks @crs48! - Add shared dependency-free helpers to @xnetjs/core and unify the SSRF guard.

    @xnetjs/core now exports clamp, clamp01, formatBytes, and the
    literal-host SSRF guard (assertPublicUrl, validateExternalUrl, SsrfError),
    replacing several behaviour-identical copies that had drifted across packages —
    including byte formatters that silently capped at megabytes and a regex-based
    URL guard that missed private ranges (CGNAT, IPv4-mapped IPv6, NAT64, the
    fe81::–fe8f:: link-local block, and the trailing-dot bypass).
    @xnetjs/plugins now delegates its outbound-action SSRF check to the canonical
    guard while keeping its ActionSsrfError contract; @xnetjs/react byte
    displays no longer cap at megabytes.

  • Updated dependencies [f626e50, df76bef, 4658b8f, 4aec093, 37d4462, e531d0d, d6d0470]:

    • @xnetjs/data@0.1.0
    • @xnetjs/core@0.1.0
    • @xnetjs/abuse@0.1.0

@xnetjs/react@0.1.0

Minor Changes

  • #341 1306265 Thanks @crs48! - Make guardian (social) recovery configurable and threshold-aware (exploration 0243).
    Settings lets you choose how many guardians (2–7) and how many are needed; the onboarding
    recovery screen now reads the required threshold from the pasted share codes and only
    enables recovery once you have enough (rather than assuming 2-of-3), flagging unrecognized
    codes as you paste.

  • #339 4fb460a Thanks @crs48! - Wire social recovery ("trusted guardians") into the UI (exploration 0243) — xNet's
    Apple-recovery-contacts analogue. Settings → Account can split a recoverable identity
    into 3 guardian share codes (any 2 recover it), and onboarding gains a "Recover with
    guardian shares" path that reconstructs the identity from enough codes on a new device.
    @xnetjs/identity adds serializeShare / parseShare for the copy-pasteable
    xnet-share:… codes. Recovery is entirely user-to-user; the cloud is never involved.

  • #324 a155c43 Thanks @crs48! - Wire opt-in recovery phrases into onboarding (exploration 0243, Phase 1). The welcome
    screen gains a "Set up a recovery phrase too" option that mints a recoverable identity
    and shows the phrase once to save; the "Enter recovery phrase" path now validates the
    phrase against the wordlist and recovers the same identity on a new device (enrolling a
    local passkey to gate it). New machine states creating-recoverable /
    show-recovery-phrase and events CREATE_RECOVERABLE / SUBMIT_PHRASE /
    RECOVERABLE_CREATED / PHRASE_SAVED / IMPORT_FAILED.

  • #333 ddf47b9 Thanks @crs48! - Surface synced-passkey recovery in onboarding (exploration 0243, P1.4). The
    IdentityManager gains recoverViaSyncedPasskey(), which discovers an xNet passkey
    synced from another device (iCloud Keychain / Google Password Manager), unlocks it
    (same PRF → same DID), and stores it locally — returning null when none is available so
    the caller can fall back to the recovery phrase. The import screen now leads with a
    "Use a synced passkey" option (new USE_SYNCED_PASSKEY onboarding event), giving
    same-ecosystem users a phrase-free return path.

Patch Changes

  • #284 d6d0470 Thanks @crs48! - Add shared dependency-free helpers to @xnetjs/core and unify the SSRF guard.

    @xnetjs/core now exports clamp, clamp01, formatBytes, and the
    literal-host SSRF guard (assertPublicUrl, validateExternalUrl, SsrfError),
    replacing several behaviour-identical copies that had drifted across packages —
    including byte formatters that silently capped at megabytes and a regex-based
    URL guard that missed private ranges (CGNAT, IPv4-mapped IPv6, NAT64, the
    fe81::–fe8f:: link-local block, and the trailing-dot bypass).
    @xnetjs/plugins now delegates its outbound-action SSRF check to the canonical
    guard while keeping its ActionSsrfError contract; @xnetjs/react byte
    displays no longer cap at megabytes.

  • Updated dependencies [f626e50, df76bef, acbf801, 4658b8f, 985ac8f, 4aec093, 37d4462, 0f7e114, e531d0d, 4fb460a, 1a44c5d, 2a638ec, cae9734, d7a87da, fc3aa1d, 5da8d92, 3c8a6a6, d6d0470, b327f99, ddf47b9]:

    • @xnetjs/data@0.1.0
    • @xnetjs/plugins@0.1.0
    • @xnetjs/runtime@0.1.0
    • @xnetjs/identity@0.1.0
    • @xnetjs/core@0.1.0
    • @xnetjs/data-bridge@0.1.0
    • @xnetjs/history@0.1.0
    • @xnetjs/sync@0.1.0
    • @xnetjs/crypto@0.1.0

@xnetjs/runtime@0.1.0

Minor Changes

  • #278 4aec093 Thanks @crs48! - Fix the cold-start boot stall and silent registry persistence failure (exploration 0227).

    Workspace presence Y.Docs (presence-*) are now in-memory only — never
    cold-loaded from yjs_state nor persisted back — so presence-doc warming no
    longer head-of-line blocks the landing read queries on the single SQLite worker
    at boot. NodePoolConfig gains isEphemeral and largeDocWarnBytes options.

    The sync registry now persists its tracked-node set through a new FK-free
    app-state key/value (getAppState/setAppState on the storage adapter, backed
    by sync_state) instead of yjs_state, fixing a SQLITE_CONSTRAINT_FOREIGNKEY
    (787) that silently prevented the registry from ever persisting.

  • #302 0f7e114 Thanks @crs48! - Add runAdapterConformance(makeClient) — the executable "use xNet from any
    framework" contract. It validates the reactive data binding (immediate live-query
    snapshot then updates on mutate, no delivery after unsubscribe, one-shot fetch
    round-trip, authorization denial surfaces, idempotent destroy()) once,
    framework-agnostically, so a Vue/Svelte/Solid adapter only needs a thin
    render-harness test on top. Exported alongside AdapterConformanceError and the
    ConformanceClientFactory / AdapterConformanceCheck / AdapterConformanceResult
    types.

Patch Changes

  • #280 985ac8f Thanks @crs48! - Boot-stall diagnosis and two fixes (exploration 0229).

    @xnetjs/sqlite: the worker now emits boot-debug-gated diagnostics — a
    per-operation queue-wait-vs-execution timing trace and a one-shot DB-stats line
    at open (file size, page/freelist counts, storage mode). This is threaded via a
    new bootDebug flag on SQLiteConfig (the worker can't read localStorage). It
    separates head-of-line queueing from real SQL/OPFS cost, which finally localizes
    the recurring cold-start stall to a single operation.

    @xnetjs/runtime: SyncManager now dials the hub before loading the offline
    queue instead of after, so the WebSocket handshake is no longer serialized
    behind local storage (which, when the single SQLite worker stalls, delayed sync
    by ~18s even though the hub answers in ~200ms). The queue loads in the
    background and the connect-time drain re-runs once entries are available.

  • #356 cae9734 Thanks @crs48! - Outbound resync no longer blocks the main thread for seconds on cold open (exploration 0253).

    When the persisted sync cursor lags far behind the local change log (e.g. the hub never
    confirmed the tail — INVALID_HASH skew), syncLocalChanges() fetched every change since the
    cursor and processed the whole slice synchronously right after the sync-response resolved — the
    single ~5s uninterrupted main-thread long task seen in cold-open captures. Two fixes:

    • The equal-lamport tie-break now uses code-unit order instead of String.localeCompare,
      which is orders of magnitude faster over a large tie-heavy slice and matches the code-unit
      collation the inbound apply path already uses (the query already returns lamport-ASC order, so
      this only orders ties).
    • The enqueue loop yields to the event loop every 1024 changes, so a large first-sync slice
      can no longer monopolise a frame regardless of size.

    A one-line self-gating [NodeStoreSync] heavy outbound resync diagnostic names the residual
    synchronous cost (the per-row deserialize inside getChangesSince) when a resync is large, to
    size the durable fix (compacting the change log). No public API or wire-contract change.

  • Updated dependencies [f626e50, df76bef, acbf801, 4658b8f, 4aec093, 37d4462, e531d0d, 4fb460a, 1a44c5d, 2a638ec, d7a87da, fc3aa1d, 5da8d92, 3c8a6a6, d6d0470, b327f99, ddf47b9]:

    • @xnetjs/data@0.1.0
    • @xnetjs/plugins@0.1.0
    • @xnetjs/identity@0.1.0
    • @xnetjs/core@0.1.0
    • @xnetjs/data-bridge@0.1.0
    • @xnetjs/history@0.1.0
    • @xnetjs/storage@0.1.0
    • @xnetjs/sync@0.1.0
    • @xnetjs/crypto@0.1.0

@xnetjs/sqlite@0.1.0

Minor Changes

  • #277 4658b8f Thanks @crs48! - Materialized views can now coexist with read authorization. Each
    materialization is stamped with a reload-stable authorization fingerprint
    (subject + grant-state version), so a view is authorized once at refresh and
    served from the persisted cache without per-row re-checks — while any grant
    change forces an authz-changed re-materialization. The cached id list can
    never serve a row a revoked viewer may no longer read. Adds a nullable
    auth_fingerprint column to node_query_materializations (schema v7, applied
    to existing databases via a defensive column guard) plus optional
    setNodeReadAuthorizer / getAuthorizationStateVersion storage-adapter seams.

  • #280 985ac8f Thanks @crs48! - Boot-stall diagnosis and two fixes (exploration 0229).

    @xnetjs/sqlite: the worker now emits boot-debug-gated diagnostics — a
    per-operation queue-wait-vs-execution timing trace and a one-shot DB-stats line
    at open (file size, page/freelist counts, storage mode). This is threaded via a
    new bootDebug flag on SQLiteConfig (the worker can't read localStorage). It
    separates head-of-line queueing from real SQL/OPFS cost, which finally localizes
    the recurring cold-start stall to a single operation.

    @xnetjs/runtime: SyncManager now dials the hub before loading the offline
    queue instead of after, so the WebSocket handshake is no longer serialized
    behind local storage (which, when the single SQLite worker stalls, delayed sync
    by ~18s even though the hub answers in ~200ms). The queue loads in the
    background and the connect-time drain re-runs once entries are available.

  • #282 d4bfe27 Thanks @crs48! - Add parallel SQLite reads to the Electron better-sqlite3 adapter (exploration
    0230). Unlike the browser — where opfs-sahpool holds an exclusive handle so a
    second connection is impossible — native SQLite + WAL allows one writer
    concurrent with many readers, each on its own connection. The adapter now:

    • fronts the writer with the shared priority scheduler (scheduler config,
      default on) so a write/import burst can't head-of-line block an interactive
      read;
    • optionally opens a read-only secondary connection (readonlyReadConnection)
      so plain reads don't contend with write locks;
    • optionally spawns a pool of read-only worker_threads readers
      (readerPoolSize, 'auto' sizes to the host) that serve heavy reads
      (FTS, aggregates, large scans) in parallel on other cores, with least-busy
      dispatch and graceful fallback to the inline connection;
    • yields cooperatively between chunks in applyNodeBatch so a long import no
      longer monopolizes the data-process thread;
    • exposes getDiagnostics() / getWalStats() / checkpointWal() plus a
      read-your-writes window (readYourWritesWindowMs).

    All additive — existing callers are unaffected, and the new behaviour is
    opt-in via config (the scheduler is on by default but only reorders
    non-transactional work).

  • #307 7e6f5b7 Thanks @crs48! - Add OPFS capability detection so the storage layer can pick and explain its
    durable backend before opening — detectOpfsCapability(), plus the
    supportsOpfs, supportsSyncAccessHandle, and isCrossOriginIsolated
    predicates and the OpfsCapability / OpfsPersistenceMode types. The web
    adapter uses it to emit an accurate diagnostic when synchronous access handles
    are unavailable (iOS 15.2–16.3 / older WebViews) — it falls back to the async
    OPFS backend, which is still durable, rather than logging a misleading error.
    This makes the mobile-webview hosting path (exploration 0238) legible: hosts can
    branch on capability and target the right minimum OS.

  • #355 3261a75 Thanks @crs48! - Web SQLite open() now retries on timeout instead of hard-failing the boot (exploration 0253).

    A cold installOpfsSAHPoolVfs() on a large database file intermittently exceeds the 15s
    open timeout — most often because a prior boot's open timed out and leaked a worker still
    holding the file's exclusive OPFS sync access handle, so the next boot's
    createSyncAccessHandle() blocks on the contended handle. Previously the first timeout threw
    ("Initialization failed: Worker initialization timeout after 15s") and showed an error screen.

    WebSQLiteProxy.open() now terminates the stuck worker (releasing the handle) and retries with
    a fresh worker up to 3 attempts via the new openWithTimeoutRetry helper, so the leaked-handle
    cascade recovers instead of failing. A genuinely broken/unavailable OPFS still fails cleanly
    after the bounded attempts. Adds SQLiteConfig.openTimeoutMs (default 15000) to tune the
    per-attempt timeout.

  • #351 839b2b7 Thanks @crs48! - Cold-open boot diagnostics: bracket the SQLite worker's open/init window (exploration 0253).

    The 7th cold-open capture showed the ~17 s stall with execMs: 0 AND queueMs: 0 on
    every op — so it is neither slow SQL nor scheduler head-of-line blocking. The cost moved
    into the one window no timer brackets: the worker's open()/init and the dispatch gap
    before the first scheduled op. This adds the two missing log lines (gated behind
    bootDebug, never throws):

    • WebSQLiteAdapter now records per-phase open timings (OpenPhaseTimings:
      wasm import/init, OPFS VFS install incl. lock retries, capacity reserve, db open,
      pragmas, total) exposed via getOpenPhaseTimings(), plus public schemaApplyMs and
      openRetryAttempts. The worker host emits them as [xNet] sqlite open phases.
    • SchedulerOpReport gains enqueuedAt + startedAt so the worker host can tag the
      FIRST op after open with idleBeforeFirstOpMs (open → first enqueue, the upstream/
      transport wait) and sinceOpenMs (open → first exec) — the disambiguator between
      "stalled in open" and "stalled upstream".

    Diagnostic only; no behaviour change on the production path.

  • #279 d9008d2 Thanks @crs48! - Add a priority scheduler with read coalescing to the web SQLite worker
    (exploration 0228). All storage operations now drain through one scheduler
    inside the single worker both the main thread and data worker share:
    interactive reads are served ahead of queued writes, so a write or sync-apply
    burst can no longer starve a read (generalizing the 0227 head-of-line fix).
    Identical concurrent reads collapse into a single execution. A new
    getSchedulerSnapshot() exposes queue depth for diagnostics. This is ordering
    only — no parallelism is added, since opfs-sahpool is single-connection by
    construction.

Patch Changes

  • #288 b0cd77c Thanks @crs48! - Forward the SQLite Web Worker's boot-debug diagnostics to the main thread so the
    in-app Logs panel captures them (exploration 0229). The per-op queue/exec timing
    ([xNet] sqlite op) and one-shot DB stats ([xNet] db stats @ open) were
    emitted only in the dedicated worker's console, which the main-thread console tap
    never sees — so every boot-stall capture/export came back missing exactly those
    lines. The worker now postMessages each boot-debug line (under a dedicated
    discriminator key that can't collide with Comlink RPC) and WebSQLiteProxy
    re-emits it on the main console. Gated by xnet:boot:debug; no effect on normal
    operation.

  • #290 142b1c0 Thanks @crs48! - Memory-map OPFS reads (PRAGMA mmap_size) on the web adapter so the first cold
    query after a reload faults its working-set pages via the OS instead of
    thousands of synchronous 8 KiB reads on the single worker thread (exploration
    0233). The boot trace caught one cold landing query taking 15.8 s of pure
    execution while every later warm query was 0 ms — the page cache only helps
    re-reads, so mmap is the lever for the first read. Guarded: a no-op where the
    opfs-sahpool VFS doesn't support it.

  • #345 0e0802d Thanks @crs48! - Boot diagnostics: name every scheduled SQLite op in the boot log (exploration
    0249). The WorkerScheduler op report gains an optional detail field and
    schedule() an optional detail argument; the web worker now forwards each
    read/write op's whitespace-collapsed, param-free SQL text so a long execMs
    line names the exact statement instead of the generic query label. This is the
    missing field that kept the ~15 s cold-open stall unidentified across
    explorations 0227–0233. Additive and backward compatible — detail is optional
    and only emitted when boot debug (xnet:boot:debug) is on.

@xnetjs/abuse@0.1.0

Patch Changes

@xnetjs/cli@0.0.4

Patch Changes

@xnetjs/crypto@0.1.0

Patch Changes

  • Updated dependencies [d6d0470]:
    • @xnetjs/core@0.1.0

@xnetjs/data-bridge@0.1.0

Patch Changes

@xnetjs/history@0.1.0

Patch Changes

@xnetjs/storage@0.1.0

Patch Changes

@xnetjs/sync@0.1.0

Patch Changes

xnet-cloud@0.0.2

Patch Changes

  • Updated dependencies [2e7e4c7]:
    • @xnetjs/entitlements@0.0.2
    • @xnetjs/cloud@0.0.1
    • @xnetjs/crypto@0.1.0

@xnetjs/brain@0.0.3

Patch Changes

@xnetjs/comms@0.0.3

Patch Changes

@xnetjs/dashboard@0.0.3

Patch Changes

@xnetjs/entitlements@0.0.2

Patch Changes

  • #319 2e7e4c7 Thanks @crs48! - Fix the managed-AI plan model IDs to match OpenRouter's catalog: the Anthropic
    models use a dotted version (anthropic/claude-haiku-4.5,
    anthropic/claude-sonnet-4.6, anthropic/claude-opus-4.8), not a dashed one.
    The previous dashed IDs (…-4-5 / …-4-6 / …-4-8) don't exist upstream, so a
    tenant on a default Anthropic model got a model-not-found error. The OpenAI and
    Google IDs were already correct.

@xnetjs/labs@0.0.3

Patch Changes

@xnetjs/licenses@0.0.3

Patch Changes

  • Updated dependencies []:
    • @xnetjs/crypto@0.1.0

@xnetjs/maps@0.0.3

Patch Changes

@xnetjs/server@0.0.2

Patch Changes

@xnetjs/social@0.0.3

Patch Changes

@xnetjs/unreal@0.0.3

Patch Changes

@github-actions github-actions Bot force-pushed the changeset-release/main branch 25 times, most recently from 74286b7 to 05d53d8 Compare July 1, 2026 23:22
@github-actions github-actions Bot force-pushed the changeset-release/main branch from 05d53d8 to a8f8391 Compare July 2, 2026 00:00
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.

0 participants