@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
@@ -1,5 +1,11 @@
1
1
  # Query and decision scenarios
2
2
 
3
+ ## Contents
4
+
5
+ - Query pipeline
6
+ - Guarded decisions
7
+ - Sources
8
+
3
9
  <!-- Copyright (c) Cratis. All rights reserved. -->
4
10
  <!-- Licensed under the MIT license. See LICENSE file in the project root for full license information. -->
5
11
 
@@ -52,6 +58,13 @@ not a caller-supplied tenant filter. Compare whole returned items when the contr
52
58
  value; otherwise assert each named value. A query backed by a database still needs that provider's
53
59
  integration setup: scenario pins do not replace arbitrary stores.
54
60
 
61
+ `QueryScenario` owns and disposes its provider. Dispose the scenario (prefer
62
+ `DisposeAsync` for async-owned resources) as well as individual observations.
63
+ Register dependencies in `Services` before the first execution. Scenario
64
+ execution runs the query through Arc's hosted query pipeline and establishes context
65
+ before `Provide`/`Handle` on the command path. A direct static query call does not
66
+ cover those pipeline hooks.
67
+
55
68
  ## Guarded decisions
56
69
 
57
70
  Create `new CommandScenario<TCommand>()`. It selects Chronicle's in-process decision
@@ -87,6 +100,12 @@ read-model dictionary is the only backing are **legacy-mode** warnings, not a
87
100
  reason to fake protected decision readers. Keep non-key enumeration/provider
88
101
  boundaries explicit in either mode; decision mode is not a MongoDB substitute.
89
102
 
103
+ The default Chronicle-backed `CommandScenario` discovers constraints
104
+ automatically. Assert real constraint refusals instead of disabling them. Do not
105
+ subclass or substitute Chronicle's `EventScenario`; use its public
106
+ seeding/assertion surface or explicit `UseDecisionReads` mode, not a synthetic
107
+ EventScenario facade.
108
+
90
109
  ## Sources
91
110
 
92
111
  - [Query scenarios](https://github.com/Cratis/Arc/blob/main/Documentation/backend/csharp/testing/query-scenario.md)
@@ -179,6 +179,14 @@ filters, and system-execution.
179
179
  `Task<AuthenticationResult> HandleAuthentication(IHttpRequestContext context)`.
180
180
  Implement it and it is discovered — there is **no** `IArcBuilder` extension and
181
181
  **no** options type for authentication.
182
+ Requires Arc 22.139.0 for handlers to opt out of anonymous endpoints through
183
+ `AppliesToAnonymousEndpoints => false`. The default is `true`: existing handlers
184
+ keep running and may establish an identity even when no credential is required.
185
+ Opt out when a handler only rejects credentials and contributes no identity on
186
+ those endpoints. A handler that still runs can inspect the endpoint's anonymous
187
+ metadata and return `AuthenticationResult.Anonymous` instead of rejecting a
188
+ credential the endpoint never required. Specify anonymous and protected requests;
189
+ anonymous access does not bypass other authorization boundaries.
182
190
 
183
191
  Arc ships `MicrosoftIdentityPlatformAuthenticationHandler` in `Arc.Core`, which
184
192
  reads the forwarded principal. See
@@ -23,6 +23,32 @@ The headers are **not signed**. A backend cannot tell a request that came throug
23
23
 
24
24
  `IdentityVerification` on an AuthProxy service defaults to `Required` (fail closed). Only a `2xx` with `"isAuthorized": true` admits the caller. A `404`, an unreachable backend, a timeout (default ten seconds), any other non-`2xx`, an empty or unparseable body, a missing verdict, or `isAuthorized: false` all deny. The earlier `BestEffort` mode denied only on `403`. Consequently your `IProvideIdentityDetails` result is the admission verdict at the proxy, not only display data: return `IsUserAuthorized = false` deliberately, and keep the endpoint reachable and fast. A service can opt back into `BestEffort` explicitly; do not do that to hide a broken identity endpoint.
25
25
 
26
+ ## Multi-host sessions are opt-in
27
+
28
+ Requires AuthProxy 2.32.4 for the multi-host/crawler/invitation contract below; check the deployed version, or retain host-only sessions and the older error-page contract.
29
+
30
+ Defaults stay host-only with cookie name
31
+ `.Cratis.AuthProxy.Auth.v2`, per-host handshakes and relative return URLs.
32
+ `Session:CookieDomain` shares sessions beneath a parent domain;
33
+ `Session:CookieName` isolates independent deployments. `SignIn:CallbackHost`
34
+ centralizes OAuth/OIDC handshakes and requires the cookie domain. Restrict
35
+ `AllowedHosts`; never broaden hosts merely to make shared cookies work.
36
+
37
+ The callback and declared service hosts must lie inside the cookie domain;
38
+ `SubHost` tenant resolution cannot be combined with it. Absolute returns require
39
+ the callback host and an allowed origin inside that domain on the request's
40
+ scheme; otherwise they reduce to a local path. Invitations, credential links and
41
+ registration still start on their original host and need provider callbacks
42
+ there. Use the product's one-proxy/several-hosts migration guide, not an inferred
43
+ cross-domain cookie recipe.
44
+
45
+ `AuthProxy:SearchIndexing:Exclude` optionally serves anonymous
46
+ `robots.txt` and adds `X-Robots-Tag: noindex, nofollow`. It is off by default and
47
+ is a crawler policy, not authorization. Invitation error-page tokens
48
+ `{{invitedEmail}}` and `{{assertedEmail}}` are blank for addresses outside ASCII
49
+ letters, digits and `._+-@`; do not assume these placeholders always contain text.
50
+ Signed-in `/register` forwarding needs no host workaround.
51
+
26
52
  ## Tenants and services
27
53
 
28
54
  AuthProxy resolves the tenant through ordered strategies under `Cratis:AuthProxy:TenantResolutions` (`Host`, `Claim`, `Route`, `Specified`, `Default`, `SubHost`, `Selection`). The result reaches the backend as `x-cratis-tenant-id`, which is Arc's default tenant header, so an Arc application behind AuthProxy needs no tenancy configuration and the `UseHeaderTenancy("Tenant-ID")` workaround seen in older applications can be removed.
@@ -16,7 +16,7 @@ Reference the build package from the project that contains the commands,
16
16
  queries and read models, and set an output path:
17
17
 
18
18
  ```xml
19
- <PackageReference Include="Cratis.Arc.ProxyGenerator.Build" Version="22.75.0" />
19
+ <PackageReference Include="Cratis.Arc.ProxyGenerator.Build" Version="22.139.0" />
20
20
 
21
21
  <PropertyGroup>
22
22
  <CratisProxiesOutputPath>$(MSBuildThisFileDirectory)../<Web>/src/api</CratisProxiesOutputPath>
@@ -47,6 +47,8 @@ switches without a declared default are off when absent.
47
47
  | --- | --- | --- |
48
48
  | `CratisProxiesOutputPath` | empty | Where to write. Empty disables generation entirely |
49
49
  | `CratisProxiesInputAssembly` | empty | Overrides the assembly to read |
50
+ | `CratisProxiesIncremental` | `true` | Requires Arc 22.138.0; reuse unchanged owned output; set `false` to regenerate every build |
51
+ | `CratisProxiesFileHeader` | project setting | Requires Arc 22.123.0; otherwise uses `.editorconfig` `file_header_template`, or no header; `none` disables it |
50
52
  | `CratisProxiesSegmentsToSkip` | empty | Leading namespace segments to drop from the output path |
51
53
  | `CratisProxiesLibraryMode` | `false` | Generates for a library rather than an application |
52
54
  | `CratisProxiesSkipOutputDeletion` | **`true`** | Already the default — the generator does not wipe the output folder |
@@ -70,6 +72,13 @@ are optional. Sources:
70
72
  `Tools/ProxyGenerator.Build/build/Cratis.Arc.ProxyGenerator.Build.targets` under
71
73
  `Source/DotNET`.
72
74
 
75
+ Incremental generation fingerprints assemblies, generator/configuration, validation metadata
76
+ and owned output. A changed or missing generated file forces regeneration, as
77
+ does a previous warning so diagnostics remain visible. It does not make a
78
+ hand-edited generated file an input. Configure `file_header_template` explicitly
79
+ if you previously relied on the built-in Cratis MIT header; it is no longer
80
+ inserted without configuration.
81
+
73
82
  Item groups the target also forwards: `AssemblyToPackageMapping`,
74
83
  `ExcludeType`, `ExcludeNamespace`, `NamespaceRoot`, and `TypeToTsType`.
75
84
 
@@ -101,8 +101,9 @@ if (result.IsSuccess)
101
101
  }
102
102
  ```
103
103
 
104
- ⚠️ `Execute<TResult>` throws `InvalidCastException` when the handler returned a
105
- response of a different type. When the handler returns no response, or the
104
+ `Execute<TResult>` accepts an assignable response, such as an array requested
105
+ as `IEnumerable<T>` or a concrete value requested as an interface/base type.
106
+ ⚠️ An incompatible non-null response still throws `InvalidCastException`. When the handler returns no response, or the
106
107
  command failed for any reason, `Response` is `default` — a failed result never
107
108
  carries a response, because the pipeline clears it once the execution scopes
108
109
  have completed.
@@ -61,12 +61,13 @@ key where that service supports it; otherwise an external effect can repeat.
61
61
  Return events from the command, or use transactional appends. Do not complete a
62
62
  stream or commit an aggregate early inside the executor's command.
63
63
 
64
- An immediate append can commit **before** the executor detects it and reports
65
- `OccurrenceCommandAppendedImmediately`. No receipt is recorded for that failed
66
- attempt, so retry can duplicate the escaped append. The executor does not
67
- implicitly provide Chronicle's `RefuseImmediateAppends()` guard. Read
68
- **cratis-chronicle-client-dotnet**'s immediate-append refusal reference when
69
- building a custom boundary that needs prevention before transport.
64
+ Requires Arc 22.118.0 for the keyed executor to refuse immediate appends
65
+ **before transport**, with neither appended events nor an effect receipt. Arc
66
+ 22.117.x detected `OccurrenceCommandAppendedImmediately` only after an append
67
+ could escape; upgrade rather than treating that detection as retry safety.
68
+ Use `.Transactional` or returned events, and assert that a forbidden direct
69
+ append writes nothing. For a custom non-executor boundary, read
70
+ **cratis-chronicle-client-dotnet**'s immediate-append refusal reference.
70
71
 
71
72
  ## Verify
72
73
 
@@ -142,6 +142,11 @@ public class TransferFundsValidator : CommandValidator<TransferFunds>
142
142
  - A validator that itself throws does not become a 500 — Arc catches it and
143
143
  emits a validation error with reason `ValidatorFailed`, returning 400.
144
144
 
145
+ Read [protected validator construction](references/protected-validator-construction.md)
146
+ for plain read-model constructor inputs under `On`, the separate untrimmed-JIT
147
+ provider opt-in for decision tokens outside `On`, and generated composite-key
148
+ metadata. Do not conflate metadata coverage with validator certification.
149
+
145
150
  ## Step 4 — Data the handler needs: `Provide()`
146
151
 
147
152
  `Provide()` runs after authorization and validation and before `Handle()`. Its
@@ -15,6 +15,14 @@ with `DateTime command property '<member>' requires an explicit offset or Z.`
15
15
  `DateTimeOffset` retains the input offset; `DateTime` becomes UTC. The attribute
16
16
  is in `Cratis.Arc.Commands`.
17
17
 
18
+ Requires Arc 22.120.0 for concepts over `DateTime` or `DateTimeOffset` with
19
+ Arc's default JSON options. Concepts over `DateOnly` are refused as a
20
+ configuration error: calendar dates have no offset. The marker affects
21
+ JSON-bound properties, including nested collection elements, not query strings
22
+ or route scalars. Use reflection-based JSON metadata for these properties;
23
+ System.Text.Json source-generated metadata does not support derived
24
+ `JsonConverterAttribute` markers.
25
+
18
26
  ## Malformed bodies still authorize
19
27
 
20
28
  Requires Arc 22.110.0 for authorization-before-binding-failure handling on
@@ -31,6 +39,15 @@ policies can run; built-in role, claim, name and authenticated-user requirements
31
39
  are already resource-free. Do not mark a requirement resource-free if it reads
32
40
  the command.
33
41
 
42
+ ## Annotations on concepts
43
+
44
+ Requires Arc 22.121.2 for data annotations on command properties and model-bound
45
+ query parameters to validate a concept's wrapped value: `[Required]` rejects an
46
+ empty wrapped string, `[Range]` checks the primitive, and `[StringLength]` does
47
+ not throw on the wrapper. This uses generated validation metadata; types without
48
+ that metadata (including external assemblies) keep the previous behavior. Do
49
+ not assume annotations replace a concept's reusable validator.
50
+
34
51
  ## Validation members are field paths
35
52
 
36
53
  Requires Arc 22.115.0 for **all** `ValidationResult.Members` paths to be
@@ -0,0 +1,94 @@
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
+ # Protected validator construction and key metadata
5
+
6
+ ## Plain read models under On
7
+
8
+ Requires Arc 22.106.0 for plain Chronicle read-model dependencies in
9
+ `CommandValidator<T>` constructors under read protection `On`. Those reads share
10
+ the command's fold cache and append guard with `Provide`/`Handle`. Let convention
11
+ discovery register a transient validator. Scoped/singleton/factory/instance
12
+ registrations are refused; a plain transient self-binding is also allowed.
13
+ Ineligible construction fails closed; never fall back to unguarded reads. Use
14
+ `[LookUpBy(nameof(Command.Property))]` on each constructor read for multiple
15
+ keys. Another source/stream can instead be read explicitly in `Provide`.
16
+
17
+ ## Explicit decision tokens outside On
18
+
19
+ Requires Arc 22.126.0 for the opt-in construction of validators taking
20
+ `DecisionRead<T>` or command-aware `IDecisionReads` on `[ProtectedDecision]`
21
+ commands outside `On`. This is **untrimmed JIT only**, not trimmed JIT or
22
+ NativeAOT, and not a switch making every DI container trusted.
23
+
24
+ Install `ProtectedDecisionServiceProviderFactory` from
25
+ `Cratis.Arc.DependencyInjection` as the host's actual Microsoft DI factory
26
+ **after** `AddCratisArc`, passing the desired `ServiceProviderOptions` explicitly.
27
+ Without them both `ValidateScopes` and `ValidateOnBuild` default to false; host
28
+ Development settings are not inherited. `BuildProtectedDecisionServiceProvider`
29
+ is for independently owned service collections, not a second root inside the
30
+ running host. Execute in a native child scope (or the pipeline's scope-owning
31
+ overload), never directly on that root. Default `CommandScenario` does not opt in.
32
+
33
+ Register Chronicle through Arc's `WithChronicle`. Do not replace readers or
34
+ re-register tokens. Arc records origins at root construction; copied descriptors,
35
+ a wrapper provider, custom container or later collection mutation cannot acquire
36
+ that evidence.
37
+
38
+ Every validator/collaborator needs exactly one public constructor and a fully
39
+ inspectable transient graph. Arc constructs fresh instances for the invocation.
40
+ It refuses scoped/singleton validators or collaborators, application validator
41
+ bindings, factory/instance dependencies, cycles, keyed/open generic/deferred or
42
+ optional dependencies, provider/scope accessors and collections (including token
43
+ collections). Plain models and raw `IReadModels`, `IEventStore` or `IEventLog`
44
+ are refused on this path: use tokens or choose `On`.
45
+
46
+ Requires Arc 22.126.0 for
47
+ `services.AddProtectedDecisionValidator<TValidator>(configure)`. Use it instead
48
+ of an application DI factory when adding rules. The callback runs once on the
49
+ actual fresh instance before validation; thrown callbacks fail the command and
50
+ callback denials are not bypassed. It can replace one Arc convention binding,
51
+ not an explicit application registration. Extra explicit bindings refuse the
52
+ protected path. Ordinary commands still use normal constructor resolution.
53
+
54
+ Arc checks rule/component identities before invocation and refuses changed or
55
+ cross-scope/reused instances. Construction and cleanup failures block before
56
+ commit even with allowed-severity overrides. Arc disposes owned validators and
57
+ collaborators in reverse order; DI owns read leaves. This is not a sandbox for
58
+ trusted constructor/callback code, mutable captures, static reads or nested-child
59
+ rule changes. `Validate` stays advisory and creates a separate invocation; only
60
+ Execute enrolls its decision for append-time checking. Under `Off`, choose the
61
+ blocking severity needed for business denials.
62
+
63
+ ## Generated key metadata is not validator certification
64
+
65
+ `CommandReadModelKeys` registers command property/model-key metadata.
66
+ Requires Arc 22.125.0 for generated composite-key descriptors and
67
+ `ProtectedReadModelKeyAccessors`, which registers exact-type composite members.
68
+ These optimize matching; they do not authorize a read or certify a validator's
69
+ dependency graph.
70
+
71
+ Known concrete composite keys receive generated complete descriptors. For an
72
+ external/runtime key, register `ProtectedReadModelKeyAccessors.Register<T>` with
73
+ every public readable non-indexed instance property, including inherited ones,
74
+ before commands run. Generated metadata uses `DeclareKeyTypes` for startup
75
+ coverage checks; that is not a replacement for registering member accessors.
76
+ Duplicate registration fails. Do not omit a member or treat a
77
+ base descriptor as covering a derived runtime type. Missing declared metadata
78
+ fails with `ProtectedReadModelKeyAccessorMissing`.
79
+
80
+ Requires Arc 22.134.0 for `ReadProtection:RequireGeneratedMetadata` (false by
81
+ default). Enabling it rejects missing command/model metadata instead of using
82
+ reflection. `ProtectedReadModelKeyOptions.Strict` is also false by default;
83
+ strict composite matching or a restricted runtime requires exact accessors.
84
+ Untrimmed JIT can use the compatibility reflection path when strict mode is off.
85
+ ARC0030 is the composite coverage warning. Do not suppress it or promise
86
+ NativeAOT support for the unrelated dynamic validator opt-in.
87
+
88
+ ## Specify the boundary
89
+
90
+ Cover a fresh allowed/denied validator, callback-added denial and exception,
91
+ refused DI graphs and cleanup failure, and repeated validation/execution without
92
+ reusing an instance. For keys, cover inherited/flattened members, exact derived
93
+ types, missing metadata under strict settings and generated versus compatibility
94
+ matching. An advisory Validate success is not proof that Execute commits.
@@ -187,6 +187,24 @@ Mark the corresponding property `[Json]`.
187
187
  `migrationBuilder.GetDatabaseType()` is available when a migration genuinely has
188
188
  to branch per provider.
189
189
 
190
+ ## Tracked and native upserts
191
+
192
+ Requires Arc 22.135.0 for `DbSet<TEntity>.UpsertAsync(item, cancellationToken)`.
193
+ On supported SQL Server, PostgreSQL and SQLite mappings it executes an immediate,
194
+ parameterized native upsert matching the complete primary key, including composite
195
+ keys and value converters. Native key matching and writing are atomic. It uses
196
+ the context's connection/current transaction, bypasses tracking and does not
197
+ refresh generated values or already tracked instances. It adds no retry policy.
198
+
199
+ Use application-assigned keys and single-table scalar mappings. Unsupported
200
+ providers or mappings (including unset generated keys, SQL Server identity
201
+ columns, navigations, owned entities, shadow properties, inheritance and multiple
202
+ tables) fall back to tracked persistence and require `SaveChangesAsync`. The
203
+ existing `Upsert(item)` always uses tracked read-then-write persistence and also
204
+ requires saving; that path is not an atomic database upsert. Choose it explicitly
205
+ when deferred persistence is required. Do not rely on fallback for concurrency
206
+ protection or assume the native path flushes pending tracked changes.
207
+
190
208
  ## Observing an EF Core read model
191
209
 
192
210
  `DbSet<T>` gains `Observe(filter?, configure?)`, `ObserveSingle(filter?, configure?)`
@@ -56,10 +56,12 @@ Sources: `Arc.Core/Queries/QueryStringQueryRequestReader.cs`,
56
56
 
57
57
  ## Which return shapes page
58
58
 
59
- A query is an eligible public or internal static method on the `[ReadModel]`
60
- type, discovered by its return type. Internal visibility does not hide an
61
- endpoint; keep helpers outside that type. Read **cratis-chronicle-read-model**'s
62
- query reference for explicit `[Query]` discovery and older-version limits.
59
+ A query is an eligible public static method on the `[ReadModel]` type,
60
+ discovered by its return type.
61
+ Requires Arc 22.121.0 for non-public statics to be
62
+ excluded even with `[Query]` (ARC0029 warns); older Arc exposes internal methods
63
+ as endpoints too. Read **cratis-chronicle-read-model**'s query reference for
64
+ explicit `[Query]` discovery and older-version limits.
63
65
 
64
66
  | Return | Paged? | How |
65
67
  | --- | --- | --- |
@@ -174,6 +176,11 @@ For composed MongoDB/EF observations, pass `ignoreQueryContext: true` to
174
176
  auxiliary sources so only the primary consumes client paging/sorting and writes
175
177
  totals. Single-instance observations emit `default` when absent, deleted or
176
178
  outside the filter; guard `hasData`/`isReady` in React.
179
+ Requires Arc 22.117.1 for
180
+ `ObserveSingle`/`ObserveById` never to page or count; their retained
181
+ `ignoreQueryContext` argument has no effect. Use collection results for paging.
182
+ Read [live query processing](references/live-query-processing.md) for shared
183
+ MongoDB watches, emitted-value interception and calendar-bound answers.
177
184
  Source: [MongoDB observations](https://github.com/Cratis/Arc/blob/main/Documentation/backend/csharp/mongodb/observing-collections.md).
178
185
 
179
186
  ## Consume it from the frontend
@@ -0,0 +1,71 @@
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
+ # Live query processing
5
+
6
+ ## Shared MongoDB watches
7
+
8
+ Requires Arc 22.136.0. MongoDB `Observe()` uses a shared database-level watch keyed by deployment and
9
+ database rather than opening a collection watch for every observer. Each
10
+ observation keeps its filter, paging and tenant context.
11
+ Requires Arc 22.137.0 for observations of collections created by the caller's
12
+ own `MongoClient` to receive changes. The watcher derives the deployment key
13
+ from the database client instead of requiring prior registration. Joined observations coalesce refresh notifications into one pending
14
+ refresh and re-read every joined source. Snapshot read failures receive a
15
+ bounded retry burst; exhaustion waits for a later notification rather than
16
+ spinning or buffering unbounded work.
17
+
18
+ Watch reconnects resume from the token when possible and request a new snapshot
19
+ when the token cannot resume. The watch reopens before asking for snapshots so
20
+ writes during the read are still observed. Disposing one observer does not stop
21
+ the shared watch; disposing its subject or losing the last subscriber stops that
22
+ observation's refresh work and prevents a late emission. Shared watches do not
23
+ replace each subscription's cancellation and disposal.
24
+
25
+ ## Intercept the emitted model, not its wrapper
26
+
27
+ Implement `Cratis.Arc.Queries.IInterceptReadModel<T>` with
28
+ `Task<T> Intercept(T readModel)`. Return a copy when transforming data that another
29
+ subscriber could share. A non-abstract open generic `IInterceptReadModel<T>`
30
+ implementation must target exactly its own type parameter; closed
31
+ implementations also work.
32
+
33
+ Interception runs for supported direct/hub streaming emissions and observable
34
+ HTTP snapshot/wait results in the requesting subscriber's scope and identity. Interceptors run before emission guards; a thrown interceptor
35
+ fails the result rather than exposing the untransformed value. Ordinary model
36
+ queries and Arc-wrapped MVC GETs also intercept results; `[AspNetResult]` opts
37
+ out of that result processing. Interceptors are transformations, **not access
38
+ control**. Filter rows/fields and authorize independently on every exposed path,
39
+ and specify snapshot, SSE/WebSocket and hub paths separately.
40
+
41
+ ## Date-sensitive answers without data changes
42
+
43
+ Requires Arc 22.138.0 for `Cratis.Arc.Calendar`. Inject `IApplicationCalendar` and
44
+ pass an instant to `Read`; it does not read the clock. Zone precedence is an
45
+ operation-declared zone, then the first non-null `ICanProvideTenantCalendar`
46
+ answer, then `Cratis:Arc:Calendar:TimeZone` (default `UTC`). Headers and query
47
+ arguments cannot choose it. Configured and tenant-provider ids must be usable
48
+ IANA ids: unknown, Windows-only and nonzero fixed-offset ids fail with
49
+ `TimeZoneIsNotAnIanaZone`,
50
+ never a silent UTC fallback. Containers need time-zone data (`tzdata`).
51
+
52
+ A live "due today" answer needs candidates observed **without a clock-dependent
53
+ store filter**, or tomorrow's members will never enter the source. Use
54
+ `IClockBoundaries.Begin(tenant, operationZone, token)` to obtain a
55
+ `ClockBoundaryContext`, then `candidates.ReevaluateAtBoundaries(context,
56
+ (candidates, reading) => new ClockEvaluation<TAnswer>(answer, nextBoundary))`.
57
+ `LocalDateChanges.NextLocalDateChange(reading.Zone, reading.Instant)` handles
58
+ midnight, skipped dates and backwards date transitions. `reading.Today.AddDays`
59
+ steps calendar days; subtracting elapsed hours from the instant is different
60
+ across daylight-saving changes.
61
+
62
+ Every next boundary must be strictly after the evaluated instant or null;
63
+ otherwise the stream fails with `ClockBoundaryIsNotInTheFuture`. The first result
64
+ always emits; equal subsequent answers do not (collections compare in order).
65
+ Evaluation is serialized in the context's tenant. The zone is fixed at Begin;
66
+ application changes require restart and tenant-zone changes affect new
67
+ subscriptions. The operator connects on first subscription and disposes timer
68
+ and candidates on last unsubscribe, cancellation, error or completion. It does
69
+ not accept `OnNext`. Use the registered `TimeProvider` and a `FakeTimeProvider`
70
+ with `Advance` to specify boundary changes without sleeps. This is not a
71
+ continuously ticking `now` or an advanceable clock in query scenarios.
@@ -45,6 +45,17 @@ import { Dialog } from '@cratis/components/Dialogs';
45
45
  import { DialogProps, DialogResult, useDialog } from '@cratis/arc.react/dialogs';
46
46
  ```
47
47
 
48
+ ## Guid command fields
49
+
50
+ Requires Components 4.31.0 and matching Arc/Arc React 22.19.1 for GuidField invalid-draft execution blocking; check `yarn why @cratis/components` and `yarn why @cratis/arc.react`, or keep a host-validated field.
51
+
52
+ Opt into `GuidField` from `@cratis/components/CommandForm`. It binds native
53
+ Fundamentals `Guid` values, accepts partial text drafts and never generates an
54
+ identifier. Register it once through `registerFieldTypeProvider` for
55
+ `AutoCommandForm`; it is not a built-in provider. Invalid drafts clear the bound
56
+ value. Preserve host-set errors and use `resetKey` to discard an unchanged empty
57
+ value's draft.
58
+
48
59
  ## Initial focus
49
60
 
50
61
  `DialogInitialFocus.Confirm` is the default and arms the confirm button, so a destructive dialog uses `DialogInitialFocus.Cancel`. Read [dialogs.md](references/dialogs.md) for the three options.
@@ -183,6 +183,21 @@ when omission is invalid for the selected query.
183
183
 
184
184
  ### `ConceptValidator<TConcept>`
185
185
 
186
+ Requires Arc.Kotlin 7.8.0 for shared Fundamentals concepts and their validators; check `./gradlew dependencies`, or retain the legacy Arc concepts and validators until upgrading.
187
+
188
+ Prefer `io.cratis.fundamentals.concepts.ConceptAs` for new concepts and
189
+ `FundamentalsConceptValidator<TConcept>` for their rules. It implements
190
+ `ModelValidator<TConcept>` and exposes `conceptType` plus
191
+ `validate(concept): List<ValidationResult>`; read the primitive via `value()`.
192
+ JSON, validation, proxy generation, Spring conversion, Chronicle bridging and
193
+ testing recognize the shared concept type. The old Arc `ConceptAs` extends it
194
+ and is deprecated, as is `ArcCamelCase` (use Fundamentals `toCamelCase`).
195
+ Existing Arc concepts/validators keep compiling and linking unchanged.
196
+
197
+ The legacy Arc concept example below remains valid with `ConceptValidator` and
198
+ its `value` property; do not copy that property shape to a new Fundamentals-only
199
+ concept, whose interface method is `value()`.
200
+
186
201
  A reusable invariant on a `ConceptAs<T>` concept type, walked automatically
187
202
  wherever that concept type appears — command, nested model, collection,
188
203
  array, or map — without each owner repeating the rule. Matching uses
@@ -206,9 +221,11 @@ Jakarta `Validator` bean. Exclude one direct edge deliberately with
206
221
  Java record component/field) whose *declared* type implements `ConceptAs`. A
207
222
  scalar root, a collection element, or a nested path cannot be excluded this
208
223
  way — register the nested owner type and its direct member instead. Excluding
209
- an edge suppresses only `ConceptValidator` execution there; owner rules, exact
210
- `ModelValidator` rules, Jakarta constraints, and root typed validators still
211
- run.
224
+ an edge suppresses concept-rule execution there, including
225
+ `FundamentalsConceptValidator`; owner rules, exact `ModelValidator` rules,
226
+ Jakarta constraints, and root typed validators still run.
227
+
228
+ Requires Arc.Kotlin 7.8.1 for exclusions to suppress FundamentalsConceptValidator; check `./gradlew dependencies`, or upgrade before relying on a shared-concept exclusion.
212
229
 
213
230
  ### `ModelValidator<T>`
214
231
 
@@ -60,6 +60,10 @@ Two things worth knowing before running it:
60
60
  connection guidance in a repository-owned project context file; never patch
61
61
  packaged or generated bytes.
62
62
 
63
+ Read [project tooling](references/project-tooling.md) for embedded release notes,
64
+ cached templates, managed MCP registration and install-only versus harness AI
65
+ conformance checks. Updating instructions does not run those behavior checks.
66
+
63
67
  ## Reach the right server
64
68
 
65
69
  The connection string resolves in this exact order:
@@ -180,6 +184,10 @@ needs Chronicle 19.29.0 or later, resets the retry budget and retries unless `--
180
184
  is given; handler side effects may repeat. `retry-partition` exits non-zero
181
185
  when quarantined or not failed. `jobs resume` resumes Stopped jobs, not Failed.
182
186
 
187
+ Read [recovery outcomes and namespace comparison](references/recovery-and-comparison.md)
188
+ for refusal-aware job actions, retained-job deletion, observer-wide failed-partition
189
+ recovery, exact manual stream reopening and bounded metadata comparison.
190
+
183
191
  ## Before you change anything
184
192
 
185
193
  Default to read-only inspection. A request to diagnose a live store does not
@@ -188,12 +196,13 @@ authorize replay, retry, removal, quarantine clearing, or another mutation.
188
196
  These commands mutate the running store:
189
197
 
190
198
  - `chronicle observers replay`, `replay-partition`, `retry-partition`,
191
- `clear-quarantine`
199
+ `retry-failed-partitions`, `clear-quarantine`
192
200
  - `chronicle observers remove` — destructive across every namespace of the event
193
201
  store: definition, state, handled counts, failures and projection definition;
194
202
  read model data stays. Refused while running or subscribed, no force flag.
195
203
  - `chronicle observers clear-partition-quarantine` — may retry the handler
196
- - `chronicle jobs stop`, `chronicle jobs resume`
204
+ - `chronicle jobs stop`, `chronicle jobs resume`, `chronicle jobs delete`
205
+ - `chronicle streams closed reopen` — exact manual scope repair with a reason
197
206
  - `chronicle recommendations perform`, `chronicle recommendations ignore`
198
207
  - `chronicle subscriptions add`, `chronicle subscriptions remove`
199
208
  - `chronicle users add`, `chronicle users remove`
@@ -20,6 +20,7 @@ non-read-only commands.
20
20
  | `workbench` | destructive | false (its actions have their own dialogs) |
21
21
  | `applications add` | mutating | false |
22
22
  | `applications remove` | destructive | true |
23
+ | `jobs delete` | destructive | true |
23
24
  | `jobs resume` | mutating | true |
24
25
  | `jobs stop` | mutating | true |
25
26
  | `observers clear-partition-quarantine` | mutating | true |
@@ -27,14 +28,20 @@ non-read-only commands.
27
28
  | `observers remove` | destructive | true |
28
29
  | `observers replay` | destructive | true |
29
30
  | `observers replay-partition` | destructive | true |
31
+ | `observers retry-failed-partitions` | mutating | true |
30
32
  | `observers retry-partition` | mutating | true |
31
33
  | `recommendations ignore` | mutating | true |
32
34
  | `recommendations perform` | destructive | true |
35
+ | `streams closed reopen` | mutating | true |
33
36
  | `subscriptions add` | mutating | false |
34
37
  | `subscriptions remove` | destructive | true |
35
38
  | `users add` | mutating | false |
36
39
  | `users remove` | destructive | true |
37
40
 
41
+ See [recovery outcomes](recovery-and-comparison.md) for CLI/server floors and
42
+ acceptance versus completed work. `jobs delete` exits nonzero on declined/unavailable
43
+ confirmation; success means deletion requested, not completed removal.
44
+
38
45
  The remaining Chronicle commands are cataloged read-only, including
39
46
  `report-error`; the guard deliberately blocks that command because it opens an
40
47
  external browser issue form. `chronicle version` is not a command in this
@@ -0,0 +1,91 @@
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
+ # CLI updates and project tooling
5
+
6
+ This complements live-store operations; it does not grant permission to install
7
+ servers, change a repository or run quota-consuming agent sessions. Inspect the
8
+ installed version with `cratis --version` and its catalog before using a flag.
9
+
10
+ ## Inspect the upgrade, not a remembered bundle
11
+
12
+ Requires CLI 3.87.0 for offline embedded release notes:
13
+
14
+ ```bash
15
+ cratis release-notes --since <version> -o json
16
+ cratis release-notes --version <version>
17
+ ```
18
+
19
+ `cratis update` displays the skipped releases after its update results. Requires
20
+ 3.89.0 for `cratis new` to use the template set cached at `~/.cratis/templates`:
21
+ first use downloads from NuGet; offline use can reuse a complete cached set.
22
+ `cratis new cratis --language csharp --version <version>` selects a version for
23
+ one run rather than replacing the installed choice. `cratis update` refreshes
24
+ compatible templates without downgrading or failing the CLI update when refresh
25
+ fails; `--no-templates` skips it. CLI and template versions are separate. Do not
26
+ silently enable scaffold scripts; preserve the template's `--allow-scripts`
27
+ choice. Multi-service orchestration still needs explicit per-store settings.
28
+
29
+ For `cratis render` / `run`, read **cratis-screenplay-render-and-gap-fill** and
30
+ **cratis-stage-rendering-and-sandbox**. Their bundled renderer determines support;
31
+ a CLI upgrade can change admission, generated output and the default container
32
+ without changing the model. Never infer support from the ESM version alone or
33
+ edit generated output to make an older CLI accept it.
34
+
35
+ ## Managed AI installation and MCP
36
+
37
+ Requires CLI 3.77.1 for `.pi/agents` to link to Pi-native corpus adapters when
38
+ available, falling back to canonical agents only for older corpora. Do not
39
+ hand-edit generated adapters to restore missing tools; update the CLI/corpus.
40
+
41
+ Requires 3.90.0 for profile-selected servers in the corpus's `mcp-servers.json` to
42
+ be registered by `cratis ai install` / `update` in Claude Code, Copilot, Cursor,
43
+ Codex and OpenCode. Installation registers configuration; it does not start the
44
+ servers. Deselecting/uninstalling removes only unchanged owned entries. Foreign
45
+ or modified entries remain conflicts, even with force. Resolve a conflict by
46
+ intentionally renaming/removing your entry or disabling that server with
47
+ `mcpServers.<id>.enabled = false` in the project configuration; do not overwrite
48
+ it speculatively. Pi supports only Screenplay through its native extension and
49
+ reports other servers unsupported. An invalid selected descriptor is reported
50
+ and skipped; successful guidance installation does not prove MCP availability.
51
+ Installing a server does not authorize its tools or commands.
52
+
53
+ ## Deterministic AI checks versus harness behavior
54
+
55
+ Requires CLI 3.98.0 for opt-in `cratis ai test`. Each fixture × harness uses a
56
+ fresh temporary workspace with the fixture's selected profiles/languages; the
57
+ invoking repository is unchanged. It is **not** a security sandbox: fixture
58
+ commands and harnesses still have host tools/authentication. Trust the source,
59
+ request the intended session/budget, and keep transcripts off unless needed.
60
+ The default fixture root is `Evaluations/conformance`; `--fixtures` overrides
61
+ it, `--fixture` selects names, and `--harnesses claude,codex` narrows adapters.
62
+ `--output json` is this command's structured format, not proof of a passing run.
63
+
64
+ Requires 3.100.0 for install-only CI without a harness, credentials or model quota:
65
+
66
+ ```bash
67
+ cratis ai test --source <corpus> --install-only --output json
68
+ ```
69
+
70
+ This runs install-phase checks for declared harness ids (or the configured ids
71
+ when a fixture declares none), narrowed by `--harnesses`. Result-phase checks
72
+ stay `not_run`; no install checks means skipped, not behavioral conformance.
73
+ Normal mode rejects missing/modified installations unless corpus-source mode is
74
+ selected. `--source`/`CRATIS_AI_SOURCE` selects a trusted local corpus.
75
+
76
+ Fixtures require a non-optional result check even in install-only mode. File
77
+ checks choose one path/glob; an empty glob match fails. Install checks cannot be
78
+ commands. A result command uses `run: ["executable", "argument"]` with no implicit
79
+ shell and cannot also declare file path/glob/pattern fields. Invalid check shapes
80
+ are errors. Paths and links cannot escape the workspace.
81
+
82
+ A timeout kills the process tree; output is capped. Requested `--timeout` and
83
+ `--max-budget-usd` can lower, not raise, fixture limits. Claude enforces a spending
84
+ limit; Codex reports that bound `not_enforced`. Missing harnesses/credentials are
85
+ skipped with a reason, never passed. Exit 0 can mean all skipped or no selected
86
+ runs: inspect counts and `no fixtures ran successfully`. Exit 1 means fixture,
87
+ harness or check failures/errors; exit 2 means usage/install errors. Installed
88
+ file hashes, observed tool reads and check results are separate evidence levels;
89
+ unknown reads remain unknown. `--keep-transcripts` retains best-effort-redacted
90
+ temporary output; inspect it for secrets before sharing. Passing install checks
91
+ is not proof that an agent read or obeyed the guidance.