Skip to content

Release digest for week of 2026-07-20 to 2026-07-27

  • Studio (Release v0.24.0): A shared Catalog service that is the single, cluster-wide authority for the product catalog and pricing. It is event-sourced (Chronicle) and exposed as a singleton Orleans grain, so Core and Admin read and write one authoritative set of SKUs and prices. Default pricing is seeded on first activation.
  • Studio (Release v0.24.0): The add-seats checkout flow: pick a plan and billing cycle, then review and complete. Individual-seat plans (single user) show a seat-quantity field; fixed packages are bought as a single unit.
  • Studio (Release v0.23.0): Studio services can co-host an Orleans silo joined to a single shared cluster, backed by a MongoDB membership table on the connection each service already uses. Infrastructure.AddStudioOrleansCluster sets this up; Core, Admin and Lobby opt in. This is the foundation for cross-service grains such as the upcoming Catalog (#891).
  • Chronicle (Release v16.7.0): ReactorScenario<T>.Services collection (with logging registered by default) and an Action<IServiceCollection> constructor for registering a reactor’s dependencies.
  • Chronicle (Release v16.7.0): Given.ForEventSourceId(id).ReadModel(...) to seed read-model handler-method parameters in a reactor scenario.
  • Chronicle (Release v16.7.0): ReactorScenario<T>.ShouldHaveProduced<T>() / ShouldNotHaveProduced<T>() and a Produced list to assert the events and commands a reactor returns as side effects, with no mocked event store.
  • Chronicle (Release v16.7.0): ReadModelScenario<T>.Services collection for registering reducer and projection dependencies without supplying a full IServiceProvider.
  • Chronicle (Release v16.7.0): CannotActivateReactorForScenario, thrown with the name of the dependency that could not be resolved when a reactor cannot be constructed.
  • release-action (Release v1.1.2): Documentation for the required contents: write permission, for choosing between the pull_request and push triggers (a push trigger keeps releases working for fork pull requests, whose token is read-only), and for manual workflow_dispatch runs.
  • Chronicle (Release v16.6.0): Configuration options for previously-hardcoded operational timeouts — connected-client intervals, the webhook HTTP resilience pipeline, the SQL live-query polling interval, the event-queue depletion wait, and the subscription-ready timeout — each defaulting to its current value (#1417)
  • Chronicle (Release v16.6.0): The ability to rename an identity’s display name, from kernel storage through gRPC to the client SDK, keyed by subject so it never affects the PII encryption key (#1684)
  • Chronicle (Release v16.6.0): React to read model changes with IReadModelReactor: methods named Added, Modified or Removed are invoked by convention with the changed read model (a single instance or a collection), an optional EventContext, and services, and may return events as side effects (#3359)
  • Chronicle (Release v16.6.0): [Materialized] opts a read model into materialized change tracking, deducing the change type by comparing successive materialized windows (#3359)
  • Chronicle (Release v16.6.0): OpenTelemetry tracing spans for client unit-of-work commit and rollback, tagged with the correlation id (#1396)
  • release-action (Release v1.1.0): major-labels, minor-labels and patch-labels inputs to configure which label names drive each version bump.
  • release-action (Release v1.1.0): tag-prefix input to configure the prefix used for the release tag.
  • release-action (Release v1.1.0): tag and previous-version outputs.
  • release-action (Release v1.1.0): A decision table written to the job summary explaining what the run decided.
  • Studio (Release v0.22.0): Organization seats & billing foundation completed on StudioCatalog: Admin SKU-pricing management + grant-seats, Core billing page with a Miro-style Add-seats popup (monthly/yearly, enterprise→contact sales), purchase, and downgrade-next-cycle. (#859)
  • Studio (Release v0.22.0): Sign-in tracking: every real logged-out→signed-in transition records a UserSignedIn event (approximate location + browser info), keyed to the user with the personal fields [PII]-encrypted. (#877)
  • AuthProxy (Release v2.10.0): Sign-in notification back-channel: on a genuine logged-out → signed-in transition, AuthProxy POSTs { subject, identityProvider, ipAddress, location, browser, operatingSystem, userAgent } to a configured application endpoint (Cratis/Studio#877).
  • AuthProxy (Release v2.10.0): New configuration key Cratis:AuthProxy:SignIn:NotifyUrl, alongside the existing Invite:ExchangeUrl and Link:ExchangeUrl. Leave it unset to disable notifications (Cratis/Studio#877).
  • AuthProxy (Release v2.10.0): Approximate location derived from the client IP (honoring X-Forwarded-For) and any geo headers a fronting CDN/proxy adds (CF-IPCountry, X-Geo-*, X-AppEngine-*) — no heavy geo-IP dependency; when no geo headers are present only the IP travels (Cratis/Studio#877).
  • AuthProxy (Release v2.10.0): Lightweight built-in User-Agent parsing into browser and operating system, with the raw header also forwarded (Cratis/Studio#877).
  • AuthProxy (Release v2.10.0): Documentation: Documentation/configuration/sign-in.md, wired into the configuration TOC (Cratis/Studio#877).
  • AuthProxy (Release v2.10.0): The notification fires only from the provider callback (OnTicketReceived), so it is scoped to real sign-ins — never on reused sessions or ordinary proxied requests. The credential-link flow short-circuits before this point, so a link is never reported as a sign-in.
  • AuthProxy (Release v2.10.0): Recording a sign-in is best-effort: any failure is logged and swallowed, and never breaks the sign-in itself.
  • AuthProxy (Release v2.9.0): /.cratis/logout now performs OIDC RP-initiated logout: for a session established through an OIDC provider it redirects the browser to the provider’s end_session_endpoint with id_token_hint and a post_logout_redirect_uri pointing at the new /.cratis/logout/callback, which then clears every AuthProxy cookie and redirects to the validated final target.
  • AuthProxy (Release v2.9.0): Cratis:AuthProxy:... OIDC applications should register https://<proxy-host>/.cratis/logout/callback as a permitted post-logout redirect URI.
  • AuthProxy (Release v2.8.0): GET /.cratis/link/{scheme} — a session-preserving credential-linking challenge. It authenticates the requested provider for an already signed-in user but, on the provider callback, captures the authenticated subject and posts it to the application instead of signing the new identity in, so the user’s primary session is preserved. The one-time link token and a same-site-only returnUrl travel through the flow. (Cratis/Studio#862)
  • AuthProxy (Release v2.8.0): Cratis:AuthProxy:Link:ExchangeUrl configuration — the application back-channel endpoint AuthProxy posts { subject, identityProvider } to (with the link token as the bearer credential), the link counterpart of Cratis:AuthProxy:Invite:ExchangeUrl. (Cratis/Studio#862)
  • AuthProxy (Release v2.7.0): GET /.cratis/logout — signs the user out of the authentication cookie and clears every AuthProxy session cookie (.cratis-identity, .cratis-tenant, .cratis-tenants, .cratis-invite, .cratis-registration, .cratis-providers), then redirects to the absolute URL in the redirect query parameter. The target is validated against an allow-list of origins (the proxy’s own public origin plus configured service/lobby frontends) so it cannot be used as an open redirect; a missing or disallowed target falls back to the application root. The endpoint is anonymous and runs before the authentication-challenge stages, so it works without a valid session.
  • Screenplay (Release v1.5.2): The invoicing sample now includes a CancelledInvoices slice whose projection has no explicit mappings at all — showcasing AutoMap’s default behavior copying every matching property from the event
  • Studio (Release v0.21.0): Prologue extraction now runs through a resumable interpreter service session: the interpreter container persists its state, exits itself after a configurable grace period, and Studio restarts it to resume — including when Studio itself is reopened
  • Studio (Release v0.21.0): The interpreter can ask questions when it is uncertain: questions surface live in the Prologue list with a pending-question badge, a new AwaitingAnswers status, and a stepper dialog answering one question at a time with multiple choice plus a free-text “Other” option
  • Studio (Release v0.21.0): Sticky toast notification with an “Answer now” action when the interpreter raises questions
  • Studio (Release v0.21.0): The generated Screenplay is stored per Prologue and downloadable as <SystemName>.play from the Prologue list
  • Studio (Release v0.21.0): Extraction results now carry the derived system name, descriptions, validation rules, and constraints from Prologue 1.1.0
  • Studio (Release v0.20.0): Adding a credential is now a proof of control: “Add credential” opens the chosen provider’s session-preserving link challenge in a popup, and the credential is associated only after the provider authenticates that identity for real. (#862)
  • Studio (Release v0.19.1): Regression specs guarding all three user-provisioning reactors (join-tenant, create-tenant, self-registration): the PII-bearing UserAdded must be appended into the target tenant namespace and never the ambient Default namespace.
  • Studio (Release v0.19.1): A read-model round-trip spec asserting the projection carries the email onto the User read model.
  • Studio (Release v0.19.1): An operations runbook for recovering already-blank organization-user emails (identify affected users, re-source the plaintext, re-append so it re-encrypts under a freshly persisted tenant-namespace key, and rebuild the read models). It notes that a plain observer replay cannot recover the crypto-shredded ciphertext, and that the founder’s data is unaffected.
  • Studio (Release v0.19.0): An encryption key is now provisioned per organization, with a tenant-scoped IOrganizationEncryptionKeys service to encrypt/decrypt per-organization secrets. A reactor provisions the key from the organization-setup events, and because it replays history, existing organizations get a key automatically. (#753)
  • Studio (Release v0.19.0): A StudioCatalog project shared by Core and Admin defining the seat/billing SKUs as stable predefined GUIDs with a dynamic pricing model — the foundation for organization seats and billing. (#859)
  • cli (Release v2.2.0): cratis llm group — configure the language model used by Cratis tools: use <anthropic|openai|local> (interactive prompts, secret API-key input), show (masked key), and clear
  • cli (Release v2.2.0): cratis prologue start — interactive wizard producing a cratis-prologue.json capture definition (SQL Server/PostgreSQL sources, API reverse-proxy capture, OpenTelemetry, JSON or Receiver API output)
  • cli (Release v2.2.0): cratis prologue interpret [PATH] — interprets captured data into a Screenplay .play file, streaming interpreter status and asking the interpreter’s questions one at a time with multiple choice plus a free-text “Other” option; output path optional, defaulting to the derived system name
  • Prologue (Release v1.1.0): Database schema captured as evidence: the Extractor reads the full schema (column types, sizes, nullability, primary keys, foreign keys, unique constraints) from SQL Server and PostgreSQL sources and emits it as a database-schema observation
  • Prologue (Release v1.1.0): Schema evidence drives interpretation: property types from column types, required/max-length validation rules, and unique constraints on the extracted model
  • Prologue (Release v1.1.0): Cratis.Prologue.Interpretation package — a resumable interpreter session engine with checkpoint questions: the language model can ask the user multiple-choice questions (always with a free-text option) when uncertain, one at a time, and sessions park, persist, and resume statelessly at any time
  • Prologue (Release v1.1.0): Structured LLM refinement producing intentful names, a derived system name, and descriptions for every module, feature, slice, and command
  • Prologue (Release v1.1.0): Cratis.Prologue.Screenplay package — generates a Screenplay .play document from an extraction result using the Screenplay syntax tree and printer
  • Prologue (Release v1.1.0): Interpreter service mode: an Orleans-backed session per Prologue behind an HTTP API, with MongoDB-persisted state, a configurable grace period for unanswered questions, and clean self-exit so orchestrators can restart-to-resume
  • Prologue (Release v1.1.0): Interpreter batch mode now also writes the generated .play file next to the extraction result
  • Prologue (Release v1.1.0): Extraction contract carries the system name, descriptions, validation rules, and constraints
  • Screenplay (Release v1.5.0): Editor syntax highlighting for the specification, given, then and error keywords.
  • Screenplay (Release v1.5.0): Editor syntax highlighting for the remaining projection keywords (sequence, all, nested, automap, no, exclude, clear, via, literal) and capture keywords (split, nested, from, to, and, or, tag).
  • Screenplay (Release v1.5.0): Editor syntax highlighting for the $eventSourceId and $causedBy context variables.
  • Screenplay (Release v1.4.0): description on commands — explain the logic and intent of a command directly in the language (#20)
  • Screenplay (Release v1.4.0): Multi-line descriptions on modules, features, slices, personas, and commands using the ``` fence convention, consistent with code blocks; the single-line description "..." form stays supported (#20)
  • Screenplay (Release v1.4.0): Editor support for fenced description blocks (Monaco tokenizer states and VS Code TextMate scoping)
  • Screenplay (Release v1.3.0): description "..." on modules, features, and slices — a human explanation carried in the syntax tree and round-tripped by the printer
  • Screenplay (Release v1.3.0): domain declaration for specifying which domain a file belongs to (#9)
  • Screenplay (Release v1.3.0): persona declarations with a description and associated policies (#18)
  • Screenplay (Release v1.3.0): authentication block for declaring identity providers with free-form settings that can reference secrets (#17)
  • Screenplay (Release v1.3.0): $secrets.<name> expressions plus encrypted .secrets companion files (AES-256-GCM, enc:v1: format) with discovery, parsing, and a pluggable cipher (#16)
  • Screenplay (Release v1.3.0): Internationalization: <base>.<locale>.strings companion files with discovery and parsing, $strings.<key> expressions, and $strings references for validation messages and screen labels/titles (#7)
  • Screenplay (Release v1.3.0): validate and validate csharp blocks on concepts, using the same rule grammar as commands with the concept value as the implied subject (#8)
  • Screenplay (Release v1.3.0): seed blocks for declaring events to seed per event source (#10)
  • Screenplay (Release v1.3.0): given readmodel and then readmodel in specifications for read-model state preconditions and expectations (#11)
  • Screenplay (Release v1.3.0): concurrency blocks on commands expressing the concurrency scope dimensions (event source, source type, stream type, stream id, event types) (#13)
  • Screenplay (Release v1.3.0): tag support on events, produces blocks, and capture append blocks — static and context-resolved dynamic tags (#14)
  • Screenplay (Release v1.3.0): Editor support (Monaco tokenizer, hover docs, VS Code TextMate grammar) for all new keywords
  • Chronicle (Release v16.5.0): Configuration options for operational timeouts that were previously hardcoded — connected-client revise/reservation-TTL/observe/keep-alive/stale-threshold intervals, the webhook HTTP resilience pipeline (retry delay, circuit-breaker sampling/break durations, request timeout, test timeout), the SQL live-query polling interval, the event-queue depletion wait, and the subscription-ready timeout — each defaulting to its current value (#1417)
  • Chronicle.Elixir (Release v2.1.2): Added Chronicle.Connections.Connection.reconnect/1 for forcing a fresh channel when a caller has independent evidence the current one is unusable
  • Chronicle.TypeScript (Release v2.1.0): chronicle://host1:port,host2:port,... connection strings — the client now connects to any one of several configured hosts instead of only a single server.
  • Chronicle.TypeScript (Release v2.1.0): chronicle+srv:// connection strings, resolving the target host(s) via a DNS SRV lookup, re-resolved on every connect/reconnect so membership changes are picked up automatically. The DNS server to query can be overridden with the srvNameServer option.
  • Chronicle.TypeScript (Release v2.1.0): A loadBalancer connection string option selecting how one address is picked among several candidates: least-connections (the default — probes each candidate and picks the one with the fewest active connections), round-robin, or random.
  • Chronicle.TypeScript (Release v2.1.0): A skipTlsValidation connection string option to skip TLS certificate validation independently of disabling TLS entirely. Defaults to true, matching the client’s previous behavior — set skipTlsValidation=false to require full certificate chain validation.
  • Chronicle.TypeScript (Release v2.1.0): Client connections now report the process id, process path, machine name, and client type to the Chronicle kernel, improving connection diagnostics.
  • Chronicle.Kotlin (Release v2.1.0): chronicle://host1:port,host2:port,... connection strings — the client now connects to any one of several configured hosts instead of only a single server.
  • Chronicle.Kotlin (Release v2.1.0): chronicle+srv:// connection strings, resolving the target host(s) via a DNS SRV lookup, re-resolved on every connect/reconnect so membership changes are picked up automatically. The DNS server to query can be overridden with the srvNameServer option.
  • Chronicle.Kotlin (Release v2.1.0): A loadBalancer connection string option selecting how one address is picked among several candidates: least-connections (the default — probes each candidate and picks the one with the fewest active connections), round-robin, or random.
  • Chronicle.Kotlin (Release v2.1.0): A skipTlsValidation connection string option to skip TLS certificate validation independently of disabling TLS entirely. Defaults to true, matching the client’s previous behavior — set skipTlsValidation=false to require full certificate chain validation.
  • Chronicle.Kotlin (Release v2.1.0): Client connections now report the process id, process path, machine name, and client type to the Chronicle kernel, improving connection diagnostics.
  • Chronicle.Elixir (Release v2.1.0): chronicle://host1:port,host2:port,... connection strings — the client now connects to any one of several configured hosts instead of only a single server. IPv6 hosts are supported via bracket notation.
  • Chronicle.Elixir (Release v2.1.0): chronicle+srv:// connection strings, resolving the target host(s) via a DNS SRV lookup, re-resolved on every connect/reconnect so membership changes are picked up automatically. The DNS server to query can be overridden with the srvNameServer option.
  • Chronicle.Elixir (Release v2.1.0): A loadBalancer connection string option selecting how one address is picked among several candidates: least-connections (the default — probes each candidate and picks the one with the fewest active connections), round-robin, or random.
  • Chronicle.Elixir (Release v2.1.0): A skipTlsValidation connection string option to skip TLS certificate validation independently of disabling TLS entirely. Defaults to true, matching the client’s previous behavior — set skipTlsValidation=false to require full certificate chain validation.
  • Chronicle.Elixir (Release v2.1.0): Client connections now report the process id, machine name, and client type to the Chronicle kernel, improving connection diagnostics.
  • Studio (Release v0.18.0): An identity-provider login can be associated with only one user per organization. Signing in with a login already tied to another account is rejected, and the Lobby shows an error instead of silently failing (#826)
  • Studio (Release v0.17.0): When adding a UI to a slice, the + button now offers a choice between starting from scratch or seeding the prototype from an existing UI template (#723)
  • Studio (Release v0.16.0): Export an event model, a module or a feature as a Mermaid eventmodeling diagram, downloaded directly from the browser (#741)
  • Studio (Release v0.15.0): Live collaboration on the brainstorming board: remote changes appear live and collaborator cursors are shown there as well
  • Arc (Release v20.61.0): ARC0014 analyzer diagnostic: a generic static method on a [ReadModel] whose return type matches a query shape is reported at compile time, since query discovery would register it as an endpoint that can never be invoked. It inspects internal methods as well as public ones, matching what discovery actually registers.
  • Arc (Release v20.61.0): QueryMethodCannotBeGeneric, thrown by ModelBoundQueryPerformer’s constructor, so a generic query method fails at wire-up naming the offending method rather than per request with a bare reflection message.
  • Studio (Release v0.13.0): Real-time collaboration on the event model board: when several people view the same event model, each collaborator’s cursor moves live across the board with a small avatar, and the collaborators panel shows who is on the project (#797)
  • Studio (Release v0.13.0): Backup type filter (Database / Secrets / Both) on the admin backups view (#801)
  • Arc (Release v20.60.2): reconcileQueryData in @cratis/arc/queries, which reconciles a freshly received payload against the previous one and preserves references for everything that did not change. Items are matched by their conventional id, falling back to position.
  • Arc (Release v20.60.1): ConceptValidator<T> rules are now generated into the client, so a concept declared once is validated in the browser everywhere it appears on a command property or query parameter
  • Studio (Release v0.12.2): Liquid Glass capture diagnostics can now be enabled on a production build with ?lgdebug in the URL (or a cratis.studio.liquid-glass.debug localStorage flag), exposing window.__lgCapture for on-site debugging of capture behavior.
  • Studio (Release v0.12.0): An Export to Screenplay action on the event-model toolbar that generates the current event model as a Cratis Screenplay (.play) file and downloads it. (#780)
  • Studio (Release v0.11.0): Reusable Screenplay generator in Core: a Studio.Screenplay namespace with an IScreenplayGenerator that turns an assembled event model into a Cratis Screenplay (.play) document — modules, features, slices, events, commands with validation rules, uniqueness constraints, specifications, and read-model queries with an automap projection. (#780)
  • Studio (Release v0.11.0): ExportToScreenplay query that assembles an event model by id and returns the generated .play file, ready to download. (#780)
  • Studio (Release v0.11.0): Depends on Cratis.Screenplay 1.2.1 (Cratis/Screenplay#15), which fixes a type-discovery build break in consumers. That PR must merge and publish before this one’s CI can restore the package.
  • Studio (Release v0.11.0): The frontend “Export to Screenplay” menu item + browser download is a thin follow-up on the working /api/.../export/export-to-screenplay endpoint (the event-model-id plumbing into the top-bar menu is left for that follow-up).
  • Studio (Release v0.11.0): Play sessions and specification runs still feed the Stage container the intermediate JSON; switching them to feed .play follows once the Stage .play-consuming image ships.
  • cli (Release v2.1.0): cratis run [PATH] — boots a local Stage sandbox from the Screenplay (.play) files in a folder. It mounts the folder into the cratis/stage container, publishes the Stage API on http://localhost:9090 (override with --port), and streams the session until you stop it. Refuses to start when no .play files are present, and reports a clear error when Docker is unavailable. Choose the image tag with --tag.
  • Studio (Release v0.10.9): A runaway-recapture detector: when the glass pipeline recaptures continuously with no idle gap, it logs a single console warning naming the most frequent element/layer driving the loop (e.g. 18x base<-DIV.some-card). Normal pages fire a handful of captures then go quiet, so it never false-positives.
  • Screenplay (Release v1.2.0): IScreenplayPrinter / ScreenplayPrinter — renders a Screenplay syntax tree back to .play source text, the reverse of the compiler. Overloads print a whole ApplicationSyntax document as well as standalone ProjectionSyntax, SpecificationSyntax and CaptureSyntax. A syntax tree can now be built or modified in code and printed to valid Screenplay, which is the basis for generating .play files from a model.
  • Screenplay (Release v1.2.0): Documentation: a “Printing and generating” reference page covering the printer, the round-trip guarantee with the compiler, and generating Screenplay from a tree built directly from a model.
  • Studio (Release v0.24.0): Core now prices seat purchases against the administrator-configured catalog price (previously it used a local default and never saw Admin’s prices). Admin’s pricing management writes to the same shared catalog.
  • Studio (Release v0.24.0): All Studio services now co-host an Orleans silo and join one shared cluster (activates the clustering added in #893), enabling cross-service grains.
  • Studio (Release v0.24.0): StudioCatalog project renamed to Catalog; the shared model + grain contract split into Catalog/Catalog.Contracts, with the event-sourced pricing slice moved into the new Catalog service.
  • Studio (Release v0.24.0): This turns the Orleans cluster ON in production (Orleans:Enabled=true for core/admin/lobby/catalog) — the first time silos form a cluster across pods. I’ll verify cluster formation + the billing flow end-to-end after deploy; rollback is a redeploy of 0.22.2 (cluster gated off).
  • Studio (Release v0.24.0): Admin’s previously event-sourced prices lived in the StudioAdmin store; the catalog seeds defaults in its own store. Any prices configured before this ship would reset to defaults (the feature is new, so this should be empty in prod).
  • Arc (Release v20.62.4): Updated Cratis Chronicle to 16.7.0
  • Chronicle (Release v16.7.0): A ReactorScenario<T> created without an explicit IServiceProvider now builds one from Services (standard dependency injection with logging registered) instead of using DefaultServiceProvider. A reactor that relied on DefaultServiceProvider constructing an unregistered concrete dependency must now register it.
  • Arc (Release v20.62.3): Updated Cratis Chronicle to 16.6.1
  • Arc (Release v20.62.3): Updated System.Reactive to 7.0.0
  • Arc (Release v20.62.3): Updated Entity Framework Core and other Microsoft/.NET dependencies to the latest 10.0.10 servicing releases
  • Chronicle (Release v16.6.0): Read model change notifications now carry the change type and the causing event’s sequence number, occurred time and correlation id (#3359)
  • Chronicle (Release v16.6.0): Faster reactor, reducer and event-type dispatch on the .NET client (#1309)
  • release-action (Release v1.1.1): Release tags (vX.Y.Z and the floating vX / vX.Y) now point at a lean commit containing only action.yml, dist, LICENSE and README.md, so a uses: checkout is about 2.7 MB instead of 6.6 MB.
  • release-action (Release v1.1.0): The action now runs on Node 24.
  • release-action (Release v1.1.0): The action now honors GITHUB_API_URL, so it runs on GitHub Enterprise Server.
  • release-action (Release v1.1.0): A release created without notes of its own now uses GitHub’s generated release notes instead of an empty body.
  • release-action (Release v1.1.0): An explicit version without release-notes now creates a release instead of being skipped.
  • Studio (Release v0.22.0): Cold event-model load is dramatically faster: JS minified + code-split (app entry 6.7 MB → ~368 kB), the editor lazy-loaded, the data subscription no longer waits on prototype bundles, and prototype bundles are content-addressed + immutable-cached.
  • Studio (Release v0.22.0): AuthProxy bumped to 2.10.0 (full-chain logout + sign-in notifier) and wired: logout redirect allow-list, credential-link, and sign-in NotifyUrl.
  • AuthProxy (Release v2.9.0): The final redirect target is now validated against the post-logout allow-list on both legs of the round-trip (initiation and callback), and is carried across the identity-provider round-trip in a short-lived HTTP-only cookie rather than in the URL.
  • AuthProxy (Release v2.9.0): OAuth 2.0 providers (such as GitHub) have no standard OIDC end-session endpoint and cannot be force-logged-out via a redirect; those sessions — and any request with no active OIDC session — fall back to the previous local-only logout (clear cookies + redirect). See Documentation/configuration/logout.md.
  • AuthProxy (Release v2.7.0): .cratis-tenants now persists for the post-login tenant switcher. It is written as a session cookie and is no longer deleted when a tenant is selected, so a user with more than one tenant keeps the list available for an in-app switch control for the rest of the browser session. Single-tenant users still have the cookie removed on auto-selection (no switcher), and every selection continues to re-validate membership against the tenants endpoint.
  • Studio (Release v0.21.0): Prologue packages updated to 1.1.0
  • Studio (Release v0.20.0): AssociateIdentityProvider no longer trusts a caller-supplied subject — it consumes a one-time link token and associates the identity the AuthProxy verified. The own-account rule and the append-time uniqueness constraint are unchanged. (#862)
  • Studio (Release v0.19.0): Liquid Glass is now the default appearance for everyone. The first-visit device-performance probe that quietly downgraded capable machines to the acrylic fallback has been removed entirely, and machines it previously downgraded are reset to Liquid Glass (the appearance storage key is bumped). Acrylic remains a choice in Appearance settings and persists once selected.
  • Chronicle.TypeScript (Release v2.1.1): When no OAuth2 token can be obtained, RPCs now proceed without authorization and fail with the server’s rejection instead of a client-side token fetch error
  • Screenplay (Release v1.5.0): The full invoicing sample now exercises every language construct at least once: the @sensitive concept attribute, the complete set of concept and command validation rules, claim-based and grouped authorization policies, a nested feature, file-based handlers, the full projection sub-language (sequence, every/all, composite keys, nested blocks, remove via join, set/count/add/subtract mappings and the $eventSourceId/$causedBy/literal/template expressions), the remaining capture triggers (split, value transition, logical and/or, template), screen titles/summaries/file references, html and typescript code blocks, multiple reactor triggers and event-based specifications.
  • Studio (Release v0.18.3): Default self-hosted LLM model is now gemma3:1b (previously gemma4:e2b-it-q4_K_M), set consistently across the LLM image pre-pull, the warmup script, and Core’s requested model.
  • Chronicle.TypeScript (Release v2.1.0): Reconnect backoff is now jittered, so a fleet of clients that lost the same kernel does not reconnect in lockstep.
  • Chronicle.TypeScript (Release v2.1.0): Updated to Chronicle contracts 16.4.0.
  • Chronicle.Kotlin (Release v2.1.0): Reconnect backoff is jittered, so a fleet of clients that lost the same kernel does not reconnect in lockstep.
  • Chronicle.Kotlin (Release v2.1.0): The client connection ID rotates on every reconnect, so observers re-register under an ID the kernel recognizes.
  • Chronicle.Elixir (Release v2.1.0): The gRPC connection target now resolves any configured hostname correctly; previously only localhost was guaranteed to resolve.
  • Chronicle.Elixir (Release v2.1.0): Updated to Chronicle contracts 16.4.0.
  • Studio (Release v0.17.2): Application names are unique per organization (namespace-wide); two projects can no longer both use the same application name
  • Studio (Release v0.15.0): Remote collaborator cursors move smoothly along an interpolated curve and track correctly through panning
  • Studio (Release v0.15.0): The collaborator cursor’s avatar is aligned diagonally in the arrow’s tail
  • Arc (Release v20.61.0): Cratis.Arc.ProxyGenerator.Build takes a framework reference on Microsoft.AspNetCore.App. Reading validation rules loads the target project’s own assembly for real, and targets are ASP.NET applications, so that load fails without the shared framework.
  • Studio (Release v0.14.0): Collaborator cursors and the collaborator list now update in near-real-time over a resilient two-way WebSocket connection
  • Studio (Release v0.14.0): Remote cursors now point at the same board content on every screen, independent of each user’s pan and zoom
  • Studio (Release v0.14.0): Collaborator cursors now show just the collaborator’s avatar circle in the cursor arrow’s tail
  • Studio (Release v0.13.0): The event model board now updates live: its query is observable, so changes stream in as deltas and the board reconciles structural changes without an explicit reload (#797)
  • Studio (Release v0.13.0): Only one UI prototype is allowed per role on a slice — the add button is hidden once a role has a prototype, and the backend rejects a second one so it cannot be created another way (#808)
  • Arc (Release v20.60.2): The Connected message on the observable query hub now carries the server’s keep-alive interval so clients can align their idle detection with it.
  • Arc (Release v20.60.2): ObservableQueryHubMessage.CreateConnected now takes the keep-alive interval alongside the connection identifier. This type is the hub’s wire protocol and is not constructed by application code, so no application-level change is needed.
  • Arc (Release v20.60.1): Query arguments are validated with the same traversal as command properties: a validator nested inside an argument, inside a collection, or on a concept now runs. Previously it only ran when the argument’s own type had a validator
  • Arc (Release v20.60.1): Queries that carry a validator which previously never ran will now reject invalid arguments. Requests that succeeded before may return 400
  • Arc (Release v20.60.1): Observable queries now run client-side validation, on both perform() and subscribe(). The rules were always generated but the proxy discarded them, so an observable query carrying a validator begins rejecting on upgrade — including a subscribe() started before its arguments are available, which a notEmpty rule will now reject. Gate such subscriptions with ObservableQueryWhen. A rejected subscription delivers an invalid result to the subscriber instead of an empty one, so “these arguments are wrong” is distinguishable from “no data yet”
  • Arc (Release v20.60.1): Validation failures now report member names the way the client does — camelCased, and attributed to the field rather than to a concept’s inner value. A failure previously reported as Email or email.Value is now email. This applies to commands as well as queries, and is what lets a form match a server rejection to the field that caused it
  • Arc (Release v20.60.1): Query validators resolve from the request scope, so they can depend on scoped services
  • Studio (Release v0.12.8): The off-screen capture margin grows from 1000px to 1400px (sized to the GPU’s texture limit), so continuous pans run out of captured background noticeably later before refilling.
  • Studio (Release v0.12.7): Liquid Glass now keeps a larger off-screen capture margin (1000px) and only re-anchors it once a pan has consumed 75% of that margin. Deliberate scrolls of up to ~750px no longer trigger a base recapture, so the browser stops re-referencing fonts and stylesheets on every scroll and continuous panning stays smooth — most noticeably on Safari.
  • Studio (Release v0.12.3): Liquid Glass capture now uses html2canvas-pro (native modern-color support and an abortable render).
  • Studio (Release v0.12.2): Liquid Glass now coalesces more of a continuous background change into each capture, reducing full-page rasterizations (and their resource re-references) during active editing.
  • Studio (Release v0.12.0): Play sessions and specification runs now hand the Stage container a generated .play file instead of the intermediate JSON document, matching the Stage container’s Screenplay input.
  • Studio (Release v0.12.0): The runtime .play feed for Play/spec-runs relies on the cratis/stage and cratis/stage-specrunner images being rebuilt from the merged Screenplay-input Stage change.
  • Studio (Release v0.10.5): The appearance settings preview is now an interactive canvas of module cards that you can pan and zoom, with a left tool palette, the zoom control in the lower-right, and a draggable glass panel — so you can see the glass bend real, movable content.
  • Studio (Release v0.24.6): Opening the event model editor pinned a CPU core at ~100% and made the toolbar mode transitions stutter. useMermaidExport returned a fresh async function on every render; that function is a useMemo dependency for the editor’s export menu items, which ApplicationContainer pushes up to the project chrome from an effect. A new function each render churned the memo, so the effect re-set parent state on every render — re-rendering the whole editor tree in an unbounded loop (~280 commits/second, “Maximum update depth exceeded”). Memoizing the callback with useCallback stops the loop (verified: idle re-renders drop from ~280/second to zero).
  • Studio (Release v0.24.5): Cleared the remaining SA1117 build warnings (these live in #if DEBUG spec fixtures, so a Release build didn’t surface them). The Mermaid, Screenplay and billing-purchasing spec fixtures built each domain object with argument lists that mixed several parameters on one line with others wrapped one per line; each argument now goes on its own line.
  • Studio (Release v0.24.4): Cleared all backend build warnings (SA1515 blank-line-before-comment, ASP0018 unused route parameter, RCS1118 non-const local, RCS1261 synchronous stream disposal, SA1204 static-before-instance ordering) so the solution builds warning-free again.
  • Studio (Release v0.24.4): yarn dev failed its dependency scan with Settings/Users/IdentityProviders/Credentials could not be resolved — the account-profile credentials page is imported through the Settings/* path that tsconfig resolves but the Core Vite config never aliased. Added the missing Settings alias so Vite resolves it the same way TypeScript does.
  • Studio (Release v0.24.3): In Acrylic appearance the Event Modeling / application toolbar lost the dividers between groups that Liquid Glass appearance shows. Liquid Glass draws one metaball pill per toolbar group, so the gaps between them read as dividers, but the acrylic fallback ignored those measured shapes and painted a single flat panel over the whole toolbar. The acrylic surface now renders one pill per group shape (with the plain single-rounded-rect look kept as the no-shapes fallback), so groups stay divided in Acrylic mode too.
  • Studio (Release v0.24.2): The billing plan cards (add-seats dialog) and the Admin pricing table showed nothing. Their grain-backed snapshot queries returned IEnumerable<SkuOffer> from the Plan / CatalogPricing read models, but Arc only registers a static method as a query when its return type is the read model (or a collection of it) — so a query returning a different type was silently never mapped, and the GET fell through to the SPA fallback with no data. The Plan and CatalogPricing read models now carry the offer/pricing fields themselves and their queries return a collection of their own type, so the catalog is served as JSON and renders.
  • Studio (Release v0.24.1): The Catalog service now serves a /health endpoint so its Kubernetes liveness/readiness probe passes. As a backend-only service it has no SPA fallback (unlike Core/Admin/Lobby), so the probe was returning 404 and the pod crash-looped.
  • Chronicle (Release v16.7.0): ReactorScenario<T> now resolves reactor handler-method parameters — injected services and materialized read models — instead of failing to resolve them.
  • release-action (Release v1.1.2): A workflow_dispatch run left at the default 0.0.0 version no longer creates a bogus v0.0.0 release or publishes 0.0.0 artifacts. An empty or 0.0.0 version now works the version out from the merged pull request as intended.
  • Chronicle (Release v16.6.1): The .NET client NuGet packages now build for the net8.0 and net9.0 targets again, so the packages publish with the release
  • Chronicle (Release v16.6.0): Releasing a coarse [PII] collection for an erased subject no longer crashes — it reads as an empty collection instead of throwing and potentially quarantining an observer after right-to-erasure
  • Chronicle (Release v16.6.0): Projection-backed observable read-model queries keep emitting after a connection drop, instead of silently freezing on stale data after the first reconnect
  • Chronicle (Release v16.6.0): Appending a batch of events no longer risks an infinite retry loop that permanently wedges an event sequence, or a sequence-number gap and phantom tail when the storage append throws
  • Chronicle (Release v16.6.0): The SQL event-store backend no longer risks an infinite retry loop when appending at a sequence number that is already taken
  • Chronicle (Release v16.6.0): Username and email lookups on the SQL backend are now case-insensitive, matching the in-memory and MongoDB backends
  • Chronicle (Release v16.6.0): Waiting for observers to catch up no longer reports success against an observer that has never handled any events; event and read-model read cursors are now disposed when an enumeration error occurs
  • Chronicle (Release v16.6.0): Event seeding no longer permanently loses events when applying them to an event store’s namespaces fails partway through, and no longer silently skips events when an append fails
  • Chronicle (Release v16.6.0): Adding a new generation to an existing event type now works on the MongoDB backend, and resolving an event type by a specific generation from the SQL database on a cold cache returns that generation’s schema
  • Chronicle (Release v16.6.0): Job monitoring surfaces backend failures instead of returning an empty result
  • Chronicle (Release v16.6.0): A unit of work whose commit fails is no longer leaked; optimistic concurrency is no longer silently disabled when a later same-source event carries no scope; and completing one unit no longer clears the current-unit reference of a different unit
  • Chronicle (Release v16.6.0): Paging a read-model query with a
  • release-action (Release v1.1.0): A pull request closed without being merged no longer produces a release, even when it has a release label (#2, #4).
  • release-action (Release v1.1.0): Duplicate releases from the version being recalculated in the post step are no longer created (#103).
  • release-action (Release v1.1.0): A merged pull request from a branch named after a version now produces a correct version.
  • release-action (Release v1.1.0): The isolated-for-pull-request output was inverted and now reports correctly.
  • release-action (Release v1.1.0): Releases now point at the actual merge commit instead of the ephemeral pull-request merge commit.
  • Arc (Release v20.62.2): Header-based tenant resolution now applies for the whole request instead of only inside endpoint delegates, so tenant-scoped work that runs earlier no longer falls back to the default namespace and database; header lookup is now case-insensitive so a configured header still matches when HTTP/2 delivers it lowercased (#2351)
  • Arc (Release v20.62.2): An IAsyncEnumerable-backed observable query is now stopped on unsubscribe, instead of leaking and duplicating results on re-subscribe
  • Arc (Release v20.62.2): Observable queries served through the MongoDB watcher are now isolated per tenant database instead of all sharing the first tenant’s
  • Arc (Release v20.62.2): The MongoDB watcher now resumes from the last change after a transient reconnect instead of silently dropping changes that happened during the disconnect
  • Arc (Release v20.62.2): A float-backed concept can now be persisted to MongoDB — it previously threw on every write
  • Arc (Release v20.62.2): A DateTime-backed concept now round-trips correctly instead of being read back as a wildly wrong date
  • Arc (Release v20.62.2): A command that returns an event collection containing a null element no longer fails with a server error during response detection
  • Arc (Release v20.62.2): Injecting an aggregate root into a command’s Handle now resolves the aggregate root itself rather than a Task
  • Arc (Release v20.62.2): Executing a command with a base-type or interface result type now returns the result instead of throwing when the response is assignable to it
  • Arc (Release v20.62.2): An exception thrown by an aggregate root event handler now surfaces as itself, instead of being wrapped in a reflection exception that hid its type and stack
  • Arc (Release v20.62.2): An aggregate root commit result now reports only that aggregate’s own events, with sequence numbers that correspond to them
  • Arc (Release v20.62.2): A command, query, or read model that references an enum not backed by int (for example enum X : byte or [Flags] enum X : long) no longer breaks TypeScript proxy generation
  • Arc (Release v20.62.2): A Uri property now generates a TypeScript string instead of a Date
  • Arc (Release v20.62.2): A dictionary whose key or value is a package type such as Guid or TimeSpan now generates compilable TypeScript, with the type’s import included
  • Arc (Release v20.62.2): Command and query validation no longer relies on Expression.Compile, Activator.CreateInstance over a runtime-constructed generic, or private-member reflection, so it works under NativeAOT and trimming (#2204)
  • Studio (Release v0.22.1): The What’s New dialog’s version dropdown now navigates to the release you pick — previously selecting a version (or opening on “show all releases”) left the picker unable to reach the releases it listed.
  • Studio (Release v0.22.1): Signing out now clears the leftover OAuth/OIDC sign-in handshake cookies that used to accumulate in the browser, via AuthProxy 2.10.1.
  • AuthProxy (Release v2.10.1): Logout now clears the transient OAuth/OIDC correlation and nonce cookies (.AspNetCore.Correlation.*, .AspNetCore.OpenIdConnect.Nonce.*) the sign-in handshake leaves behind on abandoned attempts, so signing out no longer leaves them accumulating in the browser. These cookies are now kept at the root path so the browser sends them on the logout request.
  • Studio (Release v0.22.0): Production stability: bump Arc to 20.62.1, which fixes a process crash when an observable-query SSE client disconnects mid-emission (the periodic core exit 139).
  • Studio (Release v0.22.0): Specification message now scales with canvas zoom. (#863)
  • Studio (Release v0.22.0): Collapsing a specification no longer collapses the whole slice; a collapsed feature keeps its specs visible. (#873)
  • Studio (Release v0.22.0): The “what’s new” dialog gets a centered version dropdown with flanking arrows and the show-all toggle beneath. (#872)
  • Studio (Release v0.22.0): Adds Deployment/scripts/restore-prod-locally.sh (restore the latest prod dump locally) + a performance analysis doc.
  • Studio (Release v0.22.0): Follow-ups (documented in the source PRs): #859 Admin-pricing→Core-namespace propagation and scheduled-downgrade application; the IdP must register /.cratis/logout/callback as a post-logout redirect URI for full-chain logout.
  • Arc (Release v20.62.1): Fixed a process crash in observable-query streaming (SSE and WebSocket) when a client disconnects while an emission is in flight. The emission callback is async void and, once the connection’s write lock, emission gate and cancellation source are disposed on disconnect, the in-flight emission threw ObjectDisposedException on a background thread, which went unhandled and terminated the whole process. Disconnecting mid-emission is now a graceful no-op: the expected cancellation/disposal/transport signals are swallowed and only genuine failures are surfaced to the subscriber.
  • Screenplay (Release v1.5.1): The invoicing sample no longer uses a redundant projection-level automap — AutoMap is the default
  • Screenplay (Release v1.5.1): The invoicing sample uses every instead of all for per-projection mappings, and showcases all in a new SystemActivity slice matching its documented system-wide semantics
  • Screenplay (Release v1.5.1): The invoicing sample no longer points a projection at a named sequence its own events never reach
  • Screenplay (Release v1.5.1): The invoicing sample maps arithmetic counters only from events that carry the referenced property, imports every external event it references, and uses the documented = mapping and plain string literals
  • Screenplay (Release v1.5.1): The auto-map documentation no longer shows an event-level no automap the parser rejects, and its join and children examples use the actual with and identified by forms
  • Screenplay (Release v1.5.1): The projection grammar documents the per-with AutoMap toggle and the sequence directive, and its closing example uses the real join syntax
  • Studio (Release v0.21.0): Live capture no longer recaptures the same layer back-to-back when deferred mutations re-dirty it — repeats now coalesce into a single recapture
  • Studio (Release v0.19.0): Fixed a render loop when opening a domain’s concepts from the project hierarchy that could stop the concepts view from appearing and crash the app when closing it.
  • Chronicle.TypeScript (Release v2.1.1): Fixed the client dropping its Chronicle session when an OAuth2 token refresh failed while the cached token was still valid — the cached token now keeps flowing until it truly expires, and failed token fetches are throttled so an unreachable authentication endpoint no longer turns every RPC into a token request
  • Chronicle.TypeScript (Release v2.1.1): Fixed a non-numeric expires_in in the token response causing a token fetch on every RPC
  • Chronicle.Kotlin (Release v2.1.1): Fixed the client retrying a dead server address forever: the connection now redials on every reconnect attempt — re-resolving DNS/SRV records and re-selecting a host through the load balancer — so a replaced host or a changed record is picked up instead of being retried indefinitely
  • Chronicle.Kotlin (Release v2.1.1): Fixed a momentary token-endpoint outage failing calls while the cached OAuth token was still valid: the client now falls back to the cached token until it truly expires and throttles failed fetch attempts, so an auth blip no longer drops the session
  • Arc (Release v20.62.0): Header-based tenant resolution now applies for the whole request instead of only inside endpoint delegates, so tenant-scoped work that runs earlier no longer falls back to the default namespace and database; header lookup is now case-insensitive so a configured header still matches when HTTP/2 delivers it lowercased (#2351)
  • Chronicle (Release v16.5.2): The SQL event-store backend no longer risks an infinite retry loop when appending at a sequence number that is already taken (for example after a silo restart leaves the grain’s counter behind the stored tail). Storage now reports the true next-available sequence number so the append recovers, matching the MongoDB and in-memory backends
  • Chronicle (Release v16.5.1): Job monitoring no longer hides backend failures as an empty result. When the jobs storage fails, observing jobs now surfaces the error to the caller instead of an empty stream, and both observing jobs and reading job steps log the failure — so the Workbench no longer silently shows an empty list on a real fault
  • Chronicle (Release v16.4.1): Projection-backed observable read-model queries now keep emitting after a connection drop — previously the watch stream was never re-established after the first reconnect, so live queries silently froze on stale data
  • Chronicle.Elixir (Release v2.1.3): Fixed the hourly session drop for clients using username/password authentication: the OAuth2 token is now attached to every RPC individually — cached and refreshed ahead of expiry — instead of being baked into the gRPC channel at connect time, so token expiry no longer invalidates the channel or interrupts the session
  • Chronicle.Elixir (Release v2.1.2): Fixed the client permanently losing its Chronicle session after a stale gRPC channel — e.g. an hourly OAuth token expiry or silent TCP death — by rebuilding the channel (re-resolving addresses and re-fetching authentication headers) whenever the session drops or fails to start, instead of retrying forever on the dead channel
  • Arc (Release v20.61.4): A Uri property now generates a TypeScript string instead of a Date, so its value is no longer silently lost to an invalid date on the client
  • Studio (Release v0.18.4): Fixed a full-app white-screen crash (Cannot read properties of null (reading 'useState') at ToolbarSlotProvider) caused by a second copy of React being bundled. The Core Vite build now dedupes react, react-dom, and the jsx runtimes so the local @cratis/components/Toolbar dev override (which resolves into a sibling Components checkout with its own node_modules/react) binds to Studio’s single React instance instead of a second one whose hooks dispatcher is null.
  • Studio (Release v0.18.4): Fixed the multi-arch Docker pipeline stripping the built frontend from Core/Admin/Lobby images: the broad **/wwwroot ignore rule in .dockerignore also excluded each service’s published out/{x64,arm64}/wwwroot, so the image shipped a backend with an empty wwwroot. Re-include **/out/**/wwwroot.
  • Studio (Release v0.18.4): Production was restored out-of-band by building and pushing registry.cratis.studio/core:0.18.5 locally and rolling out the core deployment (the GitHub runner is unstable). Verified on the live pod: React mounts, the shell + welcome dialog render, no dispatcher crash.
  • Studio (Release v0.18.4): Intentionally left unmerged — merging triggers the auto-deploy on the unstable runner. Merge when CI is healthy; the fix is already live in production.
  • Studio (Release v0.18.3): Built-in LLM features (AI event-model generation, explanations, Prologue extraction) no longer fail — the default self-hosted model now fits the LLM service’s memory limit instead of OOM-killing it on every request.
  • Chronicle.Elixir (Release v2.1.1): Fixed a race condition where starting a Chronicle connection session without an explicit client name could fail with {:error, {:already_started, pid}} when done concurrently, because every unnamed session was registered under the same global process name.
  • Chronicle.Elixir (Release v2.1.1): [x] mix compile --warnings-as-errors
  • Chronicle.Elixir (Release v2.1.1): [x] mix test (full suite, run repeatedly — 0 failures)
  • Chronicle.Elixir (Release v2.1.1): [x] Targeted stress test: 50 concurrent Session.start_link/1 calls without client_name — 0 collisions
  • Chronicle.TypeScript (Release v2.1.0): The client now reconnects when the kernel keep-alive is lost. Previously the keep-alive loop logged the stream ending or erroring and then stopped, leaving the client on a dead session: appending events kept working while reactors and reducers silently stopped receiving anything.
  • Chronicle.TypeScript (Release v2.1.0): A connection that goes silent without erroring is now detected and reconnected. The kernel does not close the keep-alive stream when it evicts a client, so waiting for an error never fired.
  • Chronicle.TypeScript (Release v2.1.0): Reactor and reducer observation streams are re-established after they end, instead of that observer stopping permanently. This includes streams the kernel closes deliberately, such as cross-store (inbox) observations.
  • Chronicle.TypeScript (Release v2.1.0): Reconnects no longer leak a duplicate observation stream per cycle, or leave the re-established observation untracked.
  • Chronicle.TypeScript (Release v2.1.0): The connection health check can no longer hang indefinitely or stack overlapping probes.
  • Chronicle.Kotlin (Release v2.1.0): The client now reconnects to the kernel instead of staying down. A dropped connection was swallowed by empty catch blocks, so it completed silently with nothing logged and no way to recover short of restarting the application.
  • Chronicle.Kotlin (Release v2.1.0): A connection that goes silent without erroring is now detected and reconnected. The kernel does not close the keep-alive stream when it evicts a client, so waiting for an error never fired.
  • Chronicle.Kotlin (Release v2.1.0): Reactors and reducers are re-registered on every reconnect. They previously registered once against a connection ID captured at construction, so after any reconnect they observed nothing for the rest of the process lifetime.
  • Chronicle.Kotlin (Release v2.1.0): Reactor and reducer observation streams are re-established after they end, instead of that observer stopping permanently. This includes streams the kernel closes deliberately, such as cross-store (inbox) observations.
  • Chronicle.Kotlin (Release v2.1.0): Keep-alive and observation failures are now reported instead of being discarded silently.
  • Chronicle.Elixir (Release v2.1.0): Reactors and reducers no longer stop receiving events about a minute after startup. The client consumed the kernel’s keep-alives but never answered them, so the kernel stopped counting it as connected and unsubscribed its observers — appending events kept working, which made the client look healthy.
  • Chronicle.Elixir (Release v2.1.0): A lost connection is now detected and reconnected even when the stream stays open. The kernel does not close the keep-alive stream when it evicts a client, so a half-disconnected client previously stayed in that state until the application was restarted.
  • Chronicle.Elixir (Release v2.1.0): A dropped connection no longer schedules two overlapping reconnects, and a connection that never came up no longer reports a disconnect to observers.
  • Arc (Release v20.61.3): A regex validation rule whose pattern already escapes a slash — Matches(@"^\d{2}\/\d{2}$") — generated a client validator that did not parse: the slash was escaped a second time, and the resulting \\/ let the slash terminate the regex literal early. Slash escaping is now escape-aware, so a pattern’s own escapes pass through untouched and only a bare slash is escaped.
  • Arc (Release v20.61.3): An exact-length rule — Length(4) — projected to the client as length(0, 0), since the extractor read a Length property that ExactLengthValidator does not have. It reads the validator’s Min (which carries the exact length) instead, so length(4, 4) is generated.
  • Studio (Release v0.17.2): Restored uniqueness enforcement for user-invitation emails, project names, application names, and organization names, which had been silently disabled
  • Studio (Release v0.17.2): Renaming a project onto a name already used by another project is now rejected
  • Studio (Release v0.16.1): Daily backups now write all seven weekday slots. The Sunday slot could never be created, because the weekly rollup runs on Mondays and took its place (#800)
  • Studio (Release v0.16.1): A daily backup is no longer skipped on the first of a month or on 1 January, where the monthly and yearly rollups previously replaced it (#800)
  • Studio (Release v0.15.1): Fixed remote collaborator cursors freezing at their first position instead of moving smoothly
  • Studio (Release v0.15.0): Fixed the active collaborators list showing an unreadable encrypted value instead of the person’s name
  • Arc (Release v20.61.2): A model-bound command’s client validation rules were taken from the wrong type. When a command’s own validator held no client-projectable rule, ToCommandDescriptor treated the supplied-but-empty rule set as “not supplied” and re-extracted from the Handle method’s parameter — which for a model-bound command is the value Provide() resolves, not the command. A command whose Provide() returns a record carrying a validated concept (e.g. an Email) then had that concept’s rules emitted on its own generated validator, bound to a field the command does not have — invalid TypeScript. “No rules supplied” (null) is now distinguished from “supplied, empty”, so the fallback runs only for the controller path it was written for.
  • Arc (Release v20.61.2): A regex rule was emitted as a quoted string, but the client-side matches rule takes a RegExp. The pattern is now carried through as a RegularExpressionPattern and formatted as a regex literal — an empty pattern as /(?:)/, a literal slash escaped — so matches(/^\d{4}$/) is generated rather than an unassignable matches('^\d{4}$').
  • Arc (Release v20.61.1): A validation rule comparing against a non-numeric value — most often a RuleFor(x => x.When).GreaterThan(DateOnly.MinValue) “must be set” sentinel — generated a client validator that did not parse (greaterThan(01/01/0001), an invalid TypeScript literal). The client-side comparison validators (greaterThan, lessThan, …) operate on numbers, so such a comparison is now skipped at extraction — the server still enforces it, there is simply no client rule to project. As a backstop, any non-numeric argument that still reaches the formatter is quoted, so no unparseable literal can be emitted.
  • Arc (Release v20.61.0): FluentValidation rules now reach generated client proxies. No rule had ever been projected: generation walks the target project through a MetadataLoadContext, whose types carry no executable code, while a FluentValidation rule only exists once its validator’s constructor has run — so instantiating the validator always threw, and the catch turned that into “no rules”. Every extractor spec passed because they hand it runtime types, which the generator never has. Validator types are now resolved in the default load context and instantiated there. DataAnnotations were unaffected, being read from metadata.
  • Arc (Release v20.61.0): A validation message declared lazily — .WithMessage(_ => Messages.Something), the form a localized message takes — is held as a factory rather than a string and was dropped. It is now resolved where it does not depend on the instance, and left unprojected rather than guessed at where it does.
  • Arc (Release v20.61.0): The proxy generator’s AssemblyLoadContext.Default resolving hook handed back a metadata-only assembly, which throws Resolved assembly must be a runtime Assembly object. Caching that assembly is the point of the hook; returning it was not.
  • Arc (Release v20.61.0): A generic static method on a [ReadModel] is no longer discovered as a query. Discovery matches on return type alone, so a generic composition helper returning the read model’s own query shape was registered, routed, and given a client proxy — and then every call failed with Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true. Rejected now at the shared runtime predicate, its copy in the proxy generator, and the metadata generator.
  • Studio (Release v0.14.0): Fixed the collaborator list never decreasing — closing a tab now removes the collaborator immediately
  • Arc (Release v20.60.3): A command implementing ICanProvideEventSourceId no longer returns an unhandled server error when its key cannot be composed from the incoming payload — an uncomposable or null key resolves to EventSourceId.Unspecified, so the command reaches the filter and validation stages that turn bad input into a proper response.
  • Studio (Release v0.13.7): Fixed the CPU spike and endless resource-request loop on boards containing slice specifications
  • Studio (Release v0.13.6): Fixed the remaining stylesheet/font/image request loop during live collaboration (toolbar recaptured on no-op attribute rewrites)
  • Studio (Release v0.13.5): Fixed the endless stylesheet/font/image request loop while collaborating (every remote cursor move re-captured the page)
  • Studio (Release v0.13.5): Fixed remote collaborators’ changes — moves, sticky notes, and content edits — not appearing live in other browsers
  • Studio (Release v0.13.5): Fixed remote collaborator cursors rendering on top of the project drawer and panels
  • Studio (Release v0.13.4): Fixed collaborator presence, remote cursors, and live updates never appearing in multi-tenant (organization) deployments
  • Studio (Release v0.13.3): Fixed live collaborator cursors and the collaborator list not appearing for other participants on the event model board
  • Studio (Release v0.13.2): Fixed the Core, Admin, and Lobby image builds and deploy failing after PrimeReact was accidentally bumped to a major version incompatible with @cratis/components
  • Studio (Release v0.13.1): Fixed live collaboration failing with an internal server error — collaborator presence and cursors now work across sessions
  • Studio (Release v0.13.0): Translator slices now list events produced by other modules in the event picker, including ones added earlier in the same session (#822)
  • Studio (Release v0.13.0): Admin vault tool now drills into a service and then a tenant/organization when clicked, revealing that organization’s keys (#799)
  • Arc (Release v20.60.2): Observable query connections no longer reconnect spuriously while data is flowing. The server now guarantees a message at least once per keep-alive interval instead of allowing gaps of up to twice the interval, so the SSE client stops tearing down healthy connections, re-subscribing every query and re-delivering every snapshot — which surfaced as UI flicker during normal use.
  • Arc (Release v20.60.2): Re-delivering a snapshot no longer re-renders everything. Incoming payloads are reconciled against the data already held, so items that did not change keep their object identity and only the items that actually changed re-render. An identical snapshot produces no update at all.
  • Arc (Release v20.60.2): Setting Query.KeepAliveInterval to a longer value no longer causes the SSE client to reconnect in a loop. The client now derives its idle threshold from the interval the server advertises rather than assuming the default.
  • Arc (Release v20.60.2): Disabling keep-alive by setting Query.KeepAliveInterval to zero or a negative value no longer leaves the SSE client reconnecting forever waiting for pings that were never going to come.
  • Arc (Release v20.60.1): A validator that throws while validating a query is reported as a validation failure rather than a server error
  • Arc (Release v20.60.1): A query taking an injected dependency alongside its arguments now has its client-side rules generated; the shape check previously required the argument model to mirror the dependency too, and silently emitted no rules
  • Arc (Release v20.60.1): A concept reachable both through a query’s argument model and through the parameter itself no longer has its rule, and its message, emitted twice
  • Arc (Release v20.60.1): A query with no arguments no longer binds an unrelated same-named Parameters type
  • Arc (Release v20.60.1): DateOnly and TimeOnly values are no longer walked as though their calendar components were part of the model
  • Arc (Release v20.60.1): Validation rules carrying a string argument (such as Matches) or a message containing an apostrophe now generate valid TypeScript
  • Studio (Release v0.12.8): Content behind glass no longer jumps/repositions when a background capture completes during or right after a canvas pan.
  • Studio (Release v0.12.7): Panning the event-model canvas no longer re-inlines resources or visually re-anchors the refracted background for common scroll distances.
  • Studio (Release v0.12.6): Panning/scrolling the canvas no longer “runs out of background” (glass refracting bare surface), jumps/repositions, or re-loads styles and fonts: the base scene is captured with a margin beyond the viewport and slid to follow the pan, so it stays over real content without re-rasterizing until you scroll past the margin.
  • Studio (Release v0.12.6): Where nothing is captured, glass now refracts the page’s own surface color instead of black.
  • Studio (Release v0.12.5): Fixed a Liquid Glass recapture storm driven by the cogwheel (and About-dialog logo) icons re-setting their SVG innerHTML on every render, which re-rasterized the page (re-loading styles/fonts) during board interaction.
  • Studio (Release v0.12.4): Panning/zooming the canvas no longer flickers the Liquid Glass refraction, stutters, or re-loads styles and fonts on every frame (very visible on Safari): the base scene is no longer re-rasterized mid-gesture — the compositor slides the existing capture to track the motion, and a single recapture lands shortly after the gesture stops.
  • Studio (Release v0.12.3): Liquid Glass no longer freezes for several seconds during panning/editing: captures give up on unloadable images almost immediately, and every capture is hard-capped at 2.5s (keeping the previous frame rather than blocking).
  • Studio (Release v0.12.2): A slow or hanging image (for example an avatar request that stalls) can no longer freeze a Liquid Glass capture for up to 15 seconds — captures give up on a stuck image after 4 seconds and refract without it.
  • Studio (Release v0.12.1): Fingerprinted static assets (JS, CSS, fonts) are now served with Cache-Control: public, max-age=31536000, immutable instead of no cache headers, so the browser stops re-downloading them. This removes the repeated style.css downloads and font revalidations that the liquid-glass capture pipeline triggered on every capture (html2canvas re-references the stylesheet and fonts each time) — the “it keeps loading styles and fonts over and over” churn. Unfingerprinted entry files (index.html, favicon.svg) still revalidate so a new deploy is picked up immediately.
  • Studio (Release v0.11.2): The top toolbars no longer flash black while panning the event-model board. The appearance wallpaper was part of the sliding base scene, so panning revealed an uncaptured black strip; the wallpaper is now a dedicated viewport-fixed glass layer that the compositor never slides, so the revealed area shows the wallpaper instead of black.
  • Studio (Release v0.11.1): The event-model board no longer triggers a runaway “loading fonts/styles over and over” storm. The slice status icons re-applied their SVG (dangerouslySetInnerHTML) on every board re-render because React’s DOM diff treats a fresh dangerouslySetInnerHTML object as changed by reference — each of those DOM mutations made the liquid-glass pipeline re-rasterize the whole page. The icon’s inner-HTML object is now memoized per status, so React skips the re-set while the status is unchanged.
  • Studio (Release v0.10.10): Glass captures no longer fail on modern CSS color functions. html2canvas throws on oklab/oklch and color-mix(in oklab, …) (which Tailwind v4 emits everywhere); a single occurrence aborted the whole capture, so populated pages never refracted and kept re-loading fonts/styles. The capture now resolves those to plain rgba before rasterizing.
  • Screenplay (Release v1.2.1): The printer no longer breaks the build of applications that use Cratis type discovery. The internal ScreenplayWriter’s nested Scope struct was public, so consumers’ generated type-discovery provider referenced it through its internal container and failed to compile (CS0122). Scope is now internal.
  • Studio (Release v0.10.8): Clicking any button no longer reloads all fonts/styles/icons — PrimeReact’s click ripple (and tooltip bubbles) no longer trigger a glass recapture.
  • Studio (Release v0.10.8): Toolbar groups now render as clean, separate stadium pills with a gap between them, instead of a single metaball blob that necked the groups together and clipped past the toolbar edges.
  • Studio (Release v0.10.7): Avatar uploads no longer crash against UpCloud object storage. AWS SDK v4’s default flexible-checksum trailer was rejected by UpCloud’s S3-compatible storage (“Content-SHA256 mismatch”); checksums are now only added when the operation requires one.
  • Studio (Release v0.10.7): Hovering toolbar buttons and other UI no longer triggers repeated full-page resource refetching — appearance-only CSS transitions (hover/opacity fades) and tooltip chrome no longer force a glass recapture.
  • Studio (Release v0.10.7): Dragging a dialog no longer refetches all fonts and styles — the inert p-unselectable-text drag-guard class toggled on the body is ignored.
  • Studio (Release v0.10.7): Resizing the browser window is smooth again — glass rendering is paused for the duration of the resize and does a single recapture once it settles, instead of rebuilding every scene texture per frame.
  • Studio (Release v0.10.6): Liquid-glass toolbars in the event-model editor now render each tool group as its own separated glass pill instead of merging every group into one.
  • Studio (Release v0.10.6): Inviting a user to an existing organization now shows the invited email in the pending-invitations list and sends the invitation email — previously a compliance-subject/read-model-key mismatch left the encrypted email undecryptable, so it showed empty and the mail went to an empty recipient.
  • Studio (Release v0.10.6): Persona avatars no longer show a broken image or spam avatar requests when the stored image is missing: HasAvatar is computed live from the avatar store (so it reflects the actual stored image), and the avatar falls back to initials if the image fails to load.
  • Studio (Release v0.10.5): Liquid glass now refracts a canvas in real time while you pan it, instead of freezing and only catching up after you stop. The glass in the appearance preview refracts its own canvas and never the editor behind the settings overlay.
  • Studio (Release v0.20.0): The manual add-credential dialog with free-text provider/subject fields, which let a user claim any unclaimed subject without proving control. (#862)
  • AuthProxy (Release v2.10.0): The endpoint is a service-to-service back-channel that carries no bearer token (there is no user-supplied token in this flow); it relies on being network-isolated from browser traffic, exactly like the invite and link exchanges. It trusts the subject AuthProxy delivers from a real provider authentication, never a client-supplied subject.
  • AuthProxy (Release v2.10.0): The client IP and derived location are personal data; the application is responsible for handling and retention.
  • AuthProxy (Release v2.8.0): The link challenge requires an authenticated session (anonymous → 401), validates the provider scheme (unknown → 404) and requires a one-time token (missing → 400). returnUrl is constrained to a same-site relative path so the endpoint can never be turned into an open redirect. The subject is delivered to the application server-to-server from a real provider authentication — never trusted from client input. (Cratis/Studio#862)
  • AuthProxy (Release v2.8.0): Not an iframe. The design in the issue calls for an iframe, but provider consent pages send X-Frame-Options: DENY and AuthProxy cookies are SameSite=Lax, so the flow is a popup / top-level redirect, as agreed in the issue’s posted design.
  • AuthProxy (Release v2.8.0): Session preservation is achieved by short-circuiting OnTicketReceived with context.HandleResponse() before the RemoteAuthenticationHandler signs the ticket into the cookie scheme (the “capture sub/iss and short-circuit” option from the design), rather than a throwaway sign-in scheme.
  • AuthProxy (Release v2.8.0): Same-account limitation (assumption): the challenge does not force prompt=select_account, so a provider with an active SSO session may silently return the same account. Left out because prompt handling differs across OIDC/OAuth and GitHub has no standard equivalent; flagging for review — it can be added if linking a different account of the same provider must be guaranteed.
  • Studio (Release v0.20.0): The link token is short-lived (10 min), single-use (atomic consume), and bound to the user and organization that started the link; the association runs in that user’s own authenticated request. The verified subject is delivered to the callback server-to-server from a real provider authentication with the token as bearer — a client-supplied subject is never trusted. (#862)
  • Studio (Release v0.20.0): Design deviation — store-then-consume, not “the callback runs the command”. The AuthProxy callback is server-to-server (no Studio session/tenant), so it cannot run an authenticated Arc command. Mirroring the existing invite-exchange (AuthProxy records the verified subject; the authenticated flow consumes it), the callback records the verified subject against the token and the popup-return runs AssociateIdentityProvider in the signed-in user’s request. This keeps the command as the association mechanism, with the real identity/namespace and all its guards. Called out because the issue phrasing implies the callback itself associates.
  • Studio (Release v0.20.0): Popup, not iframe (as agreed in #862): provider pages send X-Frame-Options: DENY and AuthProxy cookies are SameSite=Lax.
  • Studio (Release v0.20.0): Callback trust = network isolation, identical to the existing api/internal/identity-providers/in-use and api/internal/tenants back-channels: the endpoint must not be reachable by browsers through the AuthProxy. Please confirm the deployment does not proxy api/internal/* to browsers.
  • Studio (Release v0.20.0): CredentialLinkSessions uses a single tenant-independent MongoDB collection (built from Cratis:MongoDB:Server/Database), because the token must be resolvable with no tenant context — like the Lobby’s AcceptedInvitation. A TTL index sweeps expired sessions.
  • Studio (Release v0.20.0): Popup return path is the fixed route /link-credential/complete, which assumes the app is serve
  • Studio (Release v0.18.0): Enforced with a race-safe Chronicle uniqueness constraint, backed by a configured backchannel the Lobby uses to surface the error during onboarding (#826)
  • Studio (Release v0.17.1): Account profile commands — update email, update personal information, and upload avatar — now reject requests that target another user’s profile
  • Studio (Release v0.17.1): The “my profile” and “my avatar” queries no longer accept a caller-supplied profile id, so one user can no longer read another user’s profile details or avatar
  • Arc (Release v20.60.1): Validators declared against a query’s argument set are now enforced on the server. They were previously applied only by the generated
  • No updates