Repository navigation
baukit v0.5.1
baukit v0.5.1
One release train for the Rust crates, TypeScript packages, and templates.
Summary
baukit 0.5.1 closes the gaps that Leitbild, Hebkit, and Redemut hit while adopting 0.5.0, so those products can delete code instead of wrapping Baukit. It is a patch release by number, but a few interfaces gained required methods. Since no product is live, those breaks shipped without shims. They are listed below.
New
@baukit/data-contracts:encodeCsvcan quote every cell and write null as a marker that stays distinct from empty text. The Rustbaukit_core::export::CsvOptionsgets the same options, and shared vectors pin both languages to the same bytes.@baukit/data-contracts:KeyValueStore.clearPrefix, aWebStorageKeyValueStoreforlocalStorageandsessionStorage, andDurableDraft.moveplusisScopeActive, so a draft can follow a newly created document and stop writing once another editor owns it.@baukit/data-contracts-expo-sqlite: a transaction onExpoSqliteConnectioncan nest. The inner work runs in a savepoint on the same handle, and a caught inner failure rolls back only the inner work.@baukit/api-runtime: mutation bodies can be interface types, products can plug in their own error classifier, overlappingkeyForcalls for one intent share a key, and the full-jitter backoff is public on@baukit/api-runtime/backoff.@baukit/a11y-core/web:useReducedMotionanduseReducedMotionPreferencewithout React Native.@baukit/sync-client:SyncSchedulerretries failed runs when given aretryoption with a product-chosen delay.baukit-push:DeliveryClaimStore::purgefor PostgreSQL and in-memory stores.@baukit/auth-node/keycloak-testing: the Keycloak e2e helpers that used to live only in the template. Generated auth web products import them from the package.
Breaking
KeyValueStoreimplementations must addclearPrefix, andDurableDraftimplementations must addmove.SqliteTransaction.transactionruns nested work and returns its result instead of always rejecting. Code that typed it asPromise<never>stops compiling.- A hand-written
IdempotencyKeyStoremust addclassifyError, and itskeyForandsettleare generic. DeliveryClaimStorehas a new requiredpurgemethod.- Auth web templates add
@baukit/auth-nodeas a dev dependency, and the helperallowWebOriginis nowallowKeycloakWebOrigin.
The sections below list every change per crate and package.
Verification
Every step of the local CI mirror passed on main before the version bump, and make ci passed again on the release commit. The mirror covered make ci, all Rust tests including Docker-gated ones (711), cargo deny, MSRV 1.95, all seven generated fixture flavors with coverage floors, the MCP fixture gate, browser Dexie conformance (36 tests), the Android compile gate, Expo SQLite on an Android emulator (33 cases), and the Hermes vector and notifications checks. The auth fixture's Keycloak stack e2e ran against the new helpers. iOS and physical devices were not tested.
Rust crates
baukit-auth
- No component-specific changes in this train.
baukit-config
- No component-specific changes in this train.
baukit-core
Added
- Add
CsvOptions::with_all_cells_quoted, which quotes every text and numeric cell and leaves
empty cells unquoted, andCsvOptions::with_null_marker, which writes a marker such as\Nfor
an empty cell and quotes text with the same content. Either keeps an empty cell apart from empty
text, so a product's importer can read its own export back.with_null_markerpanics on an empty
marker or one holding a double quote, comma, CR, or LF. The shared vectors gain five cases.
baukit-credential-vault
- No component-specific changes in this train.
baukit-egress
- No component-specific changes in this train.
baukit-events
- No component-specific changes in this train.
baukit-http
- No component-specific changes in this train.
baukit-integrations
- No component-specific changes in this train.
baukit-jobs
- No component-specific changes in this train.
baukit-openapi
- No component-specific changes in this train.
baukit-ops
- No component-specific changes in this train.
baukit-push
Added
- Add
DeliveryClaimStore::purge(before, limit), which deletes one batch of
claims for local dates beforebefore, oldest date first, and returns how
many went.PostgresDeliveryClaimStorerunspurge_delivery_claimson its
pool, andMemoryDeliveryClaimStorepurges in the same order, so scheduled
purge jobs no longer need a product repository method or a store they cannot
fake in tests.
Breaking
DeliveryClaimStorehas a new required method,purge. Custom
implementations must add it.
baukit-ratelimit
- No component-specific changes in this train.
baukit-runtime
- No component-specific changes in this train.
baukit-sync
- No component-specific changes in this train.
baukit-telemetry
- No component-specific changes in this train.
baukit-test
- No component-specific changes in this train.
TypeScript packages
a11y-core
Patch Changes
- 5a29c63:
@baukit/a11y-core/webexportsuseReducedMotion,useReducedMotionPreference, andReducedMotionPreference. The web versions usematchMediaanduseSyncExternalStoreand never importreact-native, so a plain React web app can use them. They return the same shapes as the root hooks. During server rendering and hydrationuseReducedMotionPreferencereports{ reducedMotion: false, resolved: false }. The root entry's hooks are unchanged. - Release the coordinated baukit 0.5.1 train.
analytics-core
Patch Changes
- Release the coordinated baukit 0.5.1 train.
analytics-posthog-native
Patch Changes
- Release the coordinated baukit 0.5.1 train.
- Updated dependencies
- @baukit/analytics-core@0.5.1
analytics-posthog-web
Patch Changes
- Release the coordinated baukit 0.5.1 train.
- Updated dependencies
- @baukit/analytics-core@0.5.1
api-runtime
Patch Changes
-
fa3e0c3:
MutationIntenttakes any body that JSON carries unchanged. It is now generic,MutationIntent<Body extends JsonCompatible<Body> = JsonValue>, so interface-typed request bodies no longer need a cast toJsonValue.keyFor,settle,sendIdempotentMutation, andcanonicalJsoninfer the body type. Members set toundefinedare left out of the key, andundefinedarray items encode asnull, asJSON.stringifydoes. New type:JsonCompatible.createIdempotencyKeyStoreacceptsclassifyError, aMutationErrorClassifierthat maps the product's own API errors to an outcome and returnsundefinedfor the rest. The store exposesclassifyError(error), which applies it beforeclassifyMutationError, andsendIdempotentMutationsettles failed sends with it.classifyMutationStatustakes an optional error code and treatsidempotency_key_in_progressas possibly committed.Overlapping calls for the same intent share one key from the first
keyForuntil the intent settles, even while storage is still reading or when storage drops writes. A failed lookup does not block the next one.New subpath
@baukit/api-runtime/backoffexportsfullJitterBackoffMsandBackoffPolicy, the delay formulacreateApiFetchalready used. It imports nothing.Breaking:
IdempotencyKeyStoregains a requiredclassifyErrormethod, and itskeyForandsettleare generic. A hand-written store or test double must add the method. -
Release the coordinated baukit 0.5.1 train.
auth-native
Patch Changes
- Release the coordinated baukit 0.5.1 train.
auth-node
Patch Changes
-
306a46f: Add the Node-only
@baukit/auth-node/keycloak-testingsubpath for end-to-end tests against a disposable development Keycloak.keycloakStack(defaults, environment)readsE2E_KEYCLOAK_URL,E2E_KEYCLOAK_REALM,E2E_KEYCLOAK_ADMIN_USERNAME,E2E_KEYCLOAK_ADMIN_PASSWORD, andE2E_KEYCLOAK_WEB_CLIENT_IDover the product's defaults.createKeycloakTestUser(stack, user?, options?)creates a verified user, randome2e-<uuid>by default, and returns its username, password, email, and subject.revokeKeycloakUserSessions(stack, subject)ends a user's sessions.allowKeycloakWebOrigin(stack, origin)adds an origin to the web client's redirect URIs and web origins when it lacks them.signInWithKeycloak(page, user, stack, { timeoutMs })fills the login form by its#username,#password, and#kc-loginIDs. Admin calls usefetchwith a 30-second default timeout and take an injectedfetch; errors name the step and HTTP status, never a response body. The page parameter is a structural type that a PlaywrightPagesatisfies, so the package still has no runtime or peer dependencies.No breaking changes to existing exports.
-
Release the coordinated baukit 0.5.1 train.
auth-web
Patch Changes
- Release the coordinated baukit 0.5.1 train.
data-contracts-dexie
Patch Changes
-
e26045b: Add
KeyValueStore.clearPrefix(prefix), which deletes every key that starts withprefix. Matching is exact and case-sensitive, no character is a wildcard, and an empty prefix clears the store.InMemoryKeyValueStore,DexieKeyValueStore(one IndexedDB key range), and the Expo SQLite key-value store (a UTF-8 byte prefix match inside the store's namespace) implement it, anddescribeKeyValueContractchecks it, including SQLLIKEwildcards, case, emoji, and U+FFFF. The Dexie real-browser suite now runs the key-value contract too.Breaking:
KeyValueStoregains a required method, so a product's ownKeyValueStoreimplementation must addclearPrefix. -
Release the coordinated baukit 0.5.1 train.
-
Updated dependencies [06cc669]
-
Updated dependencies [d423b98]
-
Updated dependencies [e26045b]
-
Updated dependencies
-
Updated dependencies [403805a]
- @baukit/data-contracts@0.5.1
data-contracts-expo-sqlite
Patch Changes
-
89a2d0a:
SqliteTransaction.transaction(work)now nests instead of rejecting. It runsworkin aSAVEPOINTon the same handle without waiting on the per-file queue, releases it whenworkresolves, and rolls back to it whenworkrejects, so only the nested statements and schema changes are undone and the same error reaches the caller. The enclosing transaction rolls back too unless the caller catches that error. While a nested transaction is open, statements andtransaction()on an enclosing context reject with aTypeError.Break:
SqliteTransaction.transactionchanges from(work) => Promise<never>to<TResult>(work: (transaction: SqliteTransaction) => Promise<TResult> | TResult) => Promise<TResult>. Code that relied on a nested call rejecting, or that typed its forwarding method as returningPromise<never>, must change. -
e26045b: Add
KeyValueStore.clearPrefix(prefix), which deletes every key that starts withprefix. Matching is exact and case-sensitive, no character is a wildcard, and an empty prefix clears the store.InMemoryKeyValueStore,DexieKeyValueStore(one IndexedDB key range), and the Expo SQLite key-value store (a UTF-8 byte prefix match inside the store's namespace) implement it, anddescribeKeyValueContractchecks it, including SQLLIKEwildcards, case, emoji, and U+FFFF. The Dexie real-browser suite now runs the key-value contract too.Breaking:
KeyValueStoregains a required method, so a product's ownKeyValueStoreimplementation must addclearPrefix. -
Release the coordinated baukit 0.5.1 train.
-
Updated dependencies [06cc669]
-
Updated dependencies [d423b98]
-
Updated dependencies [e26045b]
-
Updated dependencies
-
Updated dependencies [403805a]
- @baukit/data-contracts@0.5.1
data-contracts
Patch Changes
-
06cc669: Add two
encodeCsvoptions that keep a null cell apart from empty text.quoteAllCells: truequotes every text and numeric cell and leaves null cells unquoted.nullMarkerwrites a marker such as\Nunquoted for a null cell and quotes a text cell with the same content; an empty marker or one holding a double quote, comma, CR, or LF throws aRangeError.baukit_core::export::CsvOptionsgainswith_all_cells_quotedandwith_null_marker, and both pass five new shared vectors.Default output is unchanged. No breaking changes.
-
d423b98: Add
DurableDraft.move(scope), which hands an open draft to another scope, for example from a "new" draft to the record the server created. It writes a dirty or stored value under the new key, deletes the old key, keeps the value, revision, and submission state, and sends later saves to the new key. It resolvesmoved,blocked, orstaleand rejects withDraftPersistenceErroron a storage failure, leaving the draft on the old scope.Add the
isScopeActiveoption tocreateDurableDraft. The helper calls it before every write or delete; when it returns false,save,clear, andmoveresolvestalewithout touching storage. Reads are not checked.Breaking: the
DurableDraftinterface gains the requiredmovemethod, so a product's own implementation of that interface must add it. Code that only callscreateDurableDraftis unaffected. -
e26045b: Add
KeyValueStore.clearPrefix(prefix), which deletes every key that starts withprefix. Matching is exact and case-sensitive, no character is a wildcard, and an empty prefix clears the store.InMemoryKeyValueStore,DexieKeyValueStore(one IndexedDB key range), and the Expo SQLite key-value store (a UTF-8 byte prefix match inside the store's namespace) implement it, anddescribeKeyValueContractchecks it, including SQLLIKEwildcards, case, emoji, and U+FFFF. The Dexie real-browser suite now runs the key-value contract too.Breaking:
KeyValueStoregains a required method, so a product's ownKeyValueStoreimplementation must addclearPrefix. -
Release the coordinated baukit 0.5.1 train.
-
403805a: Add
WebStorageKeyValueStore, aKeyValueStoreoversessionStorageorlocalStorage. It keeps every key under a required non-empty namespace, stores JSON text, rejects instead of throwing on storage failures, and maps a full storage toStorageErrorstorage_quota_exceeded. It passesdescribeKeyValueContract. No breaking changes.
events
Patch Changes
- Release the coordinated baukit 0.5.1 train.
integrations-client
Patch Changes
- Release the coordinated baukit 0.5.1 train.
localization-core
Patch Changes
- Release the coordinated baukit 0.5.1 train.
notifications-core
Patch Changes
- Release the coordinated baukit 0.5.1 train.
- Updated dependencies
- @baukit/localization-core@0.5.1
notifications-expo
Patch Changes
- Release the coordinated baukit 0.5.1 train.
- Updated dependencies
- @baukit/notifications-core@0.5.1
preferences-core
Patch Changes
- Release the coordinated baukit 0.5.1 train.
pwa-web
Patch Changes
- Release the coordinated baukit 0.5.1 train.
sync-client
Patch Changes
-
Release the coordinated baukit 0.5.1 train.
-
a39abd7:
SyncSchedulerretries failed runs when givenretry: { maxRetries, delayMs, onRetryScheduled? }.delayMs(error, retryIndex)returns the wait in milliseconds ornullfor no retry;fullJitterBackoffMsfrom@baukit/api-runtime/backoffis the Baukit policy to pass in, so the root entry keeps no runtime dependencies. The retry index restarts after a success. Any trigger during the wait ends it and restarts the index:trigger(), the interval, foreground, or connectivity.stop()ends the wait without another run, and a wait that ends while backgrounded runs nothing. A bad delay or a throwingdelayMsreachesonErrorand ends the retries. The constructor throws aRangeErrorfor amaxRetriesthat is not a non-negative integer. New types:SyncSchedulerRetryOptionsandSyncSchedulerRetry. Withoutretry, behavior is unchanged.trigger()during a run no longer only joins it: when the run is waiting to retry, the wait ends. This applies only withretryset.
ui-tokens
Patch Changes
- Release the coordinated baukit 0.5.1 train.
Commits
- chore: prepare baukit v0.5.1 (
b3583bb) - docs(plan): record the P1 CSV and durable draft fixes (
fce34a0) - docs(evidence): record the 0.5.1 CSV and durable draft follow-ups (
a2b2138) - feat(data-contracts): move durable drafts between scopes and fence writes (
d423b98) - feat(data-contracts): add a Web Storage key-value store (
403805a) - feat(data-contracts): add KeyValueStore.clearPrefix (
e26045b) - feat(data-contracts): keep null CSV cells apart from empty text (
06cc669) - docs(plan): record the P2 runtime, reduced motion, and sync retry fixes (
16ba3cb) - docs(evidence): record 0.5.1 follow-ups for idempotency, reduced motion, and sync retry (
b6f291c) - feat(sync-client): retry failed scheduler runs with a product-chosen delay (
a39abd7) - feat(a11y-core): export reduced-motion hooks from the web entry (
5a29c63) - feat(api-runtime): accept interface bodies, product error classifiers, and overlapping sends (
fa3e0c3) - docs(plan): record the P4 claim purge and Keycloak helpers (
c6da0d4) - feat(templates): import Keycloak stack helpers from @baukit/auth-node (
a7a88c0) - feat(auth-node): add Keycloak test helpers on a keycloak-testing subpath (
306a46f) - feat(push): add purge to the delivery claim store port (
eee8757) - docs(plan): record the P3 nested savepoint fix (
2ed92ef) - docs(evidence): record nested savepoints for the SQLite connection (
db596ab) - fix(data-contracts-expo-sqlite): nest connection transactions as savepoints (
89a2d0a) - docs(plan): track the 0.5.1 fix wave (
c0b207a) - docs(plan): record Redemut adoption of 0.5.0 (
28db260) - docs(plan): record Hebkit adoption of 0.5.0 (
e8aee59) - docs(plan): record Leitbild adoption of 0.5.0 (
d7f0032) - docs(plan): track product adoption of 0.5.0 (
7a865d2)