@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
@@ -10,7 +10,7 @@
10
10
  - What is not here
11
11
  - The security boundary, stated plainly
12
12
 
13
- Verified against `Cratis.Arc.Core` and `Cratis.Arc` `22.41.1`. Types are in
13
+ Verified against `Cratis.Arc.Core` and `Cratis.Arc` `22.75.0`. Types are in
14
14
  `Cratis.Arc.Authentication` and `Cratis.Arc.Identity`.
15
15
 
16
16
  ## The contract
@@ -61,7 +61,9 @@ It reads three headers, all constants on
61
61
  | `IdentityIdHeader` | `x-ms-client-principal-id` |
62
62
  | `IdentityNameHeader` | `x-ms-client-principal-name` |
63
63
 
64
- All three must be present or the result is `Anonymous`. The principal header is
64
+ The host-wide `ArcOptions.TrustForwardedIdentityHeaders` must be true first;
65
+ otherwise headers are ignored and the result is `Anonymous`. All three must be
66
+ present or the result is `Anonymous`. The principal header is
65
67
  base64-decoded and deserialized into `ClientPrincipal`:
66
68
 
67
69
  ```csharp
@@ -134,11 +136,13 @@ whose `SchemeName` is `"MicrosoftIdentityPlatform"`. `builder.AddCratis()` (the
134
136
  `Cratis` package) calls this for you and makes it the **default** authentication
135
137
  scheme; `AddCratisArc()` from `Cratis.Arc` does not register it.
136
138
 
137
- ⚠️ At `22.41.1` the default is that a plain `builder.AddCratis()` host trusts the unsigned
138
- `x-ms-client-principal*` headers from **any caller that can reach it** — it is safe
139
- only behind the ingress described below (tracked as open Arc#2946). If the host is
140
- not behind such an ingress, do not use this scheme: configure a credential-validating
141
- ASP.NET Core scheme yourself.
139
+ At **v22.75.0**, `AddCratis()` registers the scheme but forwarded headers do not
140
+ authenticate anybody until `Cratis:Arc:TrustForwardedIdentityHeaders=true`.
141
+ `AddMicrosoftIdentityPlatformIdentityAuthentication()` warns at startup without
142
+ that opt-in; built-in handlers warn on the first header-bearing request.
143
+ The three-argument `MicrosoftIDentityPlatformAuthHandler` constructor is obsolete;
144
+ use the constructor receiving `IOptions<ArcOptions>`.
145
+ Source: [secure defaults](https://github.com/Cratis/Arc/blob/v22.75.0/Documentation/upgrading/secure-defaults.mdx).
142
146
 
143
147
  ## Forwarded headers, ingress requirements and protected introspection
144
148
 
@@ -148,44 +152,36 @@ prevents direct access to the backend**. The same applies to any custom header
148
152
  such as `X-User-ID`. Adding a bearer validator does not make a separately accepted
149
153
  forwarded-header mechanism safe.
150
154
 
151
- Arc applies that rule to one place itself: the protected introspection catalogs
152
- (`/.cratis/commands`, `/.cratis/queries`). By default those are enabled and
153
- **anonymous**. Configure `Cratis:Arc:Introspection`:
155
+ Configure discovery through `Cratis:Arc:Introspection` at **v22.75.0**:
154
156
 
155
157
  | Option | Default | Effect |
156
158
  | --- | --- | --- |
157
- | `Enabled` | `true` | `false` leaves both catalog routes unmapped |
158
- | `RequireAuthentication` | `false` | `true` requires an authenticated caller, regardless of the host's default authorization policy |
159
- | `Roles` | `null` | Comma-separated, any one grants access; needs `RequireAuthentication: true` and no empty entries |
160
- | `TrustForwardedIdentityHeaders` | `false` | Accepts identity from the unsigned forwarded headers for the protected catalog; needs `Enabled` and `RequireAuthentication` |
161
-
162
- At `22.41.1` the default is that the catalogs are public, and with
163
- `RequireAuthentication: true` the forwarded headers are **ignored** for them until
164
- you set `TrustForwardedIdentityHeaders: true`: the built-in
165
- `MicrosoftIdentityPlatformAuthenticationHandler` returns
166
- `AuthenticationResult.Anonymous` for a protected catalog endpoint, so the request
167
- gets 401. **Only set the opt-in behind the trusted ingress above.**
168
-
169
- - Startup fails closed for unsafe combinations: `Roles` or the trust option
170
- without the requirements above; on Arc.Core, `RequireAuthentication` with no
171
- handler, or with only the built-in header handler and no trust opt-in; on
172
- ASP.NET Core, a header-trusting scheme reachable from the default scheme or the
173
- catalog's policy schemes without the opt-in, and a reachable scheme with
174
- `ForwardDefaultSelector` when a header handler is registered.
175
- - **Custom handlers.** Arc cannot tell whether your own `IAuthenticationHandler`
176
- reads forwarded headers, and startup accepts any custom handler as
177
- credential-validating. If yours builds an identity from ingress headers, read
178
- `IOptions<ArcOptions>` and return `AuthenticationResult.Anonymous` when
179
- `TrustForwardedIdentityHeaders` is `false` and
180
- `context.GetEndpointMetadata()?.RequireAuthentication == true`. A subclass of the
181
- ASP.NET Core header handler that overrides `HandleAuthenticateAsync` without
182
- calling the base is your own handler and carries the same obligation.
183
- - These options do **not** change `/.cratis/identity-details/schema`, command and
184
- query invocation, or the user and tenant discovery endpoints. Restrict those at
185
- the ingress. On ASP.NET Core a protected catalog's 401/403 is the configured
186
- scheme's challenge, which a cookie scheme may turn into a redirect.
187
-
188
- Discovery exposure as a whole is tracked in open Arc#2834.
159
+ | `Enabled` | `true` | `false` leaves command/query catalogs unmapped |
160
+ | `IdentityDiscovery` | `true` | `false` removes users, tenants and details schema |
161
+ | `RequireAuthentication` | unset | Environment default: anonymous in Development, authenticated elsewhere |
162
+ | `Roles` | `null` | Comma-separated, any one grants access; implies authentication |
163
+ | `TrustForwardedIdentityHeaders` | `false` | Obsolete compatibility setting; turns on the host-wide trust flag |
164
+
165
+ The `RequireAuthentication` getter remains `bool` and reads false when unset,
166
+ but **assigning** false is an explicit anonymous-everywhere opt-in, with a warning
167
+ outside Development. Explicit true requires authentication everywhere and fails
168
+ startup if the host cannot enforce it. Roles cannot combine with explicit false.
169
+ Under the environment default a host unable to authenticate omits discovery
170
+ routes (404) and logs a warning. Disabling both discovery switches removes all
171
+ discovery without enforcement checks; `/.cratis/me` remains.
172
+
173
+ Custom forwarded-header handlers must read `IOptions<ArcOptions>` and refuse
174
+ headers whenever the host-wide flag is false, **on every endpoint**, not only
175
+ protected catalogs. Startup no longer rejects the built-in header scheme for
176
+ protected catalogs: it authenticates nobody without the opt-in. A subclass that
177
+ bypasses `HandleAuthenticateAsync` in the base owns the same obligation.
178
+ On ASP.NET Core, a scheme's challenge may redirect instead of returning 401.
179
+
180
+ `[ExcludeFromDiscovery]` suppresses catalogs/OpenAPI, not endpoint invocation;
181
+ it is not authorization. These .NET options do not establish a JVM equivalent.
182
+ Sources: [IntrospectionOptions.cs](https://github.com/Cratis/Arc/blob/v22.75.0/Source/DotNET/Arc.Core/Introspection/IntrospectionOptions.cs),
183
+ [DiscoveryExposure.cs](https://github.com/Cratis/Arc/blob/v22.75.0/Source/DotNET/Arc.Core/Introspection/DiscoveryExposure.cs),
184
+ [secure defaults](https://github.com/Cratis/Arc/blob/v22.75.0/Documentation/upgrading/secure-defaults.mdx).
189
185
 
190
186
  ## What is not here
191
187
 
@@ -15,7 +15,7 @@
15
15
  - The principal and system actors
16
16
  - Protected decisions and validators
17
17
 
18
- Verified against `Cratis.Arc.Core` and `Cratis.Arc` `22.41.1`. Everything below
18
+ Verified against `Cratis.Arc.Core` and `Cratis.Arc` `22.75.0`. Everything below
19
19
  describes that version and is in `Cratis.Arc.Authorization` unless stated.
20
20
 
21
21
  ## Versions differ — check the one you run
@@ -32,12 +32,18 @@ another.
32
32
  | `22.26.0` | `Cratis:Arc:Introspection` options. |
33
33
  | `22.30.0` | `IFallbackAuthorizationEvaluator` and `AuthorizationPolicyContext.ReceivedAt`. |
34
34
  | `22.31.0` | Opt-in policy evaluation for unauthenticated callers. |
35
+ | `22.31.2` | Identity/declaration continuity rechecked around policy evaluation. |
36
+ | `22.43.0` | Forwarded identity headers require host-wide trust opt-in. |
37
+ | `22.44.2` | Guest-policy endpoints reachable over HTTP, including with authenticated fallback. |
38
+ | `22.45.0` | Discovery anonymous only in Development by default. |
39
+ | `22.46.0` | Identity cookie no longer read or written by the backend. |
40
+ | `22.51.0` | `IdentityDiscovery` controls users/tenants/details schema separately. |
35
41
  | `22.39.0` | Protected decisions arrive; the validator boundary at the end of this page is verified at `22.41.1`. |
36
42
 
37
43
  If you are on a version before `22.21.0`, either upgrade, or use only Arc's
38
44
  attributes with roles and treat everything else as unenforced. Do not write a
39
45
  policy-protected endpoint on a version before `22.23.0`. The rest of this page
40
- is `22.41.1` behavior.
46
+ is `22.75.0` behavior.
41
47
 
42
48
  ## Attributes
43
49
 
@@ -142,10 +148,11 @@ opt-in:
142
148
  - Only a declaration made **entirely** of opted-in policies, with no roles and no
143
149
  schemes, can evaluate guests. Roles and schemes always require authentication.
144
150
 
145
- ⚠️ The opt-in governs Arc's pipeline verdict only. At `22.41.1` the HTTP layer can reject
146
- a guest before the policy runs: a Core host with any authentication handler, or an
147
- ASP.NET Core `FallbackPolicy` that requires authentication, returns 401 first
148
- (tracked in Cratis/Arc#2948). Test guest endpoints through the real HTTP host.
151
+ Since 22.44.2, guest-policy endpoints accept unauthenticated callers on both HTTP
152
+ hosts, even with an authenticated fallback policy, when every declared policy
153
+ opts in. Test through the real HTTP host, not only the in-process verdict.
154
+ Source at v22.75.0: `Documentation/backend/csharp/introspection/index.md` and the
155
+ host authorization specs under `Source/DotNET`.
149
156
 
150
157
  ⚠️ Because a method replaces its type, a method-level guest policy on a read model
151
158
  with a type-level `[Roles("Admin")]` is reachable by guests when the policy
@@ -316,4 +323,8 @@ service). So an authorization or ownership rule put in such a validator — or i
316
323
  `[Unprotected]` command's validator — is **not decision-safe**. Put
317
324
  state-dependent permission and ownership rules in `Provide()` or `Handle()` using
318
325
  `DecisionRead<T>` or `IDecisionReads`, and route to the validation and Chronicle
319
- guidance. Validators that read decision state are tracked in Arc#2831.
326
+ guidance. Arc constructs/certifies discoverable parameterless validators;
327
+ factory-supplied or altered rules fail closed. Keep static/service-locator state
328
+ out of them too: certification is not proof of input purity. Validators that
329
+ read decision state are tracked in Arc#2831.
330
+ Source: [Arc v22.75.0 protected validator boundary](https://github.com/Cratis/Arc/blob/v22.75.0/Documentation/backend/csharp/chronicle/read-models/injecting-into-commands.md).
@@ -0,0 +1,30 @@
1
+ # Cratis AuthProxy as the trusted ingress
2
+
3
+ Verified against Cratis AuthProxy `v2.30.5` (container image `cratis/authproxy`) and its documentation. AuthProxy is a reverse proxy that authenticates callers (OpenID Connect, JWT) and forwards the result to a backend in exactly the header contract Arc reads. It is the ingress the rest of this skill asks for. Other ingresses (Azure Container Apps or App Service EasyAuth, your own gateway) work if they meet the same four obligations; this page is specific to AuthProxy.
4
+
5
+ ## What it does to the headers
6
+
7
+ Before forwarding any request, AuthProxy removes every inbound header whose name begins `x-ms-client-principal` (whatever the suffix) and both tenant headers, `x-cratis-tenant-id` and the legacy `Tenant-ID`. For an authenticated caller it then writes its own:
8
+
9
+ | Header | Carries |
10
+ | --- | --- |
11
+ | `x-ms-client-principal` | The client principal, base64 JSON |
12
+ | `x-ms-client-principal-id` | The provider-local subject |
13
+ | `x-ms-client-principal-name` | The display name; `x-ms-client-principal-name*` holds the RFC 8187 form when the plain value cannot travel verbatim |
14
+ | `x-cratis-tenant-id` | The tenant AuthProxy resolved (absent when none resolved) |
15
+
16
+ An unauthenticated caller cannot smuggle identity headers downstream, and a client cannot choose the tenant a backend sees. AuthProxy also calls the backend's `GET /.cratis/me` with the same headers to enrich the identity, so a backend behind it must serve that endpoint (Arc does by default).
17
+
18
+ ## The one decision that cannot be fixed afterwards
19
+
20
+ The headers are **not signed**. A backend cannot tell a request that came through AuthProxy from one that did not, except by the network it arrived on. Only AuthProxy may be able to open a connection to the backend (private network, internal ingress, network policy); otherwise anyone can impersonate any user by sending the header, and everything still appears to work. This is the same trust boundary this skill describes for any ingress. Platform isolation recipes are in the AuthProxy documentation (`Documentation/azure`, `Documentation/aspire`).
21
+
22
+ ## `/.cratis/me` is an authorization decision
23
+
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
+
26
+ ## Tenants and services
27
+
28
+ 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.
29
+
30
+ AuthProxy still forwards the legacy `Tenant-ID` and `Service-ID` alongside `x-cratis-tenant-id` and `x-cratis-microservice` during a transition. That forwarding is deprecated and will be removed in a future major release: read the `x-cratis-*` names. Tenant resolution says which tenant the request is for; it is not an authorization decision and does not isolate storage (see [tenancy](tenancy.md)).
@@ -7,7 +7,7 @@
7
7
  - `RequireRole`
8
8
  - MVVM
9
9
 
10
- Verified against `@cratis/arc` and `@cratis/arc.react` `22.41.1`.
10
+ Verified against `@cratis/arc` and `@cratis/arc.react` `22.75.0`.
11
11
 
12
12
  ## `@cratis/arc/identity`
13
13
 
@@ -27,12 +27,13 @@ interface IIdentity<TDetails = object> {
27
27
 
28
28
  | Member | Notes |
29
29
  | --- | --- |
30
- | `static readonly CookieName = '.cratis-identity'` | The cookie `/.cratis/me` writes |
30
+ | `static readonly CookieName = '.cratis-identity'` | Deprecated legacy cookie name; current backend neither reads nor writes identity there |
31
31
  | `static setHttpHeadersCallback(callback)` | Headers to send on the refresh call |
32
32
  | `static setApiBasePath(path)` / `static setOrigin(origin)` | Where `/.cratis/me` lives |
33
- | `static getCurrent<TDetails>(type?)` | Reads the **cookie**, no network call |
33
+ | `static getCurrent<TDetails>(type?)` | Fetches `/.cratis/me`, caches a resolved identity in memory |
34
34
  | `static refresh<TDetails>(type?)` | Fetches `<apiBasePath>/.cratis/me` |
35
- | `static clearIdentityCookie()` | Expires the cookie |
35
+ | `static clearCache()` | Forgets memory cache and expires a legacy cookie; use on logout |
36
+ | `static clearIdentityCookie()` | Deprecated alias for `clearCache()` |
36
37
 
37
38
  `IIdentityProvider` is an abstract class with a single
38
39
  `getCurrent<TDetails>(type?)`, which is what a view model injects.
@@ -40,9 +41,11 @@ interface IIdentity<TDetails = object> {
40
41
  `IdentityProviderResult` on the wire is
41
42
  `{ id: string; name: string; roles: string[]; details: object }`.
42
43
 
43
- `getCurrent` reads the cookie and never touches the network. That is what makes
44
- it cheap, and also why nothing it returns is a security decision — the cookie is
45
- deliberately not `HttpOnly`, so the browser can read *and write* it.
44
+ `getCurrent` fetches once for a resolved identity; `refresh` always asks again.
45
+ Only a 404 enables the warned legacy-cookie fallback; a cookie never overrides
46
+ 401/403. Stop reading `.cratis-identity` in application code. Neither the memory
47
+ cache nor the legacy fallback is an authorization boundary.
48
+ Source: [Arc v22.75.0 IdentityProvider.ts](https://github.com/Cratis/Arc/blob/v22.75.0/Source/JavaScript/Arc/identity/IdentityProvider.ts).
46
49
 
47
50
  ## `@cratis/arc.react/identity`
48
51
 
@@ -102,8 +105,8 @@ Everything that is not an unambiguous yes renders `forbidden`:
102
105
  - the predicate throws;
103
106
  - an `allow` predicate with absent or `null` details.
104
107
 
105
- ⚠️ **This hides UI; it does not protect data.** The identity comes from a cookie
106
- the browser can edit, so anyone can render these children at will. Every query
108
+ ⚠️ **This hides UI; it does not protect data.** Identity comes from the endpoint,
109
+ but anyone can edit browser state and render these children at will. Every query
107
110
  and command behind the gate must carry its own `[Authorize]`/`[Roles]` on the
108
111
  server, where the decision cannot be edited.
109
112
 
@@ -1,6 +1,6 @@
1
1
  # Running with an identity locally
2
2
 
3
- Verified against `Cratis.Arc.Core` and `Cratis.Arc` `22.41.1`.
3
+ Verified against `Cratis.Arc.Core` and `Cratis.Arc` `22.75.0`.
4
4
 
5
5
  ## What Arc does not give you
6
6
 
@@ -28,18 +28,18 @@ public record User(ClientPrincipal MicrosoftIdentity, object Details);
28
28
  public interface ICanProvideUsers { Task<IEnumerable<User>> Provide(); }
29
29
  ```
30
30
 
31
- ⚠️ Both are mapped `AllowAnonymous` and **unconditionally** — there is no
32
- environment check in the mapper, so they are anonymous in Production too, and an
33
- ASP.NET `FallbackPolicy` does not protect them. Without providers they return
34
- empty arrays. Whatever your implementations return is public to anyone who can
35
- reach the application. The `Cratis:Arc:Introspection` options do not affect them;
36
- restrict them at the ingress (see the discovery note in the skill). Register them only for a development
37
- environment, and return fixtures rather than production users or tenants.
31
+ At **v22.75.0**, both follow `Introspection.IdentityDiscovery` and discovery
32
+ access settings: anonymous by default only in Development, authenticated elsewhere,
33
+ or unmapped (404) if the host cannot authenticate. Return development fixtures,
34
+ not production users or tenants.
35
+ Source: [secure defaults](https://github.com/Cratis/Arc/blob/v22.75.0/Documentation/upgrading/secure-defaults.mdx).
38
36
 
39
37
  ## Supplying an identity locally
40
38
 
41
39
  Because the shipped handler reads forwarded headers, the way to run with an
42
- identity locally is to send those headers yourself. All three are required:
40
+ identity locally is to send those headers yourself **after explicitly enabling**
41
+ `Cratis:Arc:TrustForwardedIdentityHeaders=true` in the isolated development host.
42
+ Without it they are ignored. All three are required:
43
43
 
44
44
  - `x-ms-client-principal-id`
45
45
  - `x-ms-client-principal-name`
@@ -9,7 +9,7 @@
9
9
  - Cost
10
10
  - What a guard does not protect
11
11
 
12
- Verified against `Cratis.Arc.Core` `22.41.1` (`Cratis.Arc.Queries`).
12
+ Verified against `Cratis.Arc.Core` `22.75.0` (`Cratis.Arc.Queries`).
13
13
 
14
14
  Authorization for an observable query runs **once, when the subscription is
15
15
  established**. It decides whether the caller may obtain the live stream. It does
@@ -42,7 +42,9 @@ public class SessionMustStillBeActive(ISessions sessions) : IGuardObservableQuer
42
42
  Arc API, and never an always-true stub.
43
43
 
44
44
  It runs on **every emission** of **every subscription**, on **every transport**:
45
- the multiplexed hub, WebSocket and SSE.
45
+ the multiplexed hub, WebSocket and SSE. Since 22.69.1 it also runs with
46
+ read-model interceptors on plain HTTP snapshots, waits and long polls.
47
+ Source: [Arc v22.75.0 ObservableQueryHttp.cs](https://github.com/Cratis/Arc/blob/v22.75.0/Source/DotNET/Arc.Core/Queries/ObservableQueryHttp.cs).
46
48
 
47
49
  ## Verdicts
48
50
 
@@ -104,9 +106,10 @@ a failure.
104
106
 
105
107
  ## What a guard does not protect
106
108
 
107
- - The HTTP **snapshot** path (`ObservableQueryHttp`, including
108
- `waitForFirstResult=true`) is not an emission guard path. Apply subscription-time
109
- authorization and safe data selection to every query.
109
+ - Plain HTTP **is** guarded at v22.75.0: suppression returns 202 until an allowed
110
+ emission (or the wait deadline), denial returns unauthorized with no data.
111
+ Before 22.69.1 that path was unguarded. Keep safe data selection and initial
112
+ authorization on every query regardless of transport.
110
113
  - A guard is not a substitute for the subscription-time declaration: the
111
114
  `[Authorize]`/`[Roles]`/policy on the read model still decides who may subscribe.
112
115
  - Interceptor masking is not an access control; the producer must never yield
@@ -1,6 +1,15 @@
1
1
  # Tenancy
2
2
 
3
- Verified against `Cratis.Arc.Core` `22.41.1`. Types are in `Cratis.Arc.Tenancy`.
3
+ ## Contents
4
+
5
+ - Constants
6
+ - Options and defaults
7
+ - The resolvers
8
+ - Reading the tenant
9
+ - Development listing
10
+ - Where the boundary is
11
+
12
+ Verified against `Cratis.Arc.Core` `22.75.0`. Types are in `Cratis.Arc.Tenancy`.
4
13
 
5
14
  Arc tenancy is **request-scoped tenant resolution**. It answers "which tenant is
6
15
  this request for". It is not Chronicle's tenant namespace isolation, and it does
@@ -64,6 +73,12 @@ the configured value.
64
73
  literal string `"[NotSet]"`. `TenantId.Default` is `"Default"`. ⚠️ `IsDefault`
65
74
  is `this == NotSet || this == Default` — it is true for an **unresolved** tenant
66
75
  as well, so it cannot tell "single-tenant default" from "nothing resolved".
76
+ Arc for .NET has no tenancy-required switch. Empty header/query resolution
77
+ becomes `NotSet`; Chronicle's `TenantNamespaceResolver` maps `IsDefault` (both
78
+ `NotSet` and `Default`) to its default namespace. Refuse unresolved tenants in
79
+ application authorization when required; resolution alone is not isolation.
80
+ Sources at Arc v22.75.0: `Arc.Core/Tenancy/TenancyOptions.cs` and
81
+ `Chronicle/Tenancy/TenantNamespaceResolver.cs` under `Source/DotNET`.
67
82
  Compare against `TenantId.NotSet` explicitly, or use
68
83
  `CurrentTenantIdIsNotSet.ThrowIfNotSet(...)`, wherever an unresolved tenant must
69
84
  be refused.
@@ -82,9 +97,10 @@ created after beginning it.
82
97
 
83
98
  `ICanProvideTenants` (`Task<IEnumerable<Tenant>> Provide()`) feeds
84
99
  `GET /.cratis/tenants`, where `Tenant` is `record (TenantId Id, TenantName Name)`.
85
- The endpoint is `AllowAnonymous` and mapped unconditionally — also in Production,
86
- and an ASP.NET fallback policy does not protect it — so an implementation that
87
- returns real tenants publishes them. Return development fixtures only.
100
+ The endpoint follows `Introspection.IdentityDiscovery` and discovery access:
101
+ anonymous only in Development by default, authenticated elsewhere, or unmapped
102
+ when the host cannot authenticate. Return development fixtures only.
103
+ Source: [Arc v22.75.0 secure defaults](https://github.com/Cratis/Arc/blob/v22.75.0/Documentation/upgrading/secure-defaults.mdx).
88
104
 
89
105
  ## Where the boundary is
90
106
 
@@ -26,18 +26,24 @@ or a combination.
26
26
 
27
27
  | Package | Version | Purpose |
28
28
  | --- | --- | --- |
29
- | `Cratis.Arc.Core` | `22.16.0` | `Cratis.Arc.Commands.ModelBound.CommandAttribute`, `CommandResult`, `CommandValidator<T>` |
30
- | `Cratis.Arc.Chronicle` | `22.16.0` | event append handling, `Cratis.Arc.Chronicle.Commands.NotAuditedAttribute` |
31
- | `Cratis.Arc.ProxyGenerator.Build` | `22.16.0` | `CratisProxiesOutputPath` MSBuild integration |
32
- | `Cratis.Fundamentals` | `7.19.2` | `Cratis.Monads.Result<TResult, TError>` |
29
+ | `Cratis.Arc.Core` | `22.75.0` | `Cratis.Arc.Commands.ModelBound.CommandAttribute`, `CommandResult`, `CommandValidator<T>` |
30
+ | `Cratis.Arc.Chronicle` | `22.75.0` | event append handling, `Cratis.Arc.Chronicle.Commands.NotAuditedAttribute` |
31
+ | `Cratis.Arc.ProxyGenerator.Build` | `22.75.0` | `CratisProxiesOutputPath` MSBuild integration |
32
+ | `Cratis.Fundamentals` | `7.23.0` | `Cratis.Monads.Result<TResult, TError>` |
33
33
  | `Cratis.Chronicle` | `18.3.0` | `EventTypeAttribute`, `EventForEventSourceId`, `ICanProvideEventSourceId` |
34
- | `@cratis/arc` | `22.16.0` | `ICommand`, `CommandResult`, `ValidationResult` |
34
+ | `@cratis/arc` | `22.75.0` | `ICommand`, `CommandResult`, `ValidationResult` |
35
35
 
36
- > 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.
36
+ > Arc surface rechecked at v22.75.0, including the source-pinned references below.
37
+ > Arc's package dependency is Chronicle 19.39.1 / Fundamentals 7.23.0; separately
38
+ > version-qualified Chronicle/Fundamentals claims retain their own verification.
39
+
40
+ Fundamentals rechecked at v7.23.0 in
41
+ [`Result<TResult, TError>`](https://github.com/Cratis/Fundamentals/blob/v7.23.0/Source/DotNET/Fundamentals/Monads/Result%7BTResult,TError%7D.cs):
42
+ success is first, error second, with implicit conversions from both types.
37
43
 
38
44
  Reverify before claiming support for another version. Arc without Chronicle is a
39
45
  supported setup; everything on this page that appends events needs Chronicle.
40
- Operation guidance below is verified at **Arc v22.48.1**; see
46
+ Operation guidance below is rechecked at **Arc v22.75.0**; see
41
47
  `cratis-arc-command-operation` for its source and recovery contract.
42
48
 
43
49
  ## Declare the command
@@ -126,7 +132,7 @@ processes a non-null result, so a `null` is success with nothing appended and th
126
132
  caller is told a command succeeded that never happened. Missing state or a failed
127
133
  rule is a rejection: return `Result<TEvent, ValidationResult>` with
128
134
  `ValidationResult.Error(...)`, or reject in a validator or `Provide()`. Optional
129
- `ICommandOperation` returns are a separate contract and unaffected. A nullable
135
+ `ICommandOperation` returns are a separate contract and unaffected. `ARCCHR0015` warns on nullable event returns. A nullable
130
136
  read-model parameter (`ARC0006`) is handled by rejecting, never by returning a
131
137
  nullable event.
132
138
 
@@ -166,7 +172,7 @@ public record Transfer(<AccountId> From, <AccountId> To, <Money> Amount)
166
172
 
167
173
  ## Generate a server-owned new identifier
168
174
 
169
- **Arc 22.66.0+**, verified at **v22.68.0**: the create-command example above
175
+ **Arc 22.66.0+**, verified at **v22.75.0**: the create-command example above
170
176
  requires `<ThingId>` to implement `IGeneratable<ThingId>` with a static `New()`
171
177
  strategy (Fundamentals 7.23.0+; see `cratis-fundamentals-concept`). Replace
172
178
  `Guid.NewGuid()` or `<ThingId>.New()` inside `Handle()` with a generated parameter,
@@ -201,6 +207,17 @@ A command with more than one candidate property is ambiguous and `ARCCHR0002`
201
207
  warns; implement `ICanProvideEventSourceId` to say which value wins. Do not rely
202
208
  on property order.
203
209
 
210
+ `[Key]` on a positional record's primary-constructor parameter is recognized
211
+ and counted once. Child-only/nested read-model types are not standalone
212
+ command-scoped models. `[EventSource<TSource>(stream)]` supplies source type and
213
+ stream metadata on commands and aggregate roots.
214
+
215
+ Read [decisions and routing](references/decisions-and-routing.md) when a command
216
+ needs guarded state, stream-id templates, definition-backed routes, event tags or
217
+ post-commit `CompleteStream`. Plain read-model injection remains advisory;
218
+ `Result<,>` alone is not concurrency protection. Explicit routing on a returned
219
+ `EventForEventSourceId` wins over command context.
220
+
204
221
  Two attributes are spelled `[Key]`. Chronicle reads `Cratis.Chronicle.Keys.KeyAttribute`.
205
222
  Marking `System.ComponentModel.DataAnnotations.KeyAttribute` in an application
206
223
  that uses Chronicle compiles, resolves nothing, and silently invents a new event
@@ -283,7 +300,7 @@ either way, so the reading is all a reviewer has to go on.
283
300
  ## Generate the TypeScript proxy
284
301
 
285
302
  ```xml
286
- <PackageReference Include="Cratis.Arc.ProxyGenerator.Build" Version="22.16.0" />
303
+ <PackageReference Include="Cratis.Arc.ProxyGenerator.Build" Version="22.75.0" />
287
304
 
288
305
  <PropertyGroup>
289
306
  <CratisProxiesOutputPath>$(MSBuildThisFileDirectory)../<Web>/src/api</CratisProxiesOutputPath>
@@ -295,6 +312,11 @@ either way, so the reading is all a reviewer has to go on.
295
312
  file path. When configuring proxy generation or diagnosing missing or stale output, read [proxy generation](references/proxy-generation.md) for the full
296
313
  set of MSBuild knobs and the common failures.
297
314
 
315
+ `[BlockOnValidationSeverity(ValidationResultSeverity.Warning)]` declares the
316
+ lowest blocking severity for validation, `Provide` and execution. Caller
317
+ `allowedSeverity`/`X-Allowed-Severity` can only make it stricter; `Unknown` blocks.
318
+ The proxy carries `blockOnValidationSeverity` and honors it client-side.
319
+
298
320
  ## The generated client contract
299
321
 
300
322
  The generated proxy is a `Command` from `@cratis/arc`. Its members are the same
@@ -7,7 +7,9 @@
7
7
  - Client side
8
8
  - Executing with a severity
9
9
 
10
- Verified against `Cratis.Arc.Core` `22.16.0` and `@cratis/arc` `22.16.0`.
10
+ Verified against `Cratis.Arc.Core` and `@cratis/arc` **v22.75.0**.
11
+ Sources: `Source/DotNET/Arc.Core/Commands/CommandResult.cs`,
12
+ `CommandValidationResults.cs` and `Source/JavaScript/Arc/commands/Command.ts`.
11
13
 
12
14
  ## Server side
13
15
 
@@ -43,10 +45,15 @@ value into the error body.
43
45
  `ValidationResultSeverity`: `Unknown = 0`, `Information = 1`, `Warning = 2`,
44
46
  `Error = 3`.
45
47
 
46
- Only *blocking* results survive onto the result. With no `allowedSeverity`, only
47
- `Error` blocks — information and warnings are filtered out entirely. With an
48
- `allowedSeverity`, anything strictly greater than it blocks. So passing
49
- `Warning` keeps errors blocking and lets warnings through.
48
+ Only *blocking* results survive onto the result. For an unannotated command,
49
+ with no `allowedSeverity`, only `Error` blocks; with a caller threshold, anything
50
+ strictly greater blocks. `[BlockOnValidationSeverity(ValidationResultSeverity.Warning)]`
51
+ (`Cratis.Arc.Commands.ModelBound`) declares an inclusive blocking floor across
52
+ HTTP, Validate, Provide and in-process execution. Caller `X-Allowed-Severity` or
53
+ `allowedSeverity` can tighten, never loosen, that floor; attributed commands
54
+ also block `Unknown`. The generated proxy carries `blockOnValidationSeverity`
55
+ and applies it client-side. This attribute does not change an unannotated
56
+ command's legacy filtering.
50
57
 
51
58
  ## Client side
52
59
 
@@ -0,0 +1,95 @@
1
+ # Protected decisions and routed streams
2
+
3
+ <!-- Copyright (c) Cratis. All rights reserved. -->
4
+ <!-- Licensed under the MIT license. See LICENSE file in the project root for full license information. -->
5
+
6
+ Verified at **Arc v22.75.0**. These features require `Cratis.Arc.Chronicle`.
7
+
8
+ ## Pick the guarded read
9
+
10
+ Plain injected read models and `IReadModels.GetInstanceById` are advisory. A
11
+ `Result<TEvent, ValidationResult>` rejects a request but does not enroll a guard.
12
+
13
+ - For one stream, inject `IStreamReads` into `Provide`, call `ForCommand()`, and
14
+ return `StreamDecision.Append(...)` from `Handle`. It returns
15
+ `EventsWithConcurrencyScopes`, retaining the read route and exact tail. A
16
+ competing append conflicts, including two competing first appends.
17
+ - For projected state, opt in with `[ProtectedDecision]` in
18
+ `Cratis.Arc.Chronicle.ReadModels`, then inject `DecisionRead<T>` into
19
+ `Provide`/`Handle` (`Exists`/`Instance`). Command-aware `IDecisionReads.Get<T>`
20
+ enrolls reads of other keys. Only Chronicle-admitted direct event-source-keyed
21
+ projections with a known event-type set qualify; reducers, joins, children,
22
+ passive and incomplete definitions are refused. Arc certifies parameterless
23
+ validators it constructs; constructor dependencies and uncertified instances
24
+ are refused. Keep all decision state out of validators, including static
25
+ members and service locators. `[Unprotected]` on the command opts out; never
26
+ combine it with `[ProtectedDecision]`. A parameter-level marker acknowledges
27
+ tooling, not a runtime opt-out. `Validate` is advisory, not a commit promise.
28
+ - Automatic `concurrency: true` on the routing attributes supplies stream-level
29
+ scopes. Exact returned scopes replace automatic capture; remove the flags
30
+ when returning `EventsWithConcurrencyScopes` (ARCCHR0016).
31
+
32
+ Do not manually append or commit to bypass the owner-capable unit of work.
33
+ Protection does not guard foreign writers, external state, revisions, redactions,
34
+ migrations or changes to projection definitions. A successful empty protected
35
+ command still validates enrolled reads. In contrast, `StreamDecision.Append([])`
36
+ returns no scopes: use it only for an identical retry, not a rejected request.
37
+
38
+ ## Definition-backed routes and templates
39
+
40
+ `[EventSource<TSource>(stream)]` supplies source type and stream metadata on
41
+ commands and aggregate roots from a discovered definition. ARCCHR0013 recommends
42
+ it; ARCCHR0014 flags observer streams absent from that definition.
43
+
44
+ `[EventStreamId("{ReportingScopeId}:{Period}")]` resolves a command template after
45
+ validation. Concept properties contribute underlying values.
46
+ `EventStreamIdTemplate.ResolveFor(command)` exposes the same resolution.
47
+ ARCCHR0017/0018 check invalid templates/properties. On reactors the value is
48
+ literal, not a command template. `AmbiguousEventStreamId` rejects a non-NotSet
49
+ attribute value combined with `ICanProvideEventStreamId`, **including templates**.
50
+ Choose the attribute or the interface, not both. Source:
51
+ [EventStreamIdTemplate.cs](https://github.com/Cratis/Arc/blob/v22.75.0/Source/DotNET/Chronicle/Commands/EventStreamIdTemplate.cs).
52
+
53
+ `IEventRoutes.For<TSource>(stream).WithStreamId(value)` resolves an `EventRoute`;
54
+ `IStreamReads.Stream(id, route)` guards that route, while `StreamType(id, route)`
55
+ guards every stream id of its type. Both require a specific source, stream type
56
+ and append stream id. There is only one exact scope per source id: do not combine
57
+ two independent stream decisions for the same source and assume both are guarded.
58
+ `route.Route(id, fact)` produces a routing wrapper. Explicit routing on a returned
59
+ `EventForEventSourceId` wins over command context in every return shape.
60
+
61
+ ## Tags and completion
62
+
63
+ In `Cratis.Arc.Chronicle.Commands`, `[EventTag("projectId", nameof(ProjectId))]`
64
+ takes a property and `[EventTag("origin", Value = "import")]` a constant. Each
65
+ attribute must have exactly one source. `ICanProvideEventTags` computes command
66
+ tags; returned `EventTags` supplies handler-known tags; discovered scoped/transient
67
+ `ICanProvideCommandEventTags` providers add application conventions. All sources
68
+ form a union distinct by name/value pair; wrapper tags are preserved. Tags apply
69
+ to returned events, not manual appends or aggregate commits.
70
+
71
+ Return `CompleteStream` (`Cratis.Arc.Chronicle.Streams`) alone or with events in
72
+ a command tuple. It completes **after commit**, not atomically with append.
73
+ Completion is keyed by stream type/id across the entire event log, not source id.
74
+ A failure leaves earlier events committed; retry completion rather than blindly
75
+ duplicating events. Reactors may return it directly, using the observed route;
76
+ reactor tuples/collections cannot mix it with events.
77
+
78
+ ## Decision specifications
79
+
80
+ Call `new CommandScenario<T>().UseDecisionReads()` before seeding events.
81
+ `Given.ForEventSource(id).OnRoute(route).Events(...)` and
82
+ `AppendConcurrently(id, route, ...)` share one real in-process log. Pinned models
83
+ cannot supply guards. Assert a real nonempty decision conflicts on the intended
84
+ route, and that an independent route is not over-guarded.
85
+ `ShouldHaveCompletedStream(type, id)` asserts completion;
86
+ `DecisionReadAdmissions.ShouldAdmitDecisionReadsIn(assembly)` checks projection
87
+ admission in assembly-level specs.
88
+
89
+ ## Sources at v22.75.0
90
+
91
+ - [Stream decisions](https://github.com/Cratis/Arc/blob/v22.75.0/Documentation/backend/csharp/chronicle/commands/stream-decisions.md)
92
+ - [Protected read-model decisions and limitations](https://github.com/Cratis/Arc/blob/v22.75.0/Documentation/backend/csharp/chronicle/read-models/injecting-into-commands.md)
93
+ - [Concurrency and templates](https://github.com/Cratis/Arc/blob/v22.75.0/Documentation/backend/csharp/chronicle/commands/concurrency.md)
94
+ - [Event tags](https://github.com/Cratis/Arc/blob/v22.75.0/Documentation/backend/csharp/chronicle/commands/event-tags.md)
95
+ - [Completing streams](https://github.com/Cratis/Arc/blob/v22.75.0/Documentation/backend/csharp/chronicle/commands/completing-streams.md)
@@ -102,7 +102,7 @@ ordinary response, event and compliance contracts.
102
102
 
103
103
  ## Analyzer diagnostics
104
104
 
105
- Arc v22.68.0 reports these at compile time; none has a code fix. Runtime
105
+ Arc v22.75.0 reports these at compile time; none has a code fix. Runtime
106
106
  handler-construction checks remain for declarations compiled without analyzers.
107
107
 
108
108
  | Diagnostic | Severity | Fix |
@@ -154,7 +154,8 @@ Published guides:
154
154
  [ARC0024](/arc/backend/csharp/code-analysis/arc0024/),
155
155
  [ARC0025](/arc/backend/csharp/code-analysis/arc0025/).
156
156
 
157
- Source at **Arc v22.68.0**: `Source/DotNET/Arc.Core/Commands/ModelBound/GeneratedValueAttribute.cs`,
157
+ Source rechecked at **Arc v22.75.0** (generation/pinning APIs unchanged since
158
+ the prior verification): `Source/DotNET/Arc.Core/Commands/ModelBound/GeneratedValueAttribute.cs`,
158
159
  `Commands/GeneratedValueParameters.cs`, `GeneratedValueFactories.cs`,
159
160
  `CommandHandlerArgumentResolver.cs`, `GeneratedValueResolution.cs`;
160
161
  `Source/DotNET/Arc.Core.CodeAnalysis/DiagnosticDescriptors.cs`; and