Skip to content
Releases237 releases

Changelog

Every release across the Lunora packages, newest first. Lunora is alpha: the API still moves, and this is where it is written down.

Aug 24, 2026

Dependency updates only, across 20 packages.

@lunora/agentfix

1.0.0-alpha.61

diff

Fixed

Dependencies

  • @lunora/server: upgraded to 1.0.0-alpha.80
  • @lunora/workflow: upgraded to 1.0.0-alpha.31
@lunora/authfeature

1.0.0-alpha.88

diff

Added

  • auth: upgrade better-auth to 1.7.1 and gate MCP on its OAuth (#472) (7f17a35)
@lunora/bindingschore

1.0.0-alpha.35

diff

⚠ BREAKING CHANGES

  • storage: Storage.getPresignedUrl / buildPresignedUrl now throw a VALIDATION_ERROR (400) at mint time for an explicit out-of-range expiresInSeconds instead of silently clamping it to a different lifetime. Per input class, old behaviour -> new behaviour: - NaN / Infinity: minted a 900s URL -> throws - 0 or negative: minted a 1s URL -> throws - 0 < value < 1: minted a 1s URL -> throws (floors to 0) - value > 604800: minted a 604800s URL -> throws - absent: 900s (unchanged) - 1 .. 604800: honoured (unchanged, ceiling still inclusive) A handler forwarding a user- or config-supplied TTL that previously served a clamped URL now fails the mutation/action instead. Callers that relied on the clamp must clamp before calling, or catch VALIDATION_ERROR. Already-minted URLs are unaffected — verification is unchanged. Claude-Session: https://claude.ai/code/session_01P2mHUwAGcpzDrv4ZNd8MLG Co-authored-by: Claude Fable 5 <noreply@anthropic.com>

Fixed

  • storage: validate signed-url ttl and base path uniformly (#449) (cd830bb)
@lunora/bindingsfix

1.0.0-alpha.34

diff

Fixed

  • bindings: gate ctx.images, bound sql fetches (#448) (a6bf09e)

Dependencies

  • @lunora/platform: upgraded to 1.0.0-alpha.16
@lunora/codegenchore

1.0.0-alpha.121

diff

⚠ BREAKING CHANGES

  • flags: createFlags(options) is now createFlags(definition, env, options); callers must pass the defineFlags(...) result and the Worker env as identity keys. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P2mHUwAGcpzDrv4ZNd8MLG
  • fix(flags): bind each definition to its own openfeature domain Keying the client memo by (definition, env) was not enough on its own: every binding still went into the single global "lunora" OpenFeature domain, so a second definition's setProviderAndWait replaced the first's provider in the registry and the first's cached client silently began evaluating the second's values. The memo hid the collision rather than preventing it, and a module-scalar warning apologised for it. Each (definition, env) pair now owns its OpenFeature domain: the first — the only case a real app hits, one flags.ts and one env per isolate — keeps the stable "lunora" name so an external OpenFeature.getClient ("lunora") still reads the app's provider; additional pairs get "lunora-2", "lunora-3", … The domain is allocated once per pair and survives a failed bind, so a provider whose initialize throws retries on the same domain instead of stranding readers on a dead one. The lastBoundDefinition scalar and its console.warn are gone. createFlags also stopped taking config it was already handed: hooks, logger, and the provider factory are read from the definition, and the options bag shrank to the genuinely per-request extras — the config.flags override (undefined falls back to the definition) and the targeting-key thunk. Both codegen emission sites emit the smaller call.
  • flags: CreateFlagsOptions no longer accepts hooks or logger (read from the definition), and provider is now an optional override returning Provider | undefined instead of a required factory. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P2mHUwAGcpzDrv4ZNd8MLG
  • fix(flags): give a binding-less env a stable memo identity Generated workers build their env as this.env ?? {}, so when this.env is nullish every context build yields a FRESH object. Keyed on that, each request missed the client cache, allocated another lunora-N domain and ran setProviderAndWait again — and OpenFeature's registry holds a strong reference to every provider by domain name, so the WeakMap being weak would not release them: unbounded growth on the nullish path. An env carrying no bindings is indistinguishable to any provider factory, so they now share one EMPTY_ENV key and bind exactly once. Also record on DEFAULT_DOMAIN that which pair wins the unsuffixed "lunora" name is allocation-order dependent — "first definition wins" would be equally order-dependent, so the constraint is documented rather than papered over, with the note that code needing a specific client should be handed it instead of looking it up by domain. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P2mHUwAGcpzDrv4ZNd8MLG

Fixed

  • agent: unstrand HITL approvals (#438) (45c3b42)
  • bindings: gate ctx.images, bound sql fetches (#448) (a6bf09e)
  • flags: key the flags memo per definition (#463) (ad76ea9)

Dependencies

  • @lunora/advisor: upgraded to 1.0.0-alpha.86
  • @lunora/agent: upgraded to 1.0.0-alpha.61
  • @lunora/scheduler: upgraded to 1.0.0-alpha.36
  • @lunora/workflow: upgraded to 1.0.0-alpha.31
  • @lunora/do: upgraded to 1.0.0-alpha.95
  • @lunora/server: upgraded to 1.0.0-alpha.80
@lunora/containerfix

1.0.0-alpha.33

diff

Fixed

  • dispatch: idempotent retries, real deadlines (#455) (c92909a)

Build

  • migrate to @cloudflare/vitest-plugin v1 (#470) (05c4937)
@lunora/dbfix

1.0.0-alpha.60

diff

Fixed

  • db: scope shard checkpoints by identity (#434) (aef4e69)
@lunora/dofix

1.0.0-alpha.95

diff

Fixed

Dependencies

  • @lunora/bindings: upgraded to 1.0.0-alpha.35
@lunora/fingerprintperf

1.0.0-alpha.8

diff

Performance

@lunora/flagschore

1.0.0-alpha.33

diff

⚠ BREAKING CHANGES

  • flags: createFlags(options) is now createFlags(definition, env, options); callers must pass the defineFlags(...) result and the Worker env as identity keys. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P2mHUwAGcpzDrv4ZNd8MLG
  • fix(flags): bind each definition to its own openfeature domain Keying the client memo by (definition, env) was not enough on its own: every binding still went into the single global "lunora" OpenFeature domain, so a second definition's setProviderAndWait replaced the first's provider in the registry and the first's cached client silently began evaluating the second's values. The memo hid the collision rather than preventing it, and a module-scalar warning apologised for it. Each (definition, env) pair now owns its OpenFeature domain: the first — the only case a real app hits, one flags.ts and one env per isolate — keeps the stable "lunora" name so an external OpenFeature.getClient ("lunora") still reads the app's provider; additional pairs get "lunora-2", "lunora-3", … The domain is allocated once per pair and survives a failed bind, so a provider whose initialize throws retries on the same domain instead of stranding readers on a dead one. The lastBoundDefinition scalar and its console.warn are gone. createFlags also stopped taking config it was already handed: hooks, logger, and the provider factory are read from the definition, and the options bag shrank to the genuinely per-request extras — the config.flags override (undefined falls back to the definition) and the targeting-key thunk. Both codegen emission sites emit the smaller call.
  • flags: CreateFlagsOptions no longer accepts hooks or logger (read from the definition), and provider is now an optional override returning Provider | undefined instead of a required factory. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P2mHUwAGcpzDrv4ZNd8MLG
  • fix(flags): give a binding-less env a stable memo identity Generated workers build their env as this.env ?? {}, so when this.env is nullish every context build yields a FRESH object. Keyed on that, each request missed the client cache, allocated another lunora-N domain and ran setProviderAndWait again — and OpenFeature's registry holds a strong reference to every provider by domain name, so the WeakMap being weak would not release them: unbounded growth on the nullish path. An env carrying no bindings is indistinguishable to any provider factory, so they now share one EMPTY_ENV key and bind exactly once. Also record on DEFAULT_DOMAIN that which pair wins the unsuffixed "lunora" name is allocation-order dependent — "first definition wins" would be equally order-dependent, so the constraint is documented rather than papered over, with the note that code needing a specific client should be handed it instead of looking it up by domain. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P2mHUwAGcpzDrv4ZNd8MLG

Fixed

  • flags: key the flags memo per definition (#463) (ad76ea9)
@lunora/mcpfeature

1.0.0-alpha.82

diff

Added

  • auth: upgrade better-auth to 1.7.1 and gate MCP on its OAuth (#472) (7f17a35)
@lunora/platformfix

1.0.0-alpha.16

diff

Fixed

  • bindings: gate ctx.images, bound sql fetches (#448) (a6bf09e)
@lunora/platform-nodefix

1.0.0-alpha.22

diff

Fixed

  • bindings: gate ctx.images, bound sql fetches (#448) (a6bf09e)

Dependencies

  • @lunora/workflow: upgraded to 1.0.0-alpha.31
  • @lunora/do: upgraded to 1.0.0-alpha.95
  • @lunora/runtime: upgraded to 1.0.0-alpha.70
  • @lunora/storage: upgraded to 1.0.0-alpha.35
@lunora/queuefix

1.0.0-alpha.32

diff

Fixed

  • dispatch: idempotent retries, real deadlines (#455) (c92909a)
@lunora/react-nativefeature

1.0.0-alpha.37

diff

Added

  • auth: upgrade better-auth to 1.7.1 and gate MCP on its OAuth (#472) (7f17a35)
@lunora/schedulerchore

1.0.0-alpha.36

diff

⚠ BREAKING CHANGES

  • scheduler: QueueDispatch is now (job: QueueJob, messageId?: string) => Promise<void> — the consumer passes the queue message's native id as the second argument. @lunora/dispatch is added as a devDependency and inlined into dist by packem, matching @lunora/queue; it is not a published runtime dep. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P2mHUwAGcpzDrv4ZNd8MLG
  • fix(scheduler): make the queue job deadline configurable Routing the workpool through the dispatch runner picked up its 30s default, which is calibrated for an inline ctx.run inside a handler that is itself serving something. A workpool is the opposite case — it exists for jobs that outlive a request (an LLM call, an export, a payment round-trip), and truncating those at 30s turns a working job into a retry loop. Worse, an action's dedup read is deliberately ungated, so the retry can run concurrently with the still-in-flight first attempt. httpDispatcher now defaults to a 5 minute deadline and exposes timeoutMs on HttpDispatcherOptions to raise or lower it. The bound still cuts a hung origin off well short of the platform killing the whole queue() invocation, which is what this dispatcher did before with no deadline at all. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P2mHUwAGcpzDrv4ZNd8MLG
  • test(scheduler): assert the job deadline, not its mechanism The two dispatcher timeout tests stubbed AbortSignal.timeout and asserted the duration it was called with. That reached into how @lunora/dispatch implements its deadline rather than what this package depends on, so the tests hang for their full timeout the moment the runner arms its deadline any other way. Replaced with one test that gives the dispatcher a short real deadline and asserts the error it produces: status 503, message naming the configured duration. That holds regardless of how the runner arms the clock. The 5-minute default is a constant, and proving it fires would mean driving the runner's clock from here again. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P2mHUwAGcpzDrv4ZNd8MLG

Fixed

  • scheduler: route workpool through the runner (#454) (bd330d9)
@lunora/seedfix

1.0.0-alpha.79

diff

Fixed

  • seed: respect unique columns when seeding (#457) (37f5157)
@lunora/storagechore

1.0.0-alpha.35

diff

⚠ BREAKING CHANGES

  • storage: Storage.getPresignedUrl / buildPresignedUrl now throw a VALIDATION_ERROR (400) at mint time for an explicit out-of-range expiresInSeconds instead of silently clamping it to a different lifetime. Per input class, old behaviour -> new behaviour: - NaN / Infinity: minted a 900s URL -> throws - 0 or negative: minted a 1s URL -> throws - 0 < value < 1: minted a 1s URL -> throws (floors to 0) - value > 604800: minted a 604800s URL -> throws - absent: 900s (unchanged) - 1 .. 604800: honoured (unchanged, ceiling still inclusive) A handler forwarding a user- or config-supplied TTL that previously served a clamped URL now fails the mutation/action instead. Callers that relied on the clamp must clamp before calling, or catch VALIDATION_ERROR. Already-minted URLs are unaffected — verification is unchanged. Claude-Session: https://claude.ai/code/session_01P2mHUwAGcpzDrv4ZNd8MLG Co-authored-by: Claude Fable 5 <noreply@anthropic.com>

Fixed

  • storage: validate signed-url ttl and base path uniformly (#449) (cd830bb)
@lunora/sveltefeature

1.0.0-alpha.90

diff

Added

@lunora/vuefeature

1.0.0-alpha.91

diff

Added

@lunora/workflowfix

1.0.0-alpha.31

diff

Fixed

  • workflow: reject reserved names on step.name (#447) (f51690d)

Build

  • migrate to @cloudflare/vitest-plugin v1 (#470) (05c4937)

Dependencies

  • @lunora/server: upgraded to 1.0.0-alpha.80
lunorashchore

1.0.0-alpha.185

diff

Tests

Dependencies

  • @lunora/cli: upgraded to 1.0.0-alpha.183
  • @lunora/do: upgraded to 1.0.0-alpha.95
  • @lunora/flags: upgraded to 1.0.0-alpha.33
  • @lunora/runtime: upgraded to 1.0.0-alpha.70
  • @lunora/server: upgraded to 1.0.0-alpha.80
Aug 23, 2026

Dependency updates only, across 25 packages.

@lunora/advisorfeature

1.0.0-alpha.85

diff

Added

  • server: close all four Convex primitive gaps — _commitSeq, untracked runQuery, .memory() + onShardInit, onQueryChange reactors (#469) (75b0187)

Dependencies

  • @lunora/server: upgraded to 1.0.0-alpha.79
@lunora/authchore

1.0.0-alpha.87

diff

Build

  • migrate to @cloudflare/vitest-plugin v1 (#470) (05c4937)

Dependencies

  • @lunora/server: upgraded to 1.0.0-alpha.79
@lunora/clifix

1.0.0-alpha.180

diff

Fixed

Dependencies

  • @lunora/advisor: upgraded to 1.0.0-alpha.85
  • @lunora/bindings: upgraded to 1.0.0-alpha.33
  • @lunora/codegen: upgraded to 1.0.0-alpha.119
  • @lunora/config: upgraded to 1.0.0-alpha.150
  • @lunora/d1: upgraded to 1.0.0-alpha.84
  • @lunora/mcp: upgraded to 1.0.0-alpha.81
  • @lunora/runtime: upgraded to 1.0.0-alpha.69
  • @lunora/seed: upgraded to 1.0.0-alpha.78
  • @lunora/testing: upgraded to 1.0.0-alpha.116
@lunora/clientfeature

1.0.0-alpha.56

diff

Added

  • server: close all four Convex primitive gaps — _commitSeq, untracked runQuery, .memory() + onShardInit, onQueryChange reactors (#469) (75b0187)

Dependencies

  • @lunora/do: upgraded to 1.0.0-alpha.93
  • @lunora/runtime: upgraded to 1.0.0-alpha.69
  • @lunora/shard-engine: upgraded to 1.0.0-alpha.34
@lunora/clientfix

1.0.0-alpha.55

diff

Fixed

Build

  • migrate to @cloudflare/vitest-plugin v1 (#470) (05c4937)
Open source

Built in the open, on purpose.

Nothing about Lunora is a black box. Read it, fork it, or send the fix yourself.