@cratis/pi 7.34.0 → 7.35.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 (241) hide show
  1. package/package/corpus/agents/security-reviewer.md +1 -0
  2. package/package/corpus/agents/spec-writer.md +1 -1
  3. package/package/corpus/harnesses/pi/extensions/shared/rules.ts +3 -1
  4. package/package/corpus/hooks/scripts/cratis-nuget-pins.txt +7 -6
  5. package/package/corpus/hooks/scripts/cratis-release-notes-reviewed.cjs +7 -6
  6. package/package/corpus/hooks/scripts/cratis-store-mutations.json +7 -3
  7. package/package/corpus/product-sync.json +896 -0
  8. package/package/corpus/prompts/add-business-rule.prompt.md +1 -1
  9. package/package/corpus/prompts/ship-changes.prompt.md +2 -2
  10. package/package/corpus/rules/ai-distribution.md +31 -3
  11. package/package/corpus/rules/application-profile.md +2 -1
  12. package/package/corpus/rules/components.md +66 -7
  13. package/package/corpus/rules/concepts.md +11 -3
  14. package/package/corpus/rules/csharp.md +3 -1
  15. package/package/corpus/rules/dialogs.md +9 -0
  16. package/package/corpus/rules/efcore.md +1 -1
  17. package/package/corpus/rules/elixir.md +49 -0
  18. package/package/corpus/rules/framework.md +5 -3
  19. package/package/corpus/rules/general.md +1 -0
  20. package/package/corpus/rules/glossary.md +4 -4
  21. package/package/corpus/rules/go-engineering.md +60 -0
  22. package/package/corpus/rules/go.md +115 -0
  23. package/package/corpus/rules/java.md +5 -2
  24. package/package/corpus/rules/kotlin.md +7 -5
  25. package/package/corpus/rules/orleans.md +65 -9
  26. package/package/corpus/rules/profiles.md +43 -6
  27. package/package/corpus/rules/pull-requests.md +3 -3
  28. package/package/corpus/rules/react.md +8 -1
  29. package/package/corpus/rules/reactors.md +27 -3
  30. package/package/corpus/rules/specs.csharp.md +11 -4
  31. package/package/corpus/rules/specs.scenarios.csharp.md +35 -4
  32. package/package/corpus/rules/specs.typescript.md +2 -1
  33. package/package/corpus/rules/storybook.md +1 -1
  34. package/package/corpus/rules/typescript.md +1 -1
  35. package/package/corpus/rules/vertical-slices.md +37 -5
  36. package/package/corpus/skills/cratis-application-react-specifications/SKILL.md +4 -2
  37. package/package/corpus/skills/cratis-application-slice-specifications/SKILL.md +18 -8
  38. package/package/corpus/skills/cratis-application-slice-specifications/references/query-and-decision-scenarios.md +65 -0
  39. package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/SKILL.md +53 -57
  40. package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/authentication.md +38 -42
  41. package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/authorization.md +18 -7
  42. package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/authproxy.md +30 -0
  43. package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/frontend.md +12 -9
  44. package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/local-development.md +9 -9
  45. package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/observable-emission-guards.md +8 -5
  46. package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/tenancy.md +20 -4
  47. package/package/corpus/skills/cratis-arc-command/SKILL.md +32 -10
  48. package/package/corpus/skills/cratis-arc-command/references/command-result.md +12 -5
  49. package/package/corpus/skills/cratis-arc-command/references/decisions-and-routing.md +95 -0
  50. package/package/corpus/skills/cratis-arc-command/references/generated-values.md +3 -2
  51. package/package/corpus/skills/cratis-arc-command/references/handler-shapes.md +8 -8
  52. package/package/corpus/skills/cratis-arc-command/references/proxy-generation.md +22 -3
  53. package/package/corpus/skills/cratis-arc-command/references/read-model-injection.md +13 -1
  54. package/package/corpus/skills/cratis-arc-command-execution/SKILL.md +19 -9
  55. package/package/corpus/skills/cratis-arc-command-kotlin/SKILL.md +44 -18
  56. package/package/corpus/skills/cratis-arc-command-kotlin/references/read-model-naming.md +29 -0
  57. package/package/corpus/skills/cratis-arc-command-operation/SKILL.md +10 -9
  58. package/package/corpus/skills/cratis-arc-command-operation/references/execution-and-recovery.md +2 -2
  59. package/package/corpus/skills/cratis-arc-command-operation/references/testing.md +4 -3
  60. package/package/corpus/skills/cratis-arc-command-typescript/SKILL.md +42 -22
  61. package/package/corpus/skills/cratis-arc-command-typescript/references/chronicle-events.md +36 -5
  62. package/package/corpus/skills/cratis-arc-command-typescript/references/command-operations.md +114 -0
  63. package/package/corpus/skills/cratis-arc-command-typescript/references/hosting-and-storage.md +37 -16
  64. package/package/corpus/skills/cratis-arc-command-typescript/references/identity-and-introspection.md +88 -0
  65. package/package/corpus/skills/cratis-arc-command-typescript/references/observability-and-host-scopes.md +25 -0
  66. package/package/corpus/skills/cratis-arc-command-typescript/references/proxy-generation.md +35 -4
  67. package/package/corpus/skills/cratis-arc-command-typescript/references/slice-layout.md +11 -0
  68. package/package/corpus/skills/cratis-arc-command-typescript/verification.json +8 -1
  69. package/package/corpus/skills/cratis-arc-command-validation/SKILL.md +49 -19
  70. package/package/corpus/skills/cratis-arc-ef-core-migration/SKILL.md +12 -6
  71. package/package/corpus/skills/cratis-arc-go/SKILL.md +148 -0
  72. package/package/corpus/skills/cratis-arc-go/references/queries.md +80 -0
  73. package/package/corpus/skills/cratis-arc-hosting/SKILL.md +96 -0
  74. package/package/corpus/skills/cratis-arc-hosting/references/integrations-and-publish.md +80 -0
  75. package/package/corpus/skills/cratis-arc-identity-and-tenancy-kotlin/SKILL.md +137 -0
  76. package/package/corpus/skills/cratis-arc-observable-query-http/SKILL.md +20 -2
  77. package/package/corpus/skills/cratis-arc-query-kotlin/SKILL.md +26 -6
  78. package/package/corpus/skills/cratis-arc-query-paging/SKILL.md +25 -20
  79. package/package/corpus/skills/cratis-arc-query-typescript/SKILL.md +32 -6
  80. package/package/corpus/skills/cratis-arc-query-typescript/references/storage-observation-and-compliance.md +66 -0
  81. package/package/corpus/skills/cratis-arc-query-typescript/verification.json +5 -1
  82. package/package/corpus/skills/cratis-arc-react-page/SKILL.md +24 -13
  83. package/package/corpus/skills/cratis-arc-react-page/references/data-page.md +20 -10
  84. package/package/corpus/skills/cratis-arc-react-page/references/data-tables.md +17 -3
  85. package/package/corpus/skills/cratis-arc-react-page/references/dialogs.md +14 -3
  86. package/package/corpus/skills/cratis-arc-react-page/references/from-screenplay.md +6 -1
  87. package/package/corpus/skills/cratis-arc-react-page/references/provenance.md +1 -1
  88. package/package/corpus/skills/cratis-arc-react-page/references/queries-and-commands.md +11 -1
  89. package/package/corpus/skills/cratis-arc-react-page/verification.json +6 -1
  90. package/package/corpus/skills/cratis-arc-spring-data-kotlin/SKILL.md +163 -0
  91. package/package/corpus/skills/cratis-arc-testing-kotlin/SKILL.md +131 -0
  92. package/package/corpus/skills/cratis-arc-validation-kotlin/SKILL.md +44 -11
  93. package/package/corpus/skills/cratis-arc-validation-typescript/SKILL.md +5 -3
  94. package/package/corpus/skills/cratis-chronicle-cli-operations/SKILL.md +79 -25
  95. package/package/corpus/skills/cratis-chronicle-cli-operations/references/command-effects.md +57 -0
  96. package/package/corpus/skills/cratis-chronicle-client-dotnet/SKILL.md +87 -99
  97. package/package/corpus/skills/cratis-chronicle-client-dotnet/references/additional-surfaces.md +65 -0
  98. package/package/corpus/skills/cratis-chronicle-client-dotnet/references/client-construction.md +42 -0
  99. package/package/corpus/skills/cratis-chronicle-client-dotnet/references/compatibility-check.md +12 -0
  100. package/package/corpus/skills/cratis-chronicle-client-dotnet/references/discovery.md +43 -19
  101. package/package/corpus/skills/cratis-chronicle-client-dotnet/references/hosting.md +29 -1
  102. package/package/corpus/skills/cratis-chronicle-client-elixir/SKILL.md +158 -162
  103. package/package/corpus/skills/cratis-chronicle-client-elixir/references/append-api.md +36 -15
  104. package/package/corpus/skills/cratis-chronicle-client-elixir/references/compliance.md +32 -0
  105. package/package/corpus/skills/cratis-chronicle-client-elixir/references/connections.md +56 -0
  106. package/package/corpus/skills/cratis-chronicle-client-elixir/references/event-sources.md +64 -0
  107. package/package/corpus/skills/cratis-chronicle-client-elixir/references/pitfalls.md +25 -0
  108. package/package/corpus/skills/cratis-chronicle-client-elixir/references/projections.md +48 -0
  109. package/package/corpus/skills/cratis-chronicle-client-elixir/references/upgrading.md +34 -0
  110. package/package/corpus/skills/cratis-chronicle-client-elixir/references/variants.md +13 -5
  111. package/package/corpus/skills/cratis-chronicle-client-elixir/verification.json +23 -0
  112. package/package/corpus/skills/cratis-chronicle-client-go/SKILL.md +162 -0
  113. package/package/corpus/skills/cratis-chronicle-client-go/references/projections.md +73 -0
  114. package/package/corpus/skills/cratis-chronicle-client-kotlin/SKILL.md +87 -88
  115. package/package/corpus/skills/cratis-chronicle-client-kotlin/references/connection-lifecycle.md +13 -0
  116. package/package/corpus/skills/cratis-chronicle-client-kotlin/references/discovery-and-registration.md +14 -4
  117. package/package/corpus/skills/cratis-chronicle-client-kotlin/references/event-sources.md +65 -0
  118. package/package/corpus/skills/cratis-chronicle-client-kotlin/references/options.md +29 -0
  119. package/package/corpus/skills/cratis-chronicle-client-kotlin/references/spring-boot.md +13 -0
  120. package/package/corpus/skills/cratis-chronicle-client-kotlin/references/variants.md +5 -4
  121. package/package/corpus/skills/cratis-chronicle-client-typescript/SKILL.md +165 -156
  122. package/package/corpus/skills/cratis-chronicle-client-typescript/references/read-models-and-projections.md +54 -11
  123. package/package/corpus/skills/cratis-chronicle-client-typescript/references/testing.md +126 -0
  124. package/package/corpus/skills/cratis-chronicle-client-typescript/references/variants.md +3 -5
  125. package/package/corpus/skills/cratis-chronicle-client-typescript/verification.json +19 -0
  126. package/package/corpus/skills/cratis-chronicle-compliance/SKILL.md +36 -13
  127. package/package/corpus/skills/cratis-chronicle-decision-reads/SKILL.md +110 -0
  128. package/package/corpus/skills/cratis-chronicle-decision-reads/references/admission-and-ownership.md +57 -0
  129. package/package/corpus/skills/cratis-chronicle-decision-reads/verification.json +12 -0
  130. package/package/corpus/skills/cratis-chronicle-event-constraints/SKILL.md +58 -19
  131. package/package/corpus/skills/cratis-chronicle-event-constraints/references/closing-streams.md +73 -0
  132. package/package/corpus/skills/cratis-chronicle-event-modeling/SKILL.md +32 -3
  133. package/package/corpus/skills/cratis-chronicle-event-specifications/SKILL.md +18 -5
  134. package/package/corpus/skills/cratis-chronicle-event-type-migration/SKILL.md +32 -2
  135. package/package/corpus/skills/cratis-chronicle-hosting/SKILL.md +134 -0
  136. package/package/corpus/skills/cratis-chronicle-hosting/references/operations.md +89 -0
  137. package/package/corpus/skills/cratis-chronicle-hosting/verification.json +14 -0
  138. package/package/corpus/skills/cratis-chronicle-mcp-inspection/SKILL.md +93 -66
  139. package/package/corpus/skills/cratis-chronicle-mcp-inspection/references/blocked-tools.md +21 -7
  140. package/package/corpus/skills/cratis-chronicle-mcp-inspection/references/deployment.md +77 -0
  141. package/package/corpus/skills/cratis-chronicle-mcp-inspection/references/observational-tools.md +46 -4
  142. package/package/corpus/skills/cratis-chronicle-multi-tenancy/SKILL.md +15 -1
  143. package/package/corpus/skills/cratis-chronicle-projection/SKILL.md +44 -10
  144. package/package/corpus/skills/cratis-chronicle-projection/references/fluent-builder.md +7 -1
  145. package/package/corpus/skills/cratis-chronicle-projection/references/model-bound-attributes.md +8 -0
  146. package/package/corpus/skills/cratis-chronicle-reactor/SKILL.md +85 -105
  147. package/package/corpus/skills/cratis-chronicle-reactor/references/slice-delivery-checklist.md +1 -1
  148. package/package/corpus/skills/cratis-chronicle-reactor/references/specifications.md +20 -1
  149. package/package/corpus/skills/cratis-chronicle-read-model/SKILL.md +2 -2
  150. package/package/corpus/skills/cratis-chronicle-read-model/references/queries.md +35 -16
  151. package/package/corpus/skills/cratis-chronicle-read-model-specifications/SKILL.md +15 -3
  152. package/package/corpus/skills/cratis-chronicle-reducer/SKILL.md +23 -4
  153. package/package/corpus/skills/cratis-chronicle-web-workbench/SKILL.md +40 -15
  154. package/package/corpus/skills/cratis-cli-terminal-workbench/SKILL.md +20 -6
  155. package/package/corpus/skills/cratis-code-review/SKILL.md +25 -3
  156. package/package/corpus/skills/cratis-components-accessibility/SKILL.md +20 -4
  157. package/package/corpus/skills/cratis-components-schema-editor/SKILL.md +40 -28
  158. package/package/corpus/skills/cratis-components-schema-editor/references/tree-layout.md +62 -0
  159. package/package/corpus/skills/cratis-components-schema-editor/verification.json +14 -0
  160. package/package/corpus/skills/cratis-components-stepper-command-dialog/SKILL.md +16 -8
  161. package/package/corpus/skills/cratis-components-styling/SKILL.md +57 -20
  162. package/package/corpus/skills/cratis-components-styling/verification.json +13 -0
  163. package/package/corpus/skills/cratis-components-toolbar/SKILL.md +37 -7
  164. package/package/corpus/skills/cratis-components-toolbar/verification.json +12 -0
  165. package/package/corpus/skills/cratis-engineering-csharp-conventions/SKILL.md +6 -0
  166. package/package/corpus/skills/cratis-engineering-csharp-conventions/references/exceptions-logging-and-di.md +5 -3
  167. package/package/corpus/skills/cratis-fundamentals-concept/SKILL.md +19 -6
  168. package/package/corpus/skills/cratis-fundamentals-concept/references/typescript-concepts.md +97 -0
  169. package/package/corpus/skills/cratis-fundamentals-concept/verification.json +4 -1
  170. package/package/corpus/skills/cratis-fundamentals-concept-go/SKILL.md +112 -0
  171. package/package/corpus/skills/cratis-fundamentals-type-discovery/SKILL.md +54 -17
  172. package/package/corpus/skills/cratis-fundamentals-type-discovery/verification.json +14 -0
  173. package/package/corpus/skills/cratis-lens-browser-extension/SKILL.md +55 -28
  174. package/package/corpus/skills/cratis-performance-review/SKILL.md +5 -2
  175. package/package/corpus/skills/cratis-release-notes/SKILL.md +3 -1
  176. package/package/corpus/skills/cratis-screenplay-automations-and-translations/SKILL.md +5 -4
  177. package/package/corpus/skills/cratis-screenplay-automations-and-translations/references/realization-and-gap-fill.md +1 -1
  178. package/package/corpus/skills/cratis-screenplay-captures-and-reactions/SKILL.md +1 -1
  179. package/package/corpus/skills/cratis-screenplay-command-surface/SKILL.md +5 -6
  180. package/package/corpus/skills/cratis-screenplay-command-surface/references/compliance.md +25 -7
  181. package/package/corpus/skills/cratis-screenplay-command-surface/references/enum-numbers.md +4 -2
  182. package/package/corpus/skills/cratis-screenplay-command-surface/references/generated-values-and-responses.md +4 -1
  183. package/package/corpus/skills/cratis-screenplay-event-modeling/SKILL.md +4 -3
  184. package/package/corpus/skills/cratis-screenplay-event-modeling/references/nine-steps.md +1 -1
  185. package/package/corpus/skills/cratis-screenplay-event-modeling/references/parsed-not-runnable.md +2 -2
  186. package/package/corpus/skills/cratis-screenplay-legacy-extraction/SKILL.md +3 -2
  187. package/package/corpus/skills/cratis-screenplay-legacy-extraction/references/generate-notes.md +34 -4
  188. package/package/corpus/skills/cratis-screenplay-model-authoring/SKILL.md +5 -3
  189. package/package/corpus/skills/cratis-screenplay-model-authoring/references/language-reference.md +1 -1
  190. package/package/corpus/skills/cratis-screenplay-model-authoring/references/mcp-tools.md +4 -2
  191. package/package/corpus/skills/cratis-screenplay-model-authoring/references/property-links.md +42 -3
  192. package/package/corpus/skills/cratis-screenplay-model-authoring/verification.json +3 -1
  193. package/package/corpus/skills/cratis-screenplay-modeling-lifecycle/references/vocabulary-map.md +2 -2
  194. package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/SKILL.md +6 -6
  195. package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/references/drift-and-ledger.md +1 -1
  196. package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/references/gap-fill-handoff.md +6 -4
  197. package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/references/renderability-gate.md +1 -1
  198. package/package/corpus/skills/cratis-screenplay-scenario-coverage/SKILL.md +3 -1
  199. package/package/corpus/skills/cratis-screenplay-scenario-coverage/references/invoicing-dues-design.md +1 -1
  200. package/package/corpus/skills/cratis-screenplay-slice-design/SKILL.md +1 -1
  201. package/package/corpus/skills/cratis-screenplay-slice-design/references/rule-layers.md +2 -2
  202. package/package/corpus/skills/cratis-screenplay-slice-design/references/worked-example.md +1 -1
  203. package/package/corpus/skills/cratis-screenplay-specifications/references/examples-and-routes.md +48 -0
  204. package/package/corpus/skills/cratis-screenplay-specifications/verification.json +3 -1
  205. package/package/corpus/skills/cratis-screenplay-streams-and-consistency/SKILL.md +7 -5
  206. package/package/corpus/skills/cratis-screenplay-streams-and-consistency/references/chronicle-boundaries.md +2 -2
  207. package/package/corpus/skills/cratis-screenplay-streams-and-consistency/references/consistency-and-concurrency.md +2 -2
  208. package/package/corpus/skills/cratis-screenplay-streams-and-consistency/references/streams-example.md +5 -4
  209. package/package/corpus/skills/cratis-screenplay-toolchain/SKILL.md +8 -6
  210. package/package/corpus/skills/cratis-screenplay-toolchain/references/cheat-sheet-example.md +2 -2
  211. package/package/corpus/skills/cratis-screenplay-toolchain/references/diagnostics.md +4 -2
  212. package/package/corpus/skills/cratis-screenplay-toolchain/references/doc-contradictions.md +1 -1
  213. package/package/corpus/skills/cratis-screenplay-toolchain/references/executable-subset.md +16 -11
  214. package/package/corpus/skills/cratis-screenplay-toolchain/references/renderable-subset.md +8 -5
  215. package/package/corpus/skills/cratis-screenplay-toolchain/references/screenplay-contract.json +1329 -32
  216. package/package/corpus/skills/cratis-screenplay-toolchain/references/screenplay-contract.version +1 -1
  217. package/package/corpus/skills/cratis-screenplay-toolchain/references/verdicts.md +2 -2
  218. package/package/corpus/skills/cratis-screenplay-toolchain/references/versions.md +23 -7
  219. package/package/corpus/skills/cratis-screenplay-toolchain/verification.json +1 -1
  220. package/package/corpus/skills/cratis-screenplay-ui-composition/SKILL.md +2 -0
  221. package/package/corpus/skills/cratis-screenplay-ui-composition/references/screen-composition-contract.md +27 -9
  222. package/package/corpus/skills/cratis-security-review/SKILL.md +9 -3
  223. package/package/corpus/skills/cratis-security-review/references/arc-boundaries.md +59 -0
  224. package/package/corpus/skills/cratis-specification-by-example/SKILL.md +7 -0
  225. package/package/corpus/skills/cratis-specifications-csharp/SKILL.md +43 -11
  226. package/package/corpus/skills/cratis-specifications-csharp/references/application-scenarios.md +16 -4
  227. package/package/corpus/skills/cratis-specifications-csharp/references/csharp-patterns.md +18 -5
  228. package/package/corpus/skills/cratis-specifications-csharp/references/integration-specs.md +21 -0
  229. package/package/corpus/skills/cratis-specifications-csharp/references/shared-lifecycle.md +34 -0
  230. package/package/corpus/skills/cratis-specifications-csharp/verification.json +13 -0
  231. package/package/corpus/skills/cratis-specifications-typescript/SKILL.md +14 -5
  232. package/package/corpus/skills/cratis-specifications-typescript/verification.json +12 -0
  233. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/SKILL.md +11 -5
  234. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/admission.md +7 -4
  235. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/rendered-application.md +10 -1
  236. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/scene-runtime.md +75 -0
  237. package/package/corpus/skills/cratis-stage-rendering-and-sandbox/verification.json +6 -1
  238. package/package/corpus/skills/cratis-studio-mcp-safety-guidance/SKILL.md +14 -1
  239. package/package/profile-catalog.json +68 -1
  240. package/package.json +1 -1
  241. package/src/index.ts +3 -1
@@ -0,0 +1,114 @@
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
+ # Inline command operations and aggregate decisions
5
+
6
+ ## Contents
7
+
8
+ - Several business outcomes
9
+ - Declare work, do not execute it twice
10
+ - Recovery follows commit facts
11
+ - Chronicle aggregates (experimental)
12
+
13
+ Verified at `Cratis/Arc.TypeScript` **v0.57.2** (source preview, not on npm):
14
+ `Source/Core/commands/CommandOperation.ts`, operation execution/recovery code,
15
+ `Source/Chronicle/ChronicleCommandScope.ts`, `commandAggregate.ts`,
16
+ `Documentation/commands/operations/reference.md`, and
17
+ `Documentation/chronicle/aggregates/**`.
18
+
19
+ ## Several business outcomes
20
+
21
+ Proxy generation accepts alternatives resolving to the same client type:
22
+ literal unions retain their type; distinct concepts may fall back to their shared
23
+ primitive. Different client types, even identical-shaped DTO classes, fail
24
+ generation: use one response DTO with a status field. A .NET-style arbitrary
25
+ Result error DTO is ordinary response data, not rejection; use `response(...)`
26
+ for data and `rejected(...)`/`denied(...)` for failures.
27
+
28
+ ## Declare work, do not execute it twice
29
+
30
+ Extend `CommandOperation` from `@cratis/arc.core`. Return an instance from
31
+ `handle()`; a direct call only returns the declaration. Arc executes it in the
32
+ pipeline, never sends it to the client. Use `operations(first, second)` for an
33
+ explicit sequential batch — a plain array is not a batch. Combine with one
34
+ client response using `tuple(response(value), operation)`.
35
+
36
+ ```typescript
37
+ // Copyright (c) Cratis. All rights reserved.
38
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
39
+
40
+ import { CommandOperation, command, response, tuple } from '@cratis/arc.core';
41
+
42
+ // In-memory demonstration, not a durable external-effect implementation.
43
+ const calls: string[] = [];
44
+ class Notify extends CommandOperation {
45
+ execute(signal: AbortSignal): void {
46
+ signal.throwIfAborted();
47
+ calls.push('notify');
48
+ }
49
+ compensate(_failure: unknown, signal: AbortSignal): void {
50
+ signal.throwIfAborted();
51
+ calls.push('undo notification');
52
+ }
53
+ }
54
+
55
+ @command()
56
+ export class SendNotification {
57
+ handle() { return tuple(response('declared'), new Notify()); }
58
+ }
59
+ ```
60
+
61
+ `executeDependencies` / `compensateDependencies` are service-token arrays;
62
+ Arc resolves dependencies before starting any operation and passes them after
63
+ the signal (after `failure, signal` for compensation). Do not call the same write
64
+ in `handle()` as well as returning the operation.
65
+
66
+ ## Recovery follows commit facts
67
+
68
+ Arc records entry **before** calling execute, completes scopes before deciding
69
+ recovery, and compensates entered operations in reverse order, including one
70
+ that threw. The separate cooperative `commandCompensationTimeoutMs` budget
71
+ (default 30,000 ms) is shared by compensations, not the cancelled request signal.
72
+ A callback ignoring its signal cannot be forcibly stopped; late completion is
73
+ `BudgetExpired`.
74
+
75
+ | `CommandCommitDisposition` | Compensation after failure |
76
+ | --- | --- |
77
+ | `NoCommit`, `NotCommitted` | Attempt |
78
+ | `Committed` | Suppress |
79
+ | `Unknown`, `Mixed` | Do not guess: indeterminate recovery, not success |
80
+
81
+ Direct-call `result.recovery` / `operationOutcomes` describe execution and
82
+ recovery; they are not serialized to HTTP. `CommandScenario` results offer
83
+ `shouldHaveExecutedOperation(Type)`, `shouldHaveCompensatedOperation(Type)`,
84
+ `shouldHaveNoOperationInvocations()`, and `shouldHaveIndeterminateRecovery()`.
85
+ Specify success, throwing/partially-entered operations, cancellation, compensation
86
+ failure/budget expiry, and unknown commit facts.
87
+
88
+ With Chronicle, `tuple(event, operation)` stages the event, executes the operation,
89
+ then completes the append scope before deciding compensation. Known append
90
+ rejection compensates; unknown/partial acknowledgment does not claim rollback.
91
+ The tagged `Documentation/commands/operations/index.md` still says events and
92
+ operations cannot combine; `ChronicleCommandScope.ts` and the live integration
93
+ specs establish the supported combination at this tag.
94
+
95
+ There is no distributed transaction, automatic retry, durable recovery journal
96
+ or crash recovery. Compensation success is not proof an external effect was
97
+ undone. After-commit durable work belongs in an idempotent reactor/outbox/workflow.
98
+
99
+ ## Chronicle aggregates (experimental)
100
+
101
+ `AggregateRoot` and `commandAggregate` come from `@cratis/arc.chronicle`.
102
+ Bind `@inject(commandAggregate(Order))` to an `Order` extending AggregateRoot.
103
+ Arc rehydrates the command's **explicit key**, in the tenant namespace and the
104
+ command's source/stream route. No key fails before handle; loading another id is
105
+ not supported. Each aggregate type loads once per command.
106
+
107
+ `apply(event)` stages events in the command's batch; a successful command appends
108
+ them even when handle returns nothing. `return order.commit()` is optional;
109
+ never return the same event again. Rejection discards staged events. The route's
110
+ tail is captured at load and appended as an exact concurrency scope; another
111
+ append to the route rejects the entire batch. Projection reads may lag this
112
+ rehydrated state. Use ChronicleKernelScenario for aggregate/concurrency specs,
113
+ not the in-memory scenario. Registered event-source-definition routing for Arc
114
+ commands/aggregates is **not** part of v0.57.2.
@@ -10,8 +10,7 @@
10
10
  - Observable-query WebSockets from a dev server
11
11
  - Storage integrations
12
12
 
13
- Verified against `Cratis/Arc.TypeScript` `main` at commit `94d398d` (tag
14
- `v0.33.0` plus three commits): `Documentation/overview.md`, `hosts/**`,
13
+ Verified against `Cratis/Arc.TypeScript` tag **v0.57.2** (GitHub pre-release): `Documentation/overview.md`, `hosts/**`,
15
14
  `mongodb/getting-started.md`, `sql/getting-started.md`,
16
15
  `chronicle/registration-options.md`, and the `Express`, `Fastify`, `Hono`,
17
16
  `MongoDB`, `Drizzle` and `Chronicle` package exports. None of these packages is
@@ -48,7 +47,14 @@ export const arc = await builder.build();
48
47
  Every adapter dispatches only exact raw-path matches on a fixed internal origin
49
48
  (a crafted `Host` header cannot select an operation), hands Arc the unparsed
50
49
  body, and passes a cancellation signal that becomes `context.signal`. The
51
- framework owns its listener: close it, then `await arc.dispose()`.
50
+ framework owns its listener. With shutdown participants, coordinate listener and
51
+ service shutdown instead of closing first: `host.shutdown({ timeoutMs, registry? })`
52
+ for the standalone host, `middleware.shutdown(listener, registry?)` for Express,
53
+ or `shutdownArcHost(server, closeListener, registry?)` from
54
+ `@cratis/arc.core/hosting`. `close()` remains listener-only. Register participants
55
+ with `server.services.addShutdownParticipant({ stop, drain })`; `app.stop()` /
56
+ `dispose()` coordinate the same order when Arc owns the registry. Repeated
57
+ `server.dispose()` preserves the first outcome.
52
58
 
53
59
  ## Express
54
60
 
@@ -65,10 +71,7 @@ const listener = app.listen(3000, '127.0.0.1');
65
71
  middleware.injectWebSocket(listener);
66
72
 
67
73
  process.once('SIGTERM', () => {
68
- void (async () => {
69
- try { await middleware.close(listener); }
70
- finally { await arc.dispose(); }
71
- })();
74
+ void middleware.shutdown(listener);
72
75
  });
73
76
  ```
74
77
 
@@ -86,12 +89,13 @@ process.once('SIGTERM', () => {
86
89
  ```typescript
87
90
  import Fastify from 'fastify';
88
91
  import cratisArc from '@cratis/arc.fastify';
92
+ import { shutdownArcHost } from '@cratis/arc.core/hosting';
89
93
  import { arc } from './arc.js';
90
94
 
91
95
  const app = Fastify();
92
96
  await app.register(cratisArc, { arc });
93
97
  await app.listen({ port: 3000, host: '127.0.0.1' });
94
- process.once('SIGTERM', () => { void app.close().then(() => arc.dispose()); });
98
+ process.once('SIGTERM', () => { void shutdownArcHost(arc.server, () => app.close()); });
95
99
  ```
96
100
 
97
101
  - The plugin is encapsulated, with its own catch-all raw-body parser; your
@@ -107,13 +111,14 @@ process.once('SIGTERM', () => { void app.close().then(() => arc.dispose()); });
107
111
  ```typescript
108
112
  import { Hono } from 'hono';
109
113
  import { cratisArc, serveCratisArc } from '@cratis/arc.hono';
114
+ import { shutdownArcHost } from '@cratis/arc.core/hosting';
110
115
  import { arc } from './arc.js';
111
116
 
112
117
  const app = new Hono();
113
118
  app.use(cratisArc(arc));
114
119
  app.get('/health', context => context.text('ok'));
115
120
  const hosted = await serveCratisArc(app, arc, { port: 3000, hostname: '127.0.0.1' });
116
- process.once('SIGTERM', () => { void hosted.dispose().then(() => arc.dispose()); });
121
+ process.once('SIGTERM', () => { void shutdownArcHost(arc.server, () => hosted.dispose()); });
117
122
  ```
118
123
 
119
124
  - Running on Node needs the optional `@hono/node-server`. There the adapter also
@@ -143,9 +148,11 @@ export const app = await builder.build();
143
148
  Import `command`, `query`, `readModel` from `@cratis/arc.core/fetch` in artifacts
144
149
  served this way. Arc targets **Node-compatible** servers: Chronicle uses gRPC,
145
150
  MongoDB uses TCP, and live queries need long-lived SSE/WebSocket connections.
146
- Non-Node edge runtimes are not supported hosts for the framework or these
147
- integrations. Bun has a smoke check only. The host owns ingress limits, trusted
148
- principal metadata, and cancelling long-lived streams on disconnect.
151
+ The Fetch entry supports Next.js App Router route handlers on the **Node.js**
152
+ runtime; Bun and Deno have smoke checks. Cloudflare Workers and Next.js Edge
153
+ are unsupported. Its only Node import is `node:async_hooks`; that does not make
154
+ TCP/gRPC integrations portable to an edge host. The host owns ingress limits,
155
+ trusted principal metadata, and cancelling long-lived streams on disconnect.
149
156
 
150
157
  ## Observable-query WebSockets from a dev server
151
158
 
@@ -164,18 +171,23 @@ adds a builder method when imported; the exported function form is equivalent.
164
171
  | Integration | Register | Inject |
165
172
  | --- | --- | --- |
166
173
  | MongoDB (`@cratis/arc.mongodb`, peer `mongodb` `^6.21.0`) | `import '@cratis/arc.mongodb'; builder.withMongoDB({ client, databaseNameResolver, readModels: [TaskRecord] })` or `withMongoDB(builder, options)` | `service(mongoCollection(TaskRecord))` in `@query`, or `@inject(mongoCollection(TaskRecord))`; `commandReadModel(TaskRecord)` in commands |
167
- | SQL through Drizzle (`@cratis/arc.drizzle`, peer `drizzle-orm` `^0.45.0`) | `import '@cratis/arc.drizzle'; builder.withDrizzle({ dialect: DrizzleDialect.SQLite, database, readModels: [{ type: TaskRecord, table: tasks }] })` | `service(drizzleReadModel(TaskRecord))` for read-only query handles; `@inject(drizzleDatabase<SQLJsDatabase>())` for a writable handle in commands; `commandReadModel(TaskRecord)` |
168
- | Chronicle (`@cratis/arc.chronicle`, experimental, peer `@cratis/chronicle` `^6.7.0`) | `import '@cratis/arc.chronicle'; builder.withChronicle({ connectionString, eventStore })` or `withChronicle(builder, options)` | Commands return events; queries take `service(ChronicleReadModels)`; `commandReadModel(Type)` |
174
+ | SQL through Drizzle (`@cratis/arc.drizzle`, peers `drizzle-orm` `^0.45.0` and `rxjs` `^7.8.2`) | `import '@cratis/arc.drizzle'; builder.withDrizzle({ dialect: DrizzleDialect.SQLite, database, readModels: [{ type: TaskRecord, table: tasks }] })` | `service(drizzleReadModel(TaskRecord))` for read-only query handles; `@inject(drizzleDatabase<SQLJsDatabase>())` for a writable handle in commands; `commandReadModel(TaskRecord)` |
175
+ | Chronicle (`@cratis/arc.chronicle`, experimental, peer `@cratis/chronicle` `^6.29.0`) | `import '@cratis/arc.chronicle'; builder.withChronicle({ connectionString, eventStore })` or `withChronicle(builder, options)` | Commands return events; queries take `service(ChronicleReadModels)`; `commandReadModel(Type)` |
169
176
 
170
177
  - **MongoDB**: list every injected model in `readModels`; a model left out has
171
178
  no collection token. `@key()` marks the field stored as `_id` (otherwise a
172
179
  field named `id`). Only `server` and `database` bind from `Cratis:MongoDB`
173
- configuration. Change-stream observation needs a replica set.
180
+ configuration. Change-stream observation needs a replica set. Protected raw
181
+ documents need typed `MongoReadModels` with a Chronicle-registered `readModel`
182
+ (optional `subjectFor`); untyped reads remain ciphertext. Read
183
+ [the observation/compliance reference](../../cratis-arc-query-typescript/references/storage-observation-and-compliance.md)
184
+ before exposing protected documents.
174
185
  - **Drizzle**: `withDrizzle` never creates or changes tables — own the schema
175
186
  with migrations. Every SQL access needs a tenant (`A tenant is required for
176
187
  Drizzle access` otherwise); a single-database setup resolves one fixed tenant.
177
188
  Command read-model injection needs exactly one column-level `.primaryKey()`
178
- declared as an Arc `@field`.
189
+ declared as an Arc `@field`. Observation is opt-in; the query skill's
190
+ storage reference covers in-process announcements and PostgreSQLNotify.
179
191
  - **Chronicle**: `withChronicle` needs `eventStore` and exactly one of
180
192
  `connectionString` or `client` (`Chronicle requires eventStore and exactly one
181
193
  of connectionString or client`). It reads `Cratis:Chronicle` `connectionString`
@@ -187,6 +199,15 @@ adds a builder method when imported; the exported function form is equivalent.
187
199
  reachable makes Chronicle-backed requests wait, not fail.
188
200
  `chronicle://localhost:35000` without credentials uses the development client —
189
201
  local kernels only.
202
+ - **MongoDB + Chronicle naming**: Arc-owned `withChronicle` stores projected
203
+ models in the collection `withMongoDB` reads (pluralized by default), in either
204
+ registration order. The former `collectionName: type => type.name` workaround
205
+ is no longer needed. A throwing/empty collection-name callback fails
206
+ registration. Override with `withChronicle({ ..., readModelNamingPolicy })`;
207
+ with a caller-owned client set it in that client's `ChronicleOptions` instead.
208
+ Existing deployments must replay projections into the aligned collection;
209
+ the old collection is left intact. Core exports `readModelCollectionNameResolver`,
210
+ MongoDB exports `resolveMongoCollectionName`.
190
211
  - `@cratis/cratis` (experimental) registers Arc and Chronicle together through
191
212
  `CratisApplication.createBuilder()` and `builder.addCratis(...)`. Unlike C#
192
213
  `AddCratis`, it installs no authentication handler; protected routes still
@@ -0,0 +1,88 @@
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
+ # Identity, authorization and discovery access
5
+
6
+ Verified at `Cratis/Arc.TypeScript` **v0.57.2** (GitHub pre-release, not on npm):
7
+ `Source/Core/authentication/**`, `identity/**`, `introspection/**`,
8
+ `Documentation/core/authentication.md`, `authorization.md`,
9
+ `Documentation/identity/**`, `hosts/native-principal.md`, and
10
+ `upgrading/secure-defaults.md`. This is the **TypeScript server** contract,
11
+ not the .NET authentication skill.
12
+
13
+ ## Authenticate at one trusted boundary
14
+
15
+ | Boundary | Builder options | Trust requirement |
16
+ | --- | --- | --- |
17
+ | Arc verifies bearer JWTs | `authentication: [jwtBearer({ jwksUrl, issuer, audience, algorithms })]` | HTTPS JWKS URL; pin issuer, API audience and asymmetric algorithms; validate API tokens, not an ID token |
18
+ | Host middleware already verified identity | `nativePrincipal: true`, plus the adapter's verified native-context callback | Bridge HTTP and WebSocket upgrades explicitly; a raw request/header is not a principal |
19
+ | EasyAuth/AuthProxy ingress | `authentication: [microsoftIdentityPlatform()]` | Strip client `x-ms-client-principal*` headers, set trusted ones and block direct backend access |
20
+ | Application credential check | `authentication: [handler]` | Implement `AuthenticationHandler`; do not trust the display cookie |
21
+
22
+ `nativePrincipal` and Arc authentication handlers are mutually exclusive.
23
+ Handlers return `AuthenticationStatus.Anonymous` (try next), `Authenticated`
24
+ (with principal), or `Failed` (401 even for an anonymous operation). Principals
25
+ require authenticated status, string `id`, string-array `roles`; name, claims
26
+ and scheme are optional. Arc freezes the principal, roles and own claims.
27
+ With no handler, protected operations answer 403 rather than authenticating.
28
+
29
+ For Entra bearer tokens, verify against the tenant-specific issuer and API
30
+ audience. App roles and delegated scopes are different; require the one the API
31
+ actually uses. Do not put bearer tokens in query-string URLs. Native identity
32
+ must also be provided on upgrades/SSE; configuring HTTP middleware alone does
33
+ not authenticate a WebSocket upgrade. Named schemes belong in
34
+ `authenticationSchemes: { Verified: handler }` and are selected with
35
+ `@authorize({ schemes: ['Verified'] })`.
36
+
37
+ ## Authorize the operation, not the UI
38
+
39
+ With no decorator, anonymous callers are permitted. `@authorize()` requires authentication;
40
+ `@authorize({ policy, roles, schemes })` adds requirements, and `@roles('A', 'B')`
41
+ accepts any listed role. Stacked requirements all pass. `@allowAnonymous()` cannot
42
+ coexist with an authenticated requirement on the same declaration. Commands
43
+ carry decorators on the **class**, never `handle`/`provide`; query methods may
44
+ override the read-model class's declaration. Policies and row filters use the
45
+ verified principal, not an input role/tenant or a hidden button.
46
+ Observable authorization runs at subscription opening; changing a role later
47
+ needs an emission guard to stop further disclosure.
48
+
49
+ ## Supply identity details
50
+
51
+ `@identityDetailsProvider()` on an exported provider lets discovery register it;
52
+ `builder.add(Provider)` is also supported. Implement `IdentityDetailsProvider`
53
+ with `detailsType` (a `@field` model) or `schema` and
54
+ `provide(principal, context)`. Returning undefined denies the authenticated
55
+ caller; output must match the schema.
56
+
57
+ `GET /.cratis/me` serves principal id/name/roles plus provider `details` and sets
58
+ `.cratis-identity`. This unsigned, JavaScript-readable cookie is **display data,
59
+ never a credential**; provider details never flow into authorization. The
60
+ published React identity hooks can display it, but server protection still
61
+ belongs on every operation. Local users/tenants are development fixtures, not
62
+ production credentials; keep simulated identities on loopback hosts.
63
+
64
+ ## Secure introspection defaults (0.56.0+)
65
+
66
+ `/.cratis/commands`, `/.cratis/queries`, `/.cratis/identity-details/schema`,
67
+ `/.cratis/users`, `/.cratis/tenants`, and `/openapi.json` are anonymous only in
68
+ Development by default. Elsewhere they require an authenticated principal from
69
+ Arc handlers or the native host. Without authentication, protected discovery is
70
+ unmapped (normally 404) with a startup warning. Explicitly requiring auth with
71
+ none configured fails startup.
72
+
73
+ - `introspection.requireAuthentication: false` deliberately restores anonymous
74
+ discovery; outside Development it logs a warning. Prefer authenticating tools.
75
+ - `introspection.roles: 'Admin,Operator'` accepts any listed role, implies auth,
76
+ and cannot combine with `requireAuthentication: false`; empty roles fail.
77
+ - `introspection.enabled: false` unmaps **catalogs and HTTP OpenAPI**, not identity
78
+ discovery. Its access policy/diagnostics and in-process metadata remain.
79
+ - Node config: `Cratis:Arc:Introspection:Enabled/RequireAuthentication/Roles` or
80
+ `Cratis__Arc__Introspection__Enabled/RequireAuthentication/Roles` environment keys.
81
+ - `environmentName` is code-only. Otherwise the first defined
82
+ `DOTNET_ENVIRONMENT`, `ASPNETCORE_ENVIRONMENT`, `NODE_ENV` decides; no environment
83
+ is Production. `development: true` enables fixture providers, not this bypass.
84
+
85
+ `/.cratis/me`, command/query invocation and observable transports are unaffected
86
+ by the discovery policy. Deployed Lens/curl/OpenAPI consumers must authenticate
87
+ or rely on a deliberate anonymous opt-out. Source-based proxy generation needs
88
+ no running host. Verify both anonymous and authenticated access after upgrades.
@@ -0,0 +1,25 @@
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
+ # Observability and trusted host scopes
5
+
6
+ Verified at `Cratis/Arc.TypeScript` **v0.57.2** (source preview):
7
+ `Source/Core/execution/WellKnownTelemetryNames.ts`, `observability.ts`,
8
+ `runInScope.ts`, `RunInScopeOptions.ts`, and `Documentation/observability.md`.
9
+
10
+ - `cratis.arc.command.duration` / `cratis.arc.query.duration` measure **seconds**.
11
+ `cratis.arc.command.outcomes` counts command outcomes; the outcome vocabulary
12
+ is `success`, `validation`, `authorization`, `append_rejected`, `cancelled`,
13
+ `error`. `cratis.arc.query.transport` distinguishes query transports.
14
+ - Core exports `WellKnownTelemetryNames`, `OperationOutcome`, `QueryTransport`;
15
+ `@opentelemetry/api ^1.9.0` is a peer. Instrumentation caps command/query names
16
+ at 1,000 to bound cardinality. Do not add raw user/tenant keys to metric names.
17
+ - `cratis.arc.operation.duration` and the `query_name` attribute are deprecated;
18
+ migrate dashboards to command/query-specific names.
19
+
20
+ `ArcServer.runInScope(scope, callback, options?)` runs trusted host integration
21
+ work in a scope created with `server.services.createScope(context)`.
22
+ Service scopes snapshot the execution context at creation. Per-invocation
23
+ options accept only a correlation id (valid UUID) and extra abort signal.
24
+ This is **not** authentication or authorization: never turn untrusted request
25
+ values into a trusted principal by creating a scope.
@@ -1,5 +1,9 @@
1
1
  ## Generate metadata and proxies
2
2
 
3
+ Verified at `Cratis/Arc.TypeScript` **v0.57.2** (source preview):
4
+ `Source/Tools/ProxyGenerator/parseSourceOptions.ts`,
5
+ `Documentation/proxy-generation/getting-started.md`, and sample generator scripts.
6
+
3
7
  `arc-proxygenerator` (package `@cratis/arc.proxygenerator`, also unpublished)
4
8
  reads the TypeScript source with the compiler API — it never queries a running
5
9
  server. It writes server metadata and client proxies in one run. The CLI
@@ -32,7 +36,34 @@ process.exitCode = result.status ?? 1;
32
36
  (`--api-prefix`, `--segments-to-skip`, `--root-namespace`) to the server's
33
37
  `generatedApis` options, or proxies call URLs the server does not serve.
34
38
  - Generated proxies import the **published** `@cratis/arc` and
35
- `@cratis/arc.react` (the docs pin `22.19.1`) plus `@cratis/fundamentals`.
36
- Compile them in `Bundler` resolution with `experimentalDecorators: true`, and
37
- import `reflect-metadata` once in the frontend entry. Consuming the proxies in
38
- React is `cratis-arc-react-page`.
39
+ `@cratis/arc.react` (docs/sample pins **22.45.0**) plus `@cratis/fundamentals`;
40
+ the UI samples pin `@cratis/components` 4.23.0. Compile in strict `Bundler`
41
+ resolution with `skipLibCheck: false`, `experimentalDecorators: true`, and
42
+ import `reflect-metadata` once in the frontend entry. These published client
43
+ declarations do not support NodeNext consumer compilation. Consuming proxies
44
+ in React is `cratis-arc-react-page`.
45
+
46
+ ### Co-locate proxies with the slice
47
+
48
+ The separate-output form above remains supported. To put proxies next to backend
49
+ artifacts, set `--output` to `Features` (or its ancestor/nested folder) and add
50
+ **`--use-proxy-file-suffix`**. This is required for overlapping output. The
51
+ samples emit `RegisterAuthor.proxy.ts` beside `Registration.ts` and
52
+ `RegisterAuthorForm.tsx`, without barrels. `discover()` skips `*.proxy.ts/.tsx`;
53
+ server tsconfig excludes `Features/**/*.proxy.ts` and `Features/**/*.tsx`.
54
+ Never give a `.tsx` file the same basename as the backend slice `.ts`.
55
+
56
+ `--watch` regenerates on backend edits; the generator overwrites/deletes only
57
+ its own output. A web bundler reading slice files outside the web project must
58
+ still lower the proxies' legacy decorators: Vite 8 uses
59
+ `oxc: { decorator: { legacy: true } }`.
60
+
61
+ | Additional flag | Effect |
62
+ | --- | --- |
63
+ | `--skip-react-hooks` | No React import or generated `use*`/`when` hooks |
64
+ | `--type-mapping <Type>=<package>[#<export>]` | Repeatable external mappings (`typeMappings` in programmatic options) |
65
+ | `--watch-poll-interval <ms>` | Poll fallback; requires `--watch`; 0 disables polling |
66
+ | `--js-import-specifiers` | `.js` specifiers for compiled NodeNext ESM; does not fix client declaration compatibility |
67
+ | `--emit-interfaces` | Emit model interfaces |
68
+ | `--skip-index-generation` | Do not emit barrels |
69
+ | `--skip-output-deletion` | Retain stale generated output; use deliberately, not to hide drift |
@@ -1,5 +1,8 @@
1
1
  ## Lay out the slice
2
2
 
3
+ Verified at `Cratis/Arc.TypeScript` **v0.57.2**:
4
+ `Samples/Library/Features/Authors/Registration` and sample generator scripts.
5
+
3
6
  House convention (not a runtime requirement): one folder per behavior, one
4
7
  TypeScript file named for the behavior holding the command, its validator and —
5
8
  for Chronicle — its events. Concepts shared by several slices live one level up.
@@ -13,7 +16,15 @@ Features/Tasks/
13
16
  ├── Tasks.ts
14
17
  ├── Registration/
15
18
  │ ├── Registration.ts
19
+ │ ├── RegisterTask.proxy.ts
20
+ │ ├── RegisterTaskForm.tsx
16
21
  │ └── for_RegisterTask/when_registering/with_valid_title.ts
17
22
  └── Listing/
18
23
  └── Listing.ts
19
24
  ```
25
+
26
+ Co-location needs `--use-proxy-file-suffix` with the artifacts folder as
27
+ `--output`; no barrels. Exclude proxies and TSX from server compilation and
28
+ lower proxy decorators in the frontend bundler. Read
29
+ [proxy-generation.md](proxy-generation.md) when configuring the overlapping
30
+ output or watch mode. Separate output is still supported.
@@ -10,6 +10,13 @@
10
10
  { "kind": "skill-contains", "value": "Authorization belongs on the **class**." },
11
11
  { "kind": "skill-contains", "value": "is created through its **constructor** in `handle()`" },
12
12
  { "kind": "skill-contains", "value": "`--check-metadata`" },
13
- { "kind": "skill-contains", "value": "CommandScenario.for(RegisterTask, RegisterTaskValidator)", "file": "references/command-specifications.md" }
13
+ { "kind": "skill-contains", "value": "CommandScenario.for(RegisterTask, RegisterTaskValidator)", "file": "references/command-specifications.md" },
14
+ { "kind": "skill-contains", "value": "tag **v0.57.2**" },
15
+ { "kind": "skill-contains", "value": "peer `^6.29.0`" },
16
+ { "kind": "skill-contains", "value": "Outside **Development**" },
17
+ { "kind": "skill-contains", "value": "not identity\n discovery", "file": "references/identity-and-introspection.md" },
18
+ { "kind": "skill-contains", "value": "Unknown`, `Mixed", "file": "references/command-operations.md" },
19
+ { "kind": "skill-contains", "value": "**`--use-proxy-file-suffix`**", "file": "references/proxy-generation.md" },
20
+ { "kind": "skill-contains", "value": "projections (>=6.19.0)", "file": "references/chronicle-events.md" }
14
21
  ]
15
22
  }
@@ -23,12 +23,18 @@ rejection on it.)
23
23
 
24
24
  | Package | Version | Purpose |
25
25
  | --- | --- | --- |
26
- | `Cratis.Arc.Core` | `22.16.0` | `CommandValidator<T>`, `ConceptValidator<T>`, `ValidationResult`, `CommandResult`, the command pipeline, `ARC0004`–`ARC0013` |
27
- | `Cratis.Fundamentals` | `7.19.2` | `Cratis.Monads.Result<TResult, TError>` |
26
+ | `Cratis.Arc.Core` | `22.75.0` | `CommandValidator<T>`, `ConceptValidator<T>`, `ValidationResult`, `CommandResult`, the command pipeline, `ARC0004`–`ARC0013` |
27
+ | `Cratis.Fundamentals` | `7.23.0` | `Cratis.Monads.Result<TResult, TError>` |
28
28
  | `Cratis.Chronicle` | `18.3.0` | Read-model resolution for command-side injection |
29
29
  | `FluentValidation` | `12.1.1` | `RuleFor(...)`, `.WithMessage(...)` |
30
30
 
31
- > Re-verified at the versions above by **symbol and signature**: every type, attribute and member this skill names exists at that tag, and the public surface it describes is unchanged since the previous verification (Chronicle 16.45.x / Arc 22.10.4 — the Chronicle 16→18 client diff is converters, options and doc comments; no type was removed or renamed). Behavior claims were verified at the earlier tag unless a section says otherwise.
31
+ > Arc validation and decision boundaries rechecked at v22.75.0. Arc depends on
32
+ > Chronicle 19.39.1 / Fundamentals 7.23.0; separate product claims retain their
33
+ > version-qualified verification.
34
+
35
+ Fundamentals rechecked at v7.23.0 in
36
+ [`Result<TResult, TError>`](https://github.com/Cratis/Fundamentals/blob/v7.23.0/Source/DotNET/Fundamentals/Monads/Result%7BTResult,TError%7D.cs):
37
+ success is first, error second, with implicit conversions from both types.
32
38
 
33
39
  Reverify against the owning product repository before claiming support for
34
40
  another version.
@@ -62,7 +68,7 @@ another version.
62
68
  | A reusable value invariant — length, format, range | `ConceptValidator<T>` on the concept type |
63
69
  | Command input, cross-field, or a pre-handler check | `CommandValidator<TCommand>` with `RuleFor(...)` |
64
70
  | A dependency on data the handler must fetch first | `Provide()` — fetch, and short-circuit if unusable |
65
- | State-dependent and must hold **under concurrency** | Inject the read model into `Handle()`, return `Result<TEvent, ValidationResult>` |
71
+ | State-dependent and must hold **under concurrency** | Guard the read with `IStreamReads`/`StreamDecision`, or `[ProtectedDecision]` + `DecisionRead<T>`; return events through Arc |
66
72
  | Uniqueness | A Chronicle constraint, never a command-side read |
67
73
  | A genuine defect or missing infrastructure | `throw` a domain exception |
68
74
 
@@ -144,27 +150,49 @@ public async Task<Result<Customer, ValidationResult>> Provide(IReadModels readMo
144
150
  directly, and do not duplicate one rejection in both the validator and
145
151
  `Provide()` — pick one owner.
146
152
 
147
- ## Step 5 — Concurrency-sensitive rules: the read model in `Handle()`
148
-
149
- Use this when the rule depends on accumulated event-sourced state — a count, a
150
- running total — and must still hold when two requests arrive at once. Arc
151
- resolves the read model before `Handle()` runs and the handler returns a
152
- `Result<TEvent, ValidationResult>`: success carries the event, failure carries a
153
- typed validation error.
153
+ ## Step 5 — Guard a concurrency-sensitive decision
154
+
155
+ Plain read-model injection or `IReadModels.GetInstanceById` is **advisory**, even
156
+ inside `Handle()` returning `Result<,>`: it enrolls no guard against a competing
157
+ append. Choose the first boundary that fits at Arc v22.75.0:
158
+
159
+ 1. One routed stream: `Provide(IStreamReads reads) => reads.ForCommand()` returns
160
+ `Task<StreamDecision>`; `Handle(StreamDecision decision)` returns
161
+ `decision.Append(...)` (`EventsWithConcurrencyScopes`), guarding the read tail.
162
+ 2. Projected state: mark the command `[ProtectedDecision]` and take
163
+ `DecisionRead<T>` (`.Exists`/`.Instance`) or command-aware `IDecisionReads`.
164
+ Only Chronicle-admitted, direct event-source-keyed projections with known
165
+ event types qualify; reducers, joins, children and passive shapes are refused.
166
+ Only parameterless validators constructed/certified by Arc run. Constructor
167
+ dependencies are refused; static/service-locator decision state is still your
168
+ responsibility. Command-level `[Unprotected]` opts out, not into safety.
169
+ 3. Stream-level automatic scopes: `concurrency: true` on routing attributes
170
+ (`EventStreamId`, `EventStreamType`, `EventSourceType`). Exact returned scopes
171
+ take precedence; do not combine automatic capture with exact scopes.
172
+
173
+ `ARCCHR0011/0012` flag unprotected reads and immediate append bypasses. Return
174
+ events, never append them directly. Read
175
+ [protected and stream decisions](../cratis-arc-command/references/decisions-and-routing.md)
176
+ when choosing the guard. This handler excerpt assumes `CartSummary` is an
177
+ admitted projection; domain types are the slice's existing types.
154
178
 
155
179
  ```csharp
156
180
  using Cratis.Monads;
181
+ using Cratis.Arc.Chronicle.ReadModels;
157
182
 
158
183
  [Command]
184
+ [ProtectedDecision]
159
185
  public record AddItemToCart(CartId CartId, ItemId ItemId)
160
186
  {
161
187
  /// <summary>Adds the item; rejects when the cart already holds the maximum.</summary>
162
188
  /// <param name="cart">The current cart summary, resolved by the command's event-source id.</param>
163
189
  /// <returns>The event on success, or a validation error.</returns>
164
- public Result<ItemAddedToCart, ValidationResult> Handle(CartSummary cart) =>
165
- cart.ItemCount >= 3
166
- ? ValidationResult.Error("A cart can hold at most 3 items.")
167
- : new ItemAddedToCart(ItemId);
190
+ public Result<ItemAddedToCart, ValidationResult> Handle(DecisionRead<CartSummary> cart) =>
191
+ !cart.Exists
192
+ ? ValidationResult.Error("Cart must exist.")
193
+ : cart.Instance.ItemCount >= 3
194
+ ? ValidationResult.Error("A cart can hold at most 3 items.")
195
+ : new ItemAddedToCart(ItemId);
168
196
  }
169
197
  ```
170
198
 
@@ -205,7 +233,9 @@ where absence is *not* `null`.
205
233
  ## Step 6 — Specify the rejection
206
234
 
207
235
  Every rule gets a specification of its failure case, using
208
- `CommandScenario<TCommand>`. Assert **both** that the command did not succeed
236
+ `CommandScenario<TCommand>`. For protected reads, call `UseDecisionReads()`
237
+ before seeding actual events; pinned read models cannot supply a guard. Queue a
238
+ competing append on the relevant route and assert the conflict. Assert **both** that the command did not succeed
209
239
  and that it failed *as a validation*:
210
240
 
211
241
  ```csharp
@@ -231,9 +261,9 @@ the fact. See
231
261
  - **The rule never fires.** The read-model type has no backing Chronicle
232
262
  projection, reducer, `DbSet<T>`, or MongoDB collection, so nothing registered
233
263
  it for command-side resolution.
234
- - **Two requests both win.** The rule is in a validator or a `Provide()` read
235
- rather than in `Handle()` with `Result<,>`, or it is a uniqueness rule that
236
- belongs in a Chronicle constraint.
264
+ - **Two requests both win.** A plain read was mistaken for a protected decision;
265
+ moving it to `Handle()` or returning `Result<,>` does not guard it. Enroll a
266
+ stream/projection decision read, or use an append-time uniqueness constraint.
237
267
  - **`ARC0005` on build.** `Provide()` returns a value no `Handle()` parameter
238
268
  consumes.
239
269
 
@@ -15,11 +15,12 @@ Everything else is ordinary EF Core.
15
15
 
16
16
  | Package | Version | Purpose |
17
17
  | --- | --- | --- |
18
- | `Cratis.Arc.EntityFrameworkCore` | `22.16.0` | `BaseDbContext`, `ReadOnlyDbContext`, `WithEntityFrameworkCore`, column helpers, `EntityFrameworkReadModelForCommandResolver` |
19
- | `Cratis.Arc.Core` | `22.16.0` | `Cratis.Arc.Queries.ModelBound.ReadModelAttribute`, `ICanResolveReadModelForCommand` |
18
+ | `Cratis.Arc.EntityFrameworkCore` | `22.75.0` | `BaseDbContext`, `ReadOnlyDbContext`, `WithEntityFrameworkCore`, column helpers, `EntityFrameworkReadModelForCommandResolver` |
19
+ | `Cratis.Arc.Core` | `22.75.0` | `Cratis.Arc.Queries.ModelBound.ReadModelAttribute`, `ICanResolveReadModelForCommand` |
20
20
  | `Microsoft.EntityFrameworkCore` | `10.0.11` | EF Core itself, including all migration tooling |
21
21
 
22
- > Re-verified at the versions above by **symbol and signature**: every type, attribute and member this skill names exists at that tag, and the public surface it describes is unchanged since the previous verification (Chronicle 16.45.x / Arc 22.10.4 — the Chronicle 16→18 client diff is converters, options and doc comments; no type was removed or renamed). Behavior claims were verified at the earlier tag unless a section says otherwise.
22
+ > Arc EF context, builder and observation surface rechecked at v22.75.0.
23
+ > Verify provider-specific migration behavior against the configured provider.
23
24
 
24
25
  Reverify before claiming support for another version.
25
26
 
@@ -189,9 +190,14 @@ and `ObserveById<TEntity, TId>(id, configure?)`, returning
189
190
  `AddEntityFrameworkCoreObservation()` and `options.AddObservation(serviceProvider)`
190
191
  on the context — `WithEntityFrameworkCore` already does the first for you.
191
192
 
192
- Paging and sorting are applied at the source for these, and an out-of-range page
193
- size is clamped rather than throwing, and an unknown sort field is ignored rather
194
- than failing.
193
+ Paging and sorting are applied at the source; the query pipeline validates
194
+ `page >= 0` and `pageSize > 0`. Unknown observation sort fields are ignored.
195
+ Auxiliary observations can pass `ignoreQueryContext: true` so only the primary
196
+ uses client paging/sorting and writes totals. `ObserveSingle`/`ObserveById` emit
197
+ `default` when the row is absent/deleted/outside the filter, remaining subscribed.
198
+ Indexer-property keys (shared-type entities) are supported; composite and
199
+ shadow-only keys are refused at setup. Source at Arc v22.75.0:
200
+ `Source/DotNET/EntityFrameworkCore/Observe/DbSetObserveExtensions.cs`.
195
201
 
196
202
  ⚠️ Database-level change notification differs by provider: PostgreSQL uses
197
203
  LISTEN/NOTIFY, SQL Server uses Service Broker, and **SQLite has none at all** —