@cratis/pi 7.112.0 → 7.114.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/package/corpus/harnesses/copilot/instructions/application-profile.instructions.md +1 -1
  2. package/package/corpus/harnesses/copilot/instructions/orleans.instructions.md +10 -2
  3. package/package/corpus/harnesses/copilot/instructions/pull-requests.instructions.md +7 -0
  4. package/package/corpus/harnesses/copilot/instructions/specs.csharp.instructions.md +4 -4
  5. package/package/corpus/harnesses/copilot/instructions/vertical-slices.instructions.md +1 -1
  6. package/package/corpus/hooks/scripts/cratis-store-mutations.json +4 -0
  7. package/package/corpus/product-sync.json +88 -88
  8. package/package/corpus/rules/application-profile.md +1 -1
  9. package/package/corpus/rules/orleans.md +10 -2
  10. package/package/corpus/rules/pull-requests.md +7 -0
  11. package/package/corpus/rules/specs.csharp.md +4 -4
  12. package/package/corpus/rules/vertical-slices.md +1 -1
  13. package/package/corpus/skills/cratis-application-slice-specifications/references/query-and-decision-scenarios.md +19 -0
  14. package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/SKILL.md +8 -0
  15. package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/authproxy.md +26 -0
  16. package/package/corpus/skills/cratis-arc-command/references/proxy-generation.md +10 -1
  17. package/package/corpus/skills/cratis-arc-command-execution/SKILL.md +3 -2
  18. package/package/corpus/skills/cratis-arc-command-execution/references/occurrence-commands.md +7 -6
  19. package/package/corpus/skills/cratis-arc-command-validation/SKILL.md +5 -0
  20. package/package/corpus/skills/cratis-arc-command-validation/references/input-binding.md +17 -0
  21. package/package/corpus/skills/cratis-arc-command-validation/references/protected-validator-construction.md +94 -0
  22. package/package/corpus/skills/cratis-arc-ef-core-migration/SKILL.md +18 -0
  23. package/package/corpus/skills/cratis-arc-query-paging/SKILL.md +11 -4
  24. package/package/corpus/skills/cratis-arc-query-paging/references/live-query-processing.md +71 -0
  25. package/package/corpus/skills/cratis-arc-react-page/SKILL.md +11 -0
  26. package/package/corpus/skills/cratis-arc-validation-kotlin/SKILL.md +20 -3
  27. package/package/corpus/skills/cratis-chronicle-cli-operations/SKILL.md +11 -2
  28. package/package/corpus/skills/cratis-chronicle-cli-operations/references/command-effects.md +7 -0
  29. package/package/corpus/skills/cratis-chronicle-cli-operations/references/project-tooling.md +91 -0
  30. package/package/corpus/skills/cratis-chronicle-cli-operations/references/recovery-and-comparison.md +68 -0
  31. package/package/corpus/skills/cratis-chronicle-client-elixir/SKILL.md +12 -0
  32. package/package/corpus/skills/cratis-chronicle-client-elixir/references/decision-reads.md +10 -0
  33. package/package/corpus/skills/cratis-chronicle-client-go/SKILL.md +12 -2
  34. package/package/corpus/skills/cratis-chronicle-client-kotlin/SKILL.md +4 -0
  35. package/package/corpus/skills/cratis-chronicle-client-kotlin/references/annotations-and-handlers.md +6 -1
  36. package/package/corpus/skills/cratis-chronicle-client-kotlin/references/fundamentals-migration.md +48 -0
  37. package/package/corpus/skills/cratis-chronicle-client-typescript/SKILL.md +18 -0
  38. package/package/corpus/skills/cratis-chronicle-client-typescript/references/lifecycle.md +7 -0
  39. package/package/corpus/skills/cratis-chronicle-read-model/references/queries.md +5 -3
  40. package/package/corpus/skills/cratis-cli-terminal-workbench/SKILL.md +5 -1
  41. package/package/corpus/skills/cratis-components-common-controls/SKILL.md +11 -0
  42. package/package/corpus/skills/cratis-components-data-surfaces/SKILL.md +5 -0
  43. package/package/corpus/skills/cratis-components-data-surfaces/references/query-table-updates.md +51 -0
  44. package/package/corpus/skills/cratis-components-schema-editor/references/tree-layout.md +18 -0
  45. package/package/corpus/skills/cratis-components-stepper-command-dialog/SKILL.md +11 -0
  46. package/package/corpus/skills/cratis-fundamentals-type-discovery/SKILL.md +13 -0
  47. package/package/corpus/skills/cratis-orleans-jobs/SKILL.md +39 -51
  48. package/package/corpus/skills/cratis-orleans-jobs/references/lifecycle-and-placement.md +52 -0
  49. package/package/corpus/skills/cratis-orleans-jobs/references/state-machines.md +3 -1
  50. package/package/corpus/skills/cratis-release-notes/SKILL.md +23 -0
  51. package/package/corpus/skills/cratis-screenplay-command-surface/references/protected-reads.md +3 -2
  52. package/package/corpus/skills/cratis-screenplay-legacy-extraction/references/prologue-safety.md +14 -0
  53. package/package/corpus/skills/cratis-screenplay-toolchain/references/screenplay-contract.version +1 -1
  54. package/package/corpus/skills/cratis-specifications-csharp/SKILL.md +14 -2
  55. package/package/corpus/skills/cratis-specifications-csharp/references/running-specs.md +8 -1
  56. package/package/corpus/skills/cratis-specifications-csharp/references/shared-lifecycle.md +19 -2
  57. package/package.json +1 -1
@@ -0,0 +1,68 @@
1
+ <!-- Copyright (c) Cratis. All rights reserved. -->
2
+ <!-- Licensed under the MIT license. See LICENSE file in the project root for full license information. -->
3
+
4
+ # Recovery outcomes and namespace comparison
5
+
6
+ Check the installed `cratis llm-context` and server version before using these
7
+ commands. Confirm server, event store, namespace and exact targets. A prompt or
8
+ `--yes` is not authority to mutate a live store.
9
+
10
+ ## Jobs: acceptance is not completed removal
11
+
12
+ Requires CLI 3.79.0 for `chronicle jobs stop` / `resume` and the terminal
13
+ Workbench to report kernel refusals as failures, with reasons in text/JSON and a
14
+ nonzero exit. Do not parse an old CLI's success message as proof of progress.
15
+ Inspect the job again; resume can be refused for missing, concluded, unpersisted
16
+ or otherwise unresumable work. Do not repeat it without understanding the reason.
17
+
18
+ Requires CLI 3.99.0 for `cratis chronicle jobs delete <JOB_ID>`. It is destructive
19
+ and irreversible: retained job state is removed. Before confirmation it names
20
+ the store, namespace and job id. An invalid GUID, declined/unavailable prompt,
21
+ server refusal, authorization failure or server error is nonzero. `--yes` skips
22
+ only the local prompt; the server still authorizes and decides. Exit zero and
23
+ "deletion requested" are **not** proof of completed removal. Capture the relevant
24
+ pre-state first and inspect again after an authorized deletion. This is not a
25
+ terminal Workbench key or permission to delete every retained job.
26
+
27
+ ## Retry all failed partitions
28
+
29
+ Requires CLI 3.79.0 and Chronicle 19.80.0 for
30
+ `cratis chronicle observers retry-failed-partitions <OBSERVER_ID>`. It starts
31
+ server-owned bounded-batch recovery and reports how many partitions were failed;
32
+ it does not wait for all handlers to succeed. Inspect failures first, fix their
33
+ cause, authorize the observer-wide target, then re-read state after the request.
34
+ Do not mistake this for a client loop of one-partition requests or a guarantee
35
+ that quarantines were cleared.
36
+
37
+ ## Inspect or repair a closed scope
38
+
39
+ Requires CLI 3.80.0 and Chronicle 19.39.0 for
40
+ `cratis chronicle streams closed list`. It is read-only and lists exact scope
41
+ dimensions, origin, owner constraint, sequence number and closing time. Filter by
42
+ event source id/type and event stream type/id; do not select a repair from a
43
+ partial dimension match.
44
+
45
+ `cratis chronicle streams closed reopen --reason <text>` is a confirmed,
46
+ mutating repair of **one exact** mistaken manual close. Supply the scope flags
47
+ shown by the installed help/catalog and the reason. The kernel records actor
48
+ and reason in `StreamScopeReopened` and refuses a closure owned by a closing
49
+ event. `--yes` skips confirmation, not that ownership check. Never turn this into
50
+ a way around a modeled closure or reopen broad scopes speculatively.
51
+
52
+ ## Compare a model with live metadata
53
+
54
+ Requires CLI 3.85.0 for
55
+ `cratis screenplay conform-namespace <model> --event-store <store> --namespace <ns>`.
56
+ This is a read-only comparison, not model authoring, rendering or state repair.
57
+ It compares registered event types, producing commands/reactors and observers
58
+ with the model, scanning metadata up to the tail captured at start. The default
59
+ `--max-events` is `100000`; `--from`/`--to` bound a range. A partial scan stays
60
+ partial; without `--fail-on-drift` a drift report need not fail the command.
61
+
62
+ Requires 3.89.1 for authorization failures to exit 4 (`authentication_error`),
63
+ Ctrl+C between pages to exit 8 (`inconclusive`), and event attribution only when
64
+ the causation is a command. Chronicle's metadata API still transmits event source
65
+ ids and subjects; the CLI drops them without persisting them. Do not claim they
66
+ never cross the connection. It does not request payloads or command values.
67
+ Redact the report before sharing it, and do not treat an incomplete or cancelled
68
+ comparison as evidence of conformance.
@@ -103,6 +103,12 @@ channel exists return `{:error, :not_connected}`.
103
103
 
104
104
  ## Authentication and TLS
105
105
 
106
+ Requires Chronicle.Elixir 3.14.1 for client crash-report redaction; check `mix deps`, or treat older crash reports as potentially secret-bearing and upgrade before sharing them.
107
+
108
+ The client Logger filter redacts authentication secrets and gRPC/Mint request-header
109
+ state from crash reports; no application-level filter is needed for those client
110
+ reports. This does not authorize logging credentials in your own code.
111
+
106
112
  Use `ConnectionString.development()` locally: `default()` supplies **no
107
113
  credentials**, so an authentication-required development kernel never lets it
108
114
  reach `:registered`. Production uses URL userinfo `client-id:secret@host` or
@@ -196,6 +202,12 @@ failure.
196
202
 
197
203
  ### Reactors
198
204
 
205
+ Requires Chronicle.Elixir 3.14.0, contracts 19.70 and kernel 19.70.0 for start_at_tail; check `mix deps` and the server version, or retain initial catch-up until upgraded.
206
+
207
+ `use Chronicle.Reactors.Reactor, start_at_tail: true` skips history only on first
208
+ registration; an existing reactor keeps its position. `once_only` does not skip
209
+ initial catch-up. An older server ignores the flag and catches up from the beginning.
210
+
199
211
  Read [references/reactor-example.md](references/reactor-example.md) when you need a worked reactor module.
200
212
 
201
213
  - **`@handles` is an accumulating module attribute** declaring the subscription;
@@ -3,6 +3,16 @@
3
3
 
4
4
  # Decision reads and the dynamic consistency boundary
5
5
 
6
+ Requires Chronicle.Elixir 3.14.2 for the rejection/cleanup behavior below; check `mix deps`, or upgrade before relying on a rejected callback to discard buffered events.
7
+
8
+ A `Chronicle.decide/2` callback returning `{:error, reason}` rejects all buffered
9
+ appends and returns that tuple unchanged.
10
+ Migrate matches on `{:ok, {:error, _}}` to `{:error, _}`. A failed commit rolls
11
+ back the unit of work, and both `decide/2` and `with_unit_of_work/2` stop their
12
+ unit-of-work process on return, so later appends from long-lived GenServers or
13
+ Phoenix connections are not trapped in a failed buffer. Spec the rejection and
14
+ failed-commit paths, not only successful decisions.
15
+
6
16
  Source: `Cratis/Chronicle.Elixir`: `Source/chronicle/lib/chronicle/read_models/decision_reads.ex`, `decision_read_refused.ex`, `decision_conflict.ex`, `transactions/unit_of_work.ex`, and `Documentation/dynamic-consistency-boundary.md`.
7
17
 
8
18
  Requires `cratis_chronicle` 3.13.0.
@@ -128,7 +128,15 @@ identity. `delivery.ID()` can key an external idempotency record; it is not an
128
128
  exactly-once guarantee. Return supported follow-up events rather than manually
129
129
  recreating effect dispatch; use projections for materialization, reactors for effects.
130
130
 
131
- `reactors.OnceOnly` excludes replay; it does **not** deduplicate failed-partition
131
+ Requires Chronicle.Go 0.11.0 and kernel 19.70.0 for StartAtTail; check `go list -m github.com/Cratis/Chronicle.Go` and the server version, or retain catch-up behavior until both are upgraded.
132
+
133
+ Opt into `reactors.StartAtTail()` for a new side-effect reactor that must skip
134
+ history. It only changes first registration: existing positions are retained and
135
+ explicit replay still starts at the beginning. Older kernels ignore this option
136
+ and catch up history. `observation.Service.FastForward` and `FastForwardResult`
137
+ move an observer to the tail; this deliberate administrative skip is not recovery.
138
+
139
+ `reactors.OnceOnly()` excludes replay; it does **not** deduplicate failed-partition
132
140
  recovery. Effects may repeat after errors, cleanup failures or reconnect. Keep them
133
141
  idempotent. The kernel owns recovery/quarantine and progress; do not invent resume
134
142
  positions or acknowledge before successful processing and cleanup. Read the
@@ -137,7 +145,9 @@ for exact effect, replay and registration-readiness limits.
137
145
 
138
146
  ## Unsupported does not mean success
139
147
 
140
- Requires Chronicle kernel 19.32.3 for decision guards, with compatibility preflight;
148
+ Requires Chronicle kernel 19.70.0 for the current Go decision-guard profile; check the server version or postpone the client upgrade.
149
+
150
+ Decision guards include compatibility preflight;
141
151
  unsupported kernels return `ErrUnsupported`. Protected operations have their own
142
152
  kernel capability gates; the client supports qualified protected revisions and
143
153
  classified read-model replay routes, not every protected watch/profile.
@@ -11,6 +11,10 @@ ordinary JVM application that happens to talk to a Chronicle server over gRPC.
11
11
  There is no framework to inherit from and no application architecture imposed:
12
12
  you construct a client, ask it for an event store, and append or observe.
13
13
 
14
+ For Chronicle.Kotlin 7.x, first read the
15
+ [Fundamentals migration and upgrade notes](references/fundamentals-migration.md):
16
+ `ConceptAs.value()` and the shared correlation type are breaking changes.
17
+
14
18
  ## Verified product sources
15
19
 
16
20
  Source: `Cratis/Chronicle.Kotlin`, by source symbols and signatures.
@@ -13,7 +13,12 @@ This reference holds the observer annotations, their arguments, filtering annota
13
13
  | `@Constraint` | `id = ""` | `constraints/Constraint.kt` |
14
14
  | `@Seeder` | none | `seeding/Seeder.kt` |
15
15
 
16
- Handler-level: `@Replay`, `@OnceOnly`. Observer filtering: `@Tag`/`@Tags`,
16
+ Requires Chronicle.Kotlin 6.15.0 and kernel 19.70.0 for StartAtTail; check Gradle dependencies and the server version, or retain initial catch-up.
17
+
18
+ `@StartAtTail` on a reactor class skips initial history only. Existing positions
19
+ are unchanged.
20
+ `@OnceOnly` targets both classes and functions: it skips replay, not initial
21
+ catch-up or redelivery. Handler-level replay override: `@Replay`. Observer filtering: `@Tag`/`@Tags`,
17
22
  `@FilterEventsByTag`/`@FilterEventsByTags`, `@EventSequence`,
18
23
  `@EventSourceType`, `@EventStreamType`.
19
24
 
@@ -0,0 +1,48 @@
1
+ <!-- Copyright (c) Cratis. All rights reserved. -->
2
+ <!-- Licensed under the MIT license. See LICENSE file in the project root for full license information. -->
3
+
4
+ # Shared concepts, correlation and observer upgrades
5
+
6
+ ## Shared concepts and correlation
7
+
8
+ Requires Chronicle.Kotlin 7.0.0 for the shared concept and correlation type migration below; check Gradle dependencies, or retain the earlier client API until deliberately migrating and recompiling.
9
+
10
+ Import `ConceptAs` from `io.cratis.fundamentals.concepts` and implement `value()`,
11
+ not a property/getter. Java record accessors satisfy this interface directly.
12
+ Import `CorrelationId` from `io.cratis.fundamentals.execution`, use `NOT_SET` and
13
+ `value()`, and recompile consumers. The old Chronicle names are warning-level
14
+ Kotlin typealiases for this major version, not a permanent alternative API.
15
+ Typed source-id overloads consume Fundamentals concepts. Follow the product's
16
+ [migration guide](https://github.com/Cratis/Chronicle.Kotlin/blob/main/Documentation/guides/migrate-to-fundamentals.md).
17
+
18
+ Requires Chronicle.Kotlin 7.1.0 and Fundamentals 0.6.0 for shared ambient correlation context; check Gradle dependencies, or pass correlation explicitly instead of relying on shared ambient state.
19
+
20
+ The module-level `correlationIdManager` delegates to Fundamentals' shared
21
+ `CorrelationIdContext`. Its own API still takes/returns UUIDs; separately
22
+ constructed managers remain independent. State is thread-bound, not
23
+ coroutine-bound: pass correlation explicitly for suspending/thread-hopping work
24
+ and clear ambient context at the boundary. Never assume a pooled thread is a
25
+ request or tenant scope.
26
+
27
+ Event/read-model enum values are written as ordinal numbers to match their
28
+ schemas. Stored names remain readable; undefined ordinals, including numeric
29
+ strings, are rejected. Do not rearrange persisted enum ordinals casually.
30
+
31
+ ## Observer and transport upgrades
32
+
33
+ Requires contracts and kernel 19.70.0 for StartAtTail; check the server version, or retain initial catch-up until it is upgraded.
34
+
35
+ `@StartAtTail` applies to reactor classes in Kotlin and Java. It skips history
36
+ only on first registration; existing positions remain. `@OnceOnly` excludes
37
+ replay, not initial catch-up or redelivery. Older servers ignore the tail flag.
38
+
39
+ Requires Chronicle.Kotlin 6.14.0 and kernel 19.56.0 for fastForward; check Gradle dependencies and the server version, or do not offer this administrative operation.
40
+
41
+ `store.observers.fastForward(...)` accepts an identifier or reactor/reducer class
42
+ and returns `FastForwardResult`, with a Java bridge. It deliberately skips work;
43
+ it is not recovery or deduplication.
44
+
45
+ `ChronicleOptions.maxReceiveMessageSize` and `withMaxReceiveMessageSize()` default
46
+ to 100 MB; `null` retains grpc-java's own default. The constructor and `copy()`
47
+ have a trailing parameter; earlier constructor overloads remain. Recompile affected
48
+ calls rather than treating transport capacity as a query bound.
@@ -186,6 +186,24 @@ before enrollment.
186
186
 
187
187
  ## Observing
188
188
 
189
+ Requires Chronicle.TypeScript 6.53.0 and kernel 19.70.0 for startAtTail; check `yarn why @cratis/chronicle` and the server version, or retain catch-up until both are upgraded.
190
+
191
+ `@startAtTail()` skips history only on first registration; existing positions
192
+ stay intact. `@onceOnly()` does not skip initial catch-up. Older servers ignore
193
+ the new flag.
194
+
195
+ Requires Chronicle.TypeScript 6.52.0 and kernel 19.56.0 for fastForward; check the client/server versions, or do not offer the operation.
196
+
197
+ `observers.fastForward(observerId)` returns `FastForwardResult`; it deliberately
198
+ skips to the tail, not a retry mechanism.
199
+
200
+ Requires Chronicle.TypeScript 6.53.1, kernel 19.78.1 and Fundamentals 7.24.1 for the child/default-value behavior below; check installed packages and server version, or upgrade before relying on it.
201
+
202
+ Child/nested `@fromAllEvents` and `@fromEvery` keep root-only mappings off new
203
+ children. Replay affected projections to rebuild already-materialized child
204
+ values. Unset read-model fields retain their class defaults; absent arrays stay
205
+ empty.
206
+
189
207
  ### Handlers use camelCase names or `@handles(EventType)`
190
208
 
191
209
  The default is the camelCase event class name, **not** parameter-type dispatch.
@@ -1,5 +1,12 @@
1
1
  # Connection lifecycle
2
2
 
3
+ Requires Chronicle.TypeScript 6.51.1 for message-size options; check `yarn why @cratis/chronicle`, or keep gRPC defaults until upgrading.
4
+
5
+ `ChronicleOptions` and its factory methods accept `maxReceiveMessageSize` and
6
+ `maxSendMessageSize`. Both default to 100 MB; pass `null` to keep gRPC's own
7
+ default. Check payload bounds before increasing limits; a transport allowance is
8
+ not an unbounded-query policy.
9
+
3
10
  This reference holds the watchdog, reconnect, keepalive, compatibility check and telemetry behavior.
4
11
 
5
12
  ## Lifecycle
@@ -32,9 +32,11 @@ Chronicle extensions — Chronicle declares no `Observe` on `IMongoCollection<T>
32
32
 
33
33
  ## Discovery rules
34
34
 
35
- Arc discovers eligible **public and internal static** methods on `[ReadModel]`
36
- types. Internal visibility is not an endpoint privacy boundary. Keep helpers
37
- outside the read model, regardless of their visibility. Use
35
+ Arc discovers eligible **public static** methods on `[ReadModel]` types.
36
+ Requires Arc 22.121.0: non-public methods are excluded even with `[Query]`, and
37
+ ARC0029 warns on a non-public query-shaped method. A public query on an internal
38
+ read-model type still works. On older Arc, internal statics are exposed too;
39
+ keep helpers outside the read model when supporting those versions. Use
38
40
  `[ReadModel(RequireQueryAttribute = true)]` and `[Query]` on intended endpoints
39
41
  when the type also has folds (`Create`/`Reduce`); `[Query]` alone does not hide
40
42
  siblings. Requires Arc 22.27.1 for exclusion of private, protected, special-name
@@ -138,7 +138,11 @@ Several views bind a key to an operation that changes the running server:
138
138
  | Jobs | `S` / `U` | stop / resume the job |
139
139
  | Recommendations | `A` / `I` | perform / ignore the recommendation |
140
140
 
141
- Each has a bulk form that applies to every checked row.
141
+ Each has a bulk form that applies to every checked row. Requires CLI 3.79.0 for
142
+ job stop/resume to display kernel refusals as failures rather than success.
143
+ Inspect the reason and re-read the job; acknowledgement is not completed work.
144
+ Retained-job deletion is a separate CLI command (3.99.0), not a Workbench key;
145
+ read **cratis-chronicle-cli-operations** before requesting it.
142
146
 
143
147
  Every one of these opens a centered confirmation modal that states the action
144
148
  cannot be undone. **Only an explicit `Y` (or the Confirm button) confirms;
@@ -20,6 +20,17 @@ All claims and prop shapes are from **Cratis/Components** source rather than unc
20
20
 
21
21
  Imports are exported by `Source/Common/index.ts`; `Source/package.json` exposes the `Common` subpath. Use **cratis-components-styling** for the provider and CSS setup and **cratis-components-accessibility** for naming/focus. These controls do not replace Arc's generated `InputTextField`/other command fields; use **cratis-arc-react-page** for those bindings.
22
22
 
23
+ Requires Components 4.38.0 for provider routing and forwarded non-modal calendar fields; check `yarn why @cratis/components`, or retain host navigation and modal dates.
24
+
25
+ Set `CratisComponentsProvider.router` with `navigate` and optional `useHref` to
26
+ integrate `Breadcrumbs` and other link components with the app router. Plain
27
+ clicks navigate client-side; modifier and middle clicks retain native behavior.
28
+ Do not intercept every click in a host `onNavigate`.
29
+
30
+ `DatePickerInput.isNonModal` defaults to `false`; opting in lets an outside click
31
+ both close the calendar and reach the clicked control. The command form's
32
+ `CalendarField` forwards the same prop.
33
+
23
34
  ## Choose the semantic control first
24
35
 
25
36
  | Need | Control | Controlled contract |
@@ -132,6 +132,11 @@ Camera/controls contract (`Canvas.tsx`, `CanvasHandle.ts`):
132
132
 
133
133
  Persist item edits in the host, not in camera callbacks. Browser-test gestures and dimensions. For jsdom tests provide a `ResizeObserver` substitute where required; Pixi integration still needs a real browser signal.
134
134
 
135
+ For bound-table server filtering, query-state isolation, refreshed selection and
136
+ localized numbered pagination, read
137
+ [Query table updates](references/query-table-updates.md). Page-local filtering is
138
+ still the default; `serverQuery` is opt-in.
139
+
135
140
  ## 4. Public Chat: bind the host's messages and outcomes
136
141
 
137
142
  The public `@cratis/components/Chat` exports **`ChatConversation`**, **`ChatSidebar`**, **`ChatSidebarForObservableQueries`**, **`ChatTopicList`** and their types. It does **not** export the Kit `Chat` component or expose a `Chat/Kit` package subpath (`Source/Chat/index.ts`, `Source/package.json`). **`Chat` is exported through `@cratis/components/Canvas`** via the Kit barrel (`Source/Canvas/index.ts`, `Source/Chat/Kit/index.ts`). Prefer the non-spatial Chat subpath for ordinary host-data conversations; importing Canvas brings its Pixi edge.
@@ -0,0 +1,51 @@
1
+ <!-- Copyright (c) Cratis. All rights reserved. -->
2
+ <!-- Licensed under the MIT license. See LICENSE file in the project root for full license information. -->
3
+
4
+ # Query tables: server state, selection and pagination
5
+
6
+ Requires Components 4.35.1 for all table features described here, including serverQuery, filteredEmptyMessage, pageLinks and refreshed selection; check `yarn why @cratis/components`, or retain the older table API and host-owned filtering, pagination and selection reconciliation.
7
+
8
+ ## Server sorting and filtering are opt-in
9
+
10
+ `DataTableForQuery`, `DataTableForObservableQuery` and `DataPage` accept
11
+ `serverQuery`. Without it, sorting and filtering affect only the
12
+ loaded page, not the complete result set.
13
+
14
+ - Supply `toArguments` to translate search text and column filters to query
15
+ arguments. The backend must apply those arguments itself.
16
+ - Sorting uses Arc `sortBy`/`sortDirection`; `sortFields` maps column names to
17
+ server fields when necessary.
18
+ - Return `IQueryable` or use MongoDB `Observe` so sorting precedes paging.
19
+ - State changes return to page one; search is debounced by 300 ms by default.
20
+ Rows are rendered as the server returns them, not filtered a second time.
21
+
22
+ Do not present a page-local search as a complete-dataset search.
23
+ `filteredEmptyMessage` replaces `emptyMessage` when a search/filter has no rows.
24
+ Provider messages distinguish `filteredEmpty` (this page) from
25
+ `filteredEmptyServer` (server result). `onGlobalFilterChange` reports search text
26
+ as the user types; it does not implement backend search.
27
+
28
+ ## Query state and selection
29
+
30
+ With Arc and Arc React 22.122 or later, changing bound query arguments shows
31
+ loading instead of the previous arguments' rows, failure or access-denied state.
32
+ Returning to cached arguments avoids a loading flash. A completed
33
+ unsuccessful result is a failure, not an empty success; unauthorized stays access
34
+ denied. The query-bound chat sidebar also distinguishes these outcomes.
35
+
36
+ Bound tables and `DataPage` reconcile selection against refreshed
37
+ rows by `dataKey`, clearing it when the selected row disappears. A controlled
38
+ selection is reported through `onSelectionChange`, never forcibly overridden.
39
+ Use stable keys and exercise argument changes and removed selections in specs.
40
+
41
+ ## Pagination and localization
42
+
43
+ `pageLinks` is off by default. Set it to `true` or `{ siblings, boundaries }` on
44
+ `TablePaginator`, a bound table or `DataPage` for numbered links with ellipses.
45
+ The current button has `aria-current="page"`; the old page-count info is hidden.
46
+ The `pages`, `page`, `ellipsis` parts support styling; `page(n)` and `pages`
47
+ messages name the controls. Provider paginator messages or
48
+ `ariaLabels.range(start, end, total)` localize the range text too.
49
+
50
+ For a custom pager, `paginatorPages` and `PaginatorPageItem` export the same
51
+ windowing logic. Do not hard-code English accessible names in a localized host.
@@ -36,6 +36,7 @@ the controlled host applies and reports its own changes.
36
36
  | --- | --- |
37
37
  | `concepts: PropertyConcept[]` | Named types with a `PropertyType`; saved as `x-concept`. Overrides a surrounding `PropertyConceptsProvider` |
38
38
  | `allowRequired` | Toggle membership in the object's `required` names |
39
+ | `allowGeneratedProperty` | Boolean or per-property predicate; offers the `x-generated` toggle |
39
40
  | `allowKeyProperty` | Boolean or `(property, context) => boolean`; `x-key`, one per object |
40
41
  | `isPropertyProtected` | Prevent rename/removal, not every possible edit |
41
42
  | `validatePropertyName` | `(name, property, siblings) => string \| undefined`, after built-in checks |
@@ -60,3 +61,20 @@ The subpath exports `PropertyType`, `PropertyConceptsProvider`,
60
61
  Use the typed property-tree helpers for a controlled host, rather than treating
61
62
  `required` as a property boolean. Schema keywords are `x-concept`, `x-key`, and
62
63
  the parent object's `required: string[]`.
64
+
65
+ Requires Components 4.35.0 for generated-property preservation, schema keyword bags and unique identifiers; check `yarn why @cratis/components`, or retain the older tree contract.
66
+
67
+ Controlled hosts handle `onSetGeneratedProperty` and carry
68
+ `Property.isGenerated`, `vendorKeywords` and `itemVendorKeywords`; the exported
69
+ `GENERATED_KEYWORD` names `x-generated`. Without an offered toggle, including
70
+ read-only mode, generated properties show a marker styled through `generated`.
71
+ Also carry `schemaKeywords` and `itemSchemaKeywords` for unmodeled
72
+ standard JSON Schema keywords. Dropping these bags in a host loses constraints
73
+ and annotations even though the editor preserves them. Untouched properties now
74
+ round-trip their original shape and order; a type change drops only keywords
75
+ inapplicable to the new type (including old array-item annotations).
76
+
77
+ `PropertyType.UniqueIdentifier` writes a string with `format: uuid`
78
+ and reads either `uuid` or `guid`. Localize it with `typeUniqueIdentifier`.
79
+ `GlyphMenu` and `PropertyTypeGlyph` are exported for host-owned single-choice
80
+ type lists.
@@ -10,6 +10,17 @@ license: MIT
10
10
  user moves with Previous and Next; Submit appears on the last step once every
11
11
  field across every step is valid.
12
12
 
13
+ ## Dialog dismissal and refusal
14
+
15
+ Requires Components 4.36.0 for independent dismissal controls; check `yarn why @cratis/components`, or use the older `dismissable` contract.
16
+
17
+ `Dialog` and `CommandDialog` accept independent `dismissOnOutsideClick`,
18
+ `closeOnEscape` and `showCloseButton`; each falls back to `dismissable`. Busy
19
+ dialogs cannot be dismissed. The busy confirm remains focusable as
20
+ `aria-disabled` and ignores duplicate activation; a refused confirm restores
21
+ focus and announces the provider's `refused` message. Do not replace it with a
22
+ disabled button that loses focus or close the dialog on validation refusal.
23
+
13
24
  ## Verified product sources
14
25
 
15
26
  | Package | Verified from |
@@ -146,6 +146,19 @@ services.AddSingleton<IReportFormatters, ReportFormatters>();
146
146
  Search for every remaining reference before deleting, so nothing else was
147
147
  relying on a registration for a different reason.
148
148
 
149
+ ## Reuse derived-type discovery
150
+
151
+ Requires Fundamentals and its generator 7.26.1 for per-universe caching plus nested-generic/experimental-type generator fixes; check `dotnet list package`, or keep the older construction path until upgrading.
152
+
153
+ Use `Cratis.Serialization.DerivedTypes.For(types)` when several service
154
+ collections share the same `ITypes` instance. It returns one shared `DerivedTypes`
155
+ per universe, held weakly; distinct universes stay isolated. Do not construct one
156
+ per scope or replace a host's explicit universe with `DerivedTypes.Instance`.
157
+
158
+ The generator omits nested open-generic types from referenced Cratis packages
159
+ and handles referenced `[Experimental]` diagnostic IDs. Upgrade the generator
160
+ rather than editing its output to bypass those build failures.
161
+
149
162
  ## What breaks
150
163
 
151
164
  - **`[Singleton]` does not resolve.** The using directive is
@@ -11,32 +11,22 @@ license: MIT
11
11
 
12
12
  For services and kernel contributors using Orleans. This is library-consumer guidance, not the application vertical-slice architecture. For live Chronicle operations use **cratis-chronicle-cli-operations** instead. Co-hosting conventions are in [orleans.md](../../rules/orleans.md).
13
13
 
14
- ## Verified product sources
15
-
16
- All Orleans claims below come from `Cratis/Orleans` source.
17
-
18
- | Packages | Sources |
19
- | --- | --- |
20
- | `Cratis.Orleans`, `Cratis.Orleans.Storage` | `Source/Orleans/Jobs/{Job.cs,Job.Steps.cs,Job.Stages.cs,JobStep.cs,IJobsManager.cs,JobsOptions.cs}`; `Source/Orleans.Storage/Jobs/*` |
21
- | `Cratis.Orleans.Storage.MongoDB`, `Cratis.Orleans.Storage.Sql` | `Source/Orleans.Storage.MongoDB/{MongoDBJobsStorageOptions.cs,DatabaseNames.cs}`; `Source/Orleans.Storage.Sql/{SqlJobsStorage.cs,SqlJobsStorageOptions.cs,Jobs/Migrations/v1_0_0.cs}` |
22
- | `Cratis.Orleans.Chronicle` | `Source/Orleans.Chronicle/StateMachines/EventSourcedStateMachine.cs`; [state-machine reference](references/state-machines.md) |
23
-
24
- The API snippets cite their exact files and lines below. Product docs `Documentation/concepts/{jobs,storage-scopes,state-machines,event-sourced-state-machines}.md` supply the task vocabulary; source resolves contradictions.
25
-
26
14
  ## 1. Choose a job, not a detached task
27
15
 
28
- A job plans recoverable work; each step is a grain and does the work. Use it for work that must outlive a request. It is **at-least-once**, not exactly-once: a step interrupted before a durable checkpoint can perform the same work again. Protect external effects with receiver-owned idempotency/deduplication; a checkpoint does not atomically commit an external write (`JobStep.cs`, `JobsOptions.cs`).
16
+ A job plans recoverable work; each step is a grain and does the work. Use it for work that must outlive a request. It is **at-least-once**, not exactly-once: a step interrupted before a durable checkpoint can perform the same work again. Protect external effects with receiver-owned idempotency/deduplication; a checkpoint does not atomically commit an external write.
17
+
18
+ - Job: derive `Job<TRequest, TJobState>`; the request is a class implementing `IJobRequest`, the state derives `JobState`. Implement `PrepareSteps(TRequest)` returning `Task<IImmutableList<JobStepDetails>>`.
19
+ - Step: derive `JobStep<TRequest, TResult, TState>`; state derives `JobStepState`. Its constructor receives `[PersistentState(nameof(JobStepState), WellKnownGrainStorageProviders.JobSteps)] IPersistentState<TState>`, `IJobStepThrottle`, and `ILogger<JobStep<TRequest, TResult, TState>>`.
20
+ - Implement `PrepareStep(TRequest)` → `Task<Result<PrepareJobStepError>>`; `InitializeState(TRequest)` → `ValueTask`, called after preparation succeeds; and `PerformStep(TState, CancellationToken)` → `Task<Catch<JobStepResult>>`. `TResult` is the step's result type; the work method returns the framework's `JobStepResult` envelope, not `TResult` directly.
21
+ - Give the concrete job and step unique `[GrainType("product-specific-name")]` names. Use serializable request/state/result types. Do not reuse a class-derived grain name across assemblies.
29
22
 
30
- - Job: derive `Job<TRequest, TJobState>`; the request is a class implementing `IJobRequest`, the state derives `JobState` (`Job.cs`). Implement `PrepareSteps(TRequest)` returning `Task<IImmutableList<JobStepDetails>>` (`Job.Steps.cs`).
31
- - Step: derive `JobStep<TRequest, TResult, TState>`; state derives `JobStepState`. Its constructor receives `[PersistentState(nameof(JobStepState), WellKnownGrainStorageProviders.JobSteps)] IPersistentState<TState>`, `IJobStepThrottle`, and `ILogger<JobStep<TRequest, TResult, TState>>` (`JobStep.cs`).
32
- - Implement `PrepareStep(TRequest)` → `Task<Result<PrepareJobStepError>>`; `InitializeState(TRequest)` → `ValueTask`, called after preparation succeeds; and `PerformStep(TState, CancellationToken)` → `Task<Catch<JobStepResult>>` (`JobStep.cs`). `TResult` is the step's result type; the work method returns the framework's `JobStepResult` envelope, not `TResult` directly.
33
- - Give the concrete job and step unique `[GrainType("product-specific-name")]` names. Use serializable request/state/result types. Do not reuse a class-derived grain name across assemblies (`Jobs/JobsManager.cs`, `Documentation/how-to/host-the-silo.md`, and `orleans.md`).
23
+ `PerformStep` runs **outside the activation context** with a deep-copied state snapshot. Mutating that snapshot does not persist it; do not access/write grain `State` directly from background work. A specification host such as Orleans.TestKit must register `DeepCopier<TState>`.
34
24
 
35
- `PerformStep` runs **outside the activation context** with a state snapshot obtained through the grain reference. Mutating that snapshot does not persist it; do not access/write grain `State` directly from background work (`JobStep.cs`). Keep progress/state coordination on grain calls. Requires Cratis.Orleans 1.16.2 for framework-owned stop reporting; there, do not report cancellation again from a `PerformWork` override (`Documentation/concepts/jobs.md`).
25
+ Requires Cratis.Orleans 1.19.0 for `TryInvokeOnActivation` to coordinate state/checkpoints on the current activation, including during deactivation. Call it only from the run's background work. Keep callbacks local: capture copied inputs, call remote systems outside the callback, then commit in a second callback. Never call another grain, nest and await another callback, or start unawaited work inside it. Inspect `ActivationCallbackRejected` (`NoRun`, `StaleRun`, `Closed`, `Cancelled`); exceptions propagate. The optional `queueCancellationToken` cancels waiting callbacks only; started callbacks finish. Stop/deactivation waits for started callbacks and work to settle; `JobsOptions.StepStopTimeout` defaults to 10 seconds and `JobStepError.StopTimedOut` is not proof of quiescence. Requires 1.16.2 for framework-owned stop reporting: do not report cancellation again from a `PerformWork` override.
36
26
 
37
27
  ## 2. Plan dependencies as stages
38
28
 
39
- Default steps all use `JobStepStage.First`. Prefer independent fan-out. Use stages only when correctness requires earlier work to finish (`Job.Stages.cs`).
29
+ Default steps all use `JobStepStage.First`. Prefer independent fan-out. Use stages only when correctness requires earlier work to finish.
40
30
 
41
31
  Planning excerpt inside an existing `Job<RecoveryRequest, RecoveryState>`. It assumes `RecoveryRequest : IJobRequest`, `RecoveryState : JobState`, and the two existing grain interfaces `IRepairIndex` and `IRebuildCatalog`, each deriving a typed `IJobStep<,,>`:
42
32
 
@@ -52,64 +42,62 @@ protected override Task<IImmutableList<JobStepDetails>> PrepareSteps(RecoveryReq
52
42
  ]);
53
43
  ```
54
44
 
55
- Import `System.Collections.Immutable` and `Cratis.Orleans.Jobs` in that job file. `CreateStep<TStep>` takes the **grain interface**, not the implementation (`Job.Steps.cs`). Its stage overload accepts `JobStepStage`, with implicit integer conversion (`Source/Orleans.Storage/Jobs/Stages/JobStepStage.cs`).
45
+ Import `System.Collections.Immutable` and `Cratis.Orleans.Jobs` in that job file. `CreateStep<TStep>` takes the **grain interface**, not the implementation. Its stage overload accepts `JobStepStage`, with implicit integer conversion.
56
46
 
57
- Every step in a stage reaches an outcome before later stages start; steps within a stage run in parallel. All steps are prepared up front, so later-stage preparation cannot read the effects of earlier-stage execution. Read such dependencies in `PerformStep` (`Job.Stages.cs`).
47
+ Every step in a stage reaches an outcome before later stages start; steps within a stage run in parallel. All steps are prepared up front, so later-stage preparation cannot read the effects of earlier-stage execution. Read such dependencies in `PerformStep`.
58
48
 
59
- A failed stage stops the pipeline by default: later steps become `Unreachable`, and the job completes with failures. A best-effort stage may override `GetFailureBehaviorFor(JobStepStage)` to return `JobStageFailureBehavior.ContinueWithNextStage` (`Job.Stages.cs`, namespace `Cratis.Orleans.Jobs.Stages`). Do not silently continue when a later stage relies on the failed output.
49
+ A failed stage stops the pipeline by default: later steps become `Unreachable`, and the job completes with failures. A best-effort stage may override `GetFailureBehaviorFor(JobStepStage)` to return `JobStageFailureBehavior.ContinueWithNextStage` (namespace `Cratis.Orleans.Jobs.Stages`). Do not silently continue when a later stage relies on the failed output.
60
50
 
61
- ## 3. Start and resume through the scoped manager
51
+ Requires 1.25.0 for durable step plans: preparation requests must round-trip through the host's JSON options. Invalid plans return `StartJobError.InvalidStepPlan`. Recovery reuses identities and requests, prepares only unsaved steps, and never calls `PrepareSteps` again. Put retry-safe initialization needed before start **and** resume in `OnBeforeDispatchingJobSteps(JobStepDispatchContext)`, after the respective start/resume hook. `InitializationMayBeIncomplete` flags recovery from preparing/starting, not exactly-once initialization. A failed hook dispatches nothing; recovery never replays the start hook. A legacy preparing/starting job without a saved plan returns `CannotResumeJobError.MissingStepPlan` rather than inventing identities.
62
52
 
63
- `IGrainFactory.GetJobsManager(scope, namespace)` resolves the manager (`JobsManagerExtensions.cs`). `IJobsManager.Start<TJob,TRequest>(request)` returns `Result<JobId, StartJobError>`; inspect its error before telling a caller that a job started (`IJobsManager.cs`). Start success is not completed work; observe the job's status/outcomes.
53
+ ## 3. Start locally and recover every scope
64
54
 
65
- `IJobsManager.Resume(JobId)` returns **`Task<bool>`**. False means nothing took the job; do not wait for a completion callback as though resumption succeeded. True can mean resumed, already running, or finalized as completed (`IJobsManager.cs`). `Rehydrate()` completes after loading/preparing interrupted jobs, **before** its bounded background drain has resumed them all.
55
+ Requires 1.18.0 for the singleton local service `Cratis.Orleans.Jobs.IJobs`, registered by `AddCratisOrleans`. Prefer `Start<TJob,TRequest>(new JobKey(scope, namespace), request)` (or its explicit job-id overload), `Stop(key, jobId)` and `Delete(key, jobId)` during rolling upgrades. Generic `IJobsManager.Start`/`GetJobsOfType` send types through a manager that may run an older release and cannot decode them.
66
56
 
67
- `StartStepsInBackground` defaults to false. Overriding it to true makes Start return once the job is durable, moving step preparation/start to the grain's next turn. Later startup errors belong to the job, not the Start response (`Job.cs`).
57
+ Inspect `Result<JobId, StartJobError>` before telling a caller that work started. `FailedStartingSomeJobSteps` means remaining work is still running, not that nothing started; `AllJobStepsFailedStarting` means no step started. Start success is not completion. Match `StopJobResult`/`DeleteJobResult`: accepted, `NotFound`, `UnknownJobType`, or `Refused` with the job's error. Unknown types require a release that knows the type; exceptions propagate. Deletion acceptance is not completed removal. Third-party storage should override `IJobStorage.GetJobType` with a metadata-only read; its fallback reads the request too.
68
58
 
69
- ## 4. Know what storage retains
59
+ `IGrainFactory.GetJobsManager(scope, namespace)` remains available. `IJobsManager.Resume(JobId)` returns **`Task<bool>`**; false means nothing took the job: do not wait for a completion callback as though resumption succeeded. True may also mean already running or finalized. `IJobsManager.Stop` returns `Result<StopJobError>`; preserve a persistence refusal. `Rehydrate()` returns after loading/preparing interrupted jobs, before its bounded background drain resumes them all. `StartStepsInBackground = true` moves step preparation/start to the next turn after durability; later failures belong to the job, not Start.
70
60
 
71
- Successful jobs clear themselves by default; override `KeepAfterCompleted` to retain job state. Jobs completed with failures default to `KeepAfterCompletedWithFailures = true`, but retention cleanup still applies (`Job.cs`, `JobsOptions.cs`).
61
+ Requires 1.17.0 for automatic recovery on silo activation/member death. Provide singleton `IJobsManagerKeys` implementations on **every silo**, enumerating all host-owned scope/namespace pairs through `GetKeys(CancellationToken)`. The default remembers only keys used in this process: it is not a durable catalog. Providers run outside request scope; never inject a current tenant/user or scoped database. Requires 1.23.3 (1.24.2 for provider construction failures) for automatic recovery retries of failed providers/managers, from 1 second doubling to 60 seconds until success or silo shutdown. There is no periodic sweep by default. `AddCratisOrleans` registers recovery; separately configured silos need `AddCratisOrleansJobsRecovery()` (`Cratis.Orleans.Hosting`).
72
62
 
73
- **Keeping a job does not keep successful step state.** The step provider deletes successful/removing state, moves failed state to failed-step storage, and saves stopped/scheduled/running/unreachable state (`JobStepGrainStorageProvider.cs`). SQL keeps failed step rows with a failure status rather than a separate collection (`Source/Orleans.Storage.Sql/Jobs/JobStepStorage.cs`, `MoveToFailed`). Copy results the job must retain through `OnStepCompletedOrStopped(JobStepId, JobStepResult)` into job state (`Job.Steps.cs`); do not read deleted successful step state later.
63
+ Read [lifecycle and placement](references/lifecycle-and-placement.md) for drain/admission, bounded attempts, placement, custom storage compatibility and step test runs.
74
64
 
75
- Deliver external callbacks to a method on the **job's grain interface**, update job state there and persist it with `WriteState()`. Preserve the returned `Catch` failure; do not acknowledge input whose write failed (`Job.State.cs`, `WriteState`; `Documentation/concepts/jobs.md`). Step state is not a callback inbox: a concurrent callback can race the final write, and successful completion deletes it. A running step's snapshot will not see later job/step writes automatically.
65
+ ## 4. Know what storage retains
76
66
 
77
- ## 5. Register storage and budget concurrency
67
+ Successful jobs clear themselves by default; override `KeepAfterCompleted` to retain state. Jobs completed with failures default to `KeepAfterCompletedWithFailures = true`, but retention cleanup still applies.
68
+
69
+ Keeping a job does not keep successful step state: successful **steps delete their state**. Failed step state is retained. A durable callback receipt, deduplication set or result must live on the **job** (and be persisted), not only on a successful step. Deliver external callbacks to a method on the job's grain interface and preserve `WriteState()`'s `Catch` failure: do not acknowledge a failed write. Step state is not a callback inbox, and a running snapshot does not see later writes automatically.
78
70
 
79
- `IJobsStorage.GetFor(scope, namespace)` returns `JobsStorage`. Scope and namespace are opaque engine coordinates carried in grain keys; the host/provider owns their mapping (`Source/Orleans.Storage/Jobs/IJobsStorage.cs`, `Job.cs`). They are storage boundaries, not authorization checks.
71
+ ## 5. Register storage and budget concurrency
80
72
 
81
- Choose one storage registration alongside `AddCratisOrleans`:
73
+ `IJobsStorage.GetFor(scope, namespace)` returns `JobsStorage`. Scope and namespace are opaque host-owned storage coordinates, not authorization checks. Choose one storage registration alongside `AddCratisOrleans`:
82
74
 
83
75
  | Registration | Package / namespace | Use |
84
76
  | --- | --- | --- |
85
- | `AddCratisOrleansMongoDBJobsStorage` | `.Storage.MongoDB` / `Cratis.Orleans.Setup` | Durable MongoDB; database-name resolver can override the default `{scope}+jobs[+{namespace}]` |
86
- | `AddCratisOrleansSqlJobsStorage` | `.Storage.Sql` / `Cratis.Orleans.Setup` | Durable EF Core; `OptionsResolver(scope, namespace)` selects typed `DbContextOptions<JobsDbContext>` |
87
- | `AddCratisOrleansInMemoryJobsStorage` | `.Storage` / `Cratis.Orleans.Storage` | Specs/development only; process restart loses state |
88
-
89
- Evidence: each package's `*JobsStorageServiceCollectionExtensions.cs`; MongoDB `DatabaseNames.cs` and `MongoDBJobsStorageOptions.cs`; SQL `SqlJobsStorageOptions.cs`; in-memory `InMemory/InMemoryJobsStorage.cs`.
90
-
91
- ### SQL schema creation
77
+ | `AddCratisOrleansMongoDBJobsStorage` | `.Storage.MongoDB` / `Cratis.Orleans.Setup` | Durable MongoDB; default database `{scope}+jobs[+{namespace}]`, overridable |
78
+ | `AddCratisOrleansSqlJobsStorage` | `.Storage.Sql` / `Cratis.Orleans.Setup` | Durable EF Core; `OptionsResolver(scope, namespace)` selects `DbContextOptions<JobsDbContext>` |
79
+ | `AddCratisOrleansInMemoryJobsStorage` | `.Storage` / `Cratis.Orleans.Storage` | Specs/development; restart loses state |
92
80
 
93
- The product's SQL setup docs say to create the schema yourself. **the provider applies migrations automatically**: `SqlJobsStorage.GetFor` calls `EnsureSchema`, which calls `dbContext.Database.Migrate()` before constructing storage (`Source/Orleans.Storage.Sql/SqlJobsStorage.cs`). The migration is `Jobs/Migrations/v1_0_0.cs`; do not substitute `EnsureCreated` or hand-create those tables. The connection needs permissions to apply the migration, and scope-to-database mapping must be deliberate. Storage is cached per scope/namespace; `IJobsStorage.Reset()` clears the cache and the next resolution migrates again (`SqlJobsStorage.cs`). This resolves the documentation conflict from source, not from a release-note inference.
81
+ The SQL provider calls `dbContext.Database.Migrate()` automatically before constructing storage. Do not substitute `EnsureCreated` or hand-create tables; grant migration permissions and choose scope-to-database mapping deliberately. `IJobsStorage.Reset()` clears the cache; the next resolution migrates again. There is no MySQL/MariaDB jobs provider.
94
82
 
95
- Configure `JobsOptions` through the host's options registration. Its properties are **init-only**: supply a constructed instance via the options mechanism rather than assigning them in a `Configure(options => options.Property = …)` callback (`JobsOptions.cs`).
83
+ `JobsOptions` properties are **init-only**: supply a constructed instance through the host's options mechanism, not assignment in `Configure(options => …)`.
96
84
 
97
85
  | Option | Default | Purpose |
98
86
  | --- | --- | --- |
99
- | `MaxParallelSteps` | `max(1, ProcessorCount - 1)` when unset | Actual execution throttle |
100
- | `MaxConcurrentStepStarts` | `16` | Startup/resume calls per job, not the execution limit |
87
+ | `MaxParallelSteps` | `max(1, ProcessorCount - 1)` when unset | Execution throttle per silo |
88
+ | `MaxConcurrentStepStarts` | `16` | Startup/resume calls per job, not execution limit |
101
89
  | `MaxConcurrentRehydration` | `8` | Jobs resumed concurrently by a manager |
102
90
  | `MaxConcurrentCleanup` | `4` | Dead-job deletions |
103
- | `StepCheckpointBatchInterval` | `100` | Batches between durable progress checkpoints |
104
- | `StepCheckpointFlushInterval` | `5 seconds` | Timed checkpoint flush; nonpositive disables it |
105
- | `DeadJobThreshold`, `CleanupCadence` | `1 hour` each | Preparation-with-no-steps scavenging |
106
- | `TerminalJobRetention` | `7 days` | Terminal history retention; `Timeout.InfiniteTimeSpan` retains indefinitely |
91
+ | `StepCheckpointBatchInterval` | `100` | Batches between durable checkpoints |
92
+ | `StepCheckpointFlushInterval` | `5 seconds` | Timed flush; nonpositive disables it |
93
+ | `DeadJobThreshold`, `CleanupCadence` | `1 hour` each | Preparation-with-no-steps scavenging; saved plans are excluded |
94
+ | `TerminalJobRetention` | `7 days` | Terminal history; `Timeout.InfiniteTimeSpan` retains indefinitely |
107
95
  | `MaxTerminalJobsPerCleanup` | `100` | Bounded oldest-first cleanup page |
108
96
 
109
- Source: `JobsOptions.cs`. The three concurrency options for starts/rehydration/cleanup treat values below one as one. Retention does not delete preparing/running/stopped/removing jobs. Larger checkpoint intervals mean more post-crash redelivery, not higher delivery guarantees.
97
+ Concurrency values below one become one. Retention does not delete preparing/running/stopped/removing jobs. Larger checkpoint intervals increase post-crash redelivery, not delivery guarantees.
110
98
 
111
99
  ## State machines and verification
112
100
 
113
- Use [state-machines.md](references/state-machines.md) for `StateMachine<TStoredState>` and `EventSourcedStateMachine<TModel>`: jobs are recoverable work, state machines are lifecycle behavior. Neither makes external effects exactly-once.
101
+ Use [state-machines.md](references/state-machines.md) for `StateMachine<TStoredState>` and `EventSourcedStateMachine<TModel>`. Neither makes external effects exactly-once.
114
102
 
115
- Verify a new job with specs for planning, idempotent redelivery, stop/resume (including false), failed barriers/Unreachable, retention and persistence failures. Exercise the selected durable provider for restart recovery and SQL migration permissions. A build alone cannot establish crash recovery. Do not operate a live store merely to validate a code example.
103
+ Verify planning, invalid/missing saved plans, idempotent redelivery, stop/resume/refusal, failed barriers/Unreachable, retention and persistence failures. Exercise durable storage restart recovery and SQL migration permissions. A build alone cannot establish crash recovery. Do not operate a live store merely to validate an example.