@cratis/pi 7.34.1 → 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.
- package/package/corpus/agents/security-reviewer.md +1 -0
- package/package/corpus/agents/spec-writer.md +1 -1
- package/package/corpus/harnesses/pi/extensions/shared/rules.ts +3 -1
- package/package/corpus/hooks/scripts/cratis-nuget-pins.txt +7 -6
- package/package/corpus/hooks/scripts/cratis-release-notes-reviewed.cjs +7 -6
- package/package/corpus/hooks/scripts/cratis-store-mutations.json +7 -3
- package/package/corpus/product-sync.json +896 -0
- package/package/corpus/prompts/add-business-rule.prompt.md +1 -1
- package/package/corpus/prompts/ship-changes.prompt.md +2 -2
- package/package/corpus/rules/ai-distribution.md +31 -3
- package/package/corpus/rules/application-profile.md +2 -1
- package/package/corpus/rules/components.md +66 -7
- package/package/corpus/rules/concepts.md +11 -3
- package/package/corpus/rules/csharp.md +3 -1
- package/package/corpus/rules/dialogs.md +9 -0
- package/package/corpus/rules/efcore.md +1 -1
- package/package/corpus/rules/elixir.md +49 -0
- package/package/corpus/rules/framework.md +5 -3
- package/package/corpus/rules/general.md +1 -0
- package/package/corpus/rules/glossary.md +4 -4
- package/package/corpus/rules/go-engineering.md +60 -0
- package/package/corpus/rules/go.md +115 -0
- package/package/corpus/rules/java.md +5 -2
- package/package/corpus/rules/kotlin.md +7 -5
- package/package/corpus/rules/orleans.md +65 -9
- package/package/corpus/rules/profiles.md +43 -6
- package/package/corpus/rules/pull-requests.md +3 -3
- package/package/corpus/rules/react.md +8 -1
- package/package/corpus/rules/reactors.md +27 -3
- package/package/corpus/rules/specs.csharp.md +11 -4
- package/package/corpus/rules/specs.scenarios.csharp.md +35 -4
- package/package/corpus/rules/specs.typescript.md +2 -1
- package/package/corpus/rules/storybook.md +1 -1
- package/package/corpus/rules/typescript.md +1 -1
- package/package/corpus/rules/vertical-slices.md +37 -5
- package/package/corpus/skills/cratis-application-react-specifications/SKILL.md +4 -2
- package/package/corpus/skills/cratis-application-slice-specifications/SKILL.md +18 -8
- package/package/corpus/skills/cratis-application-slice-specifications/references/query-and-decision-scenarios.md +65 -0
- package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/SKILL.md +53 -57
- package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/authentication.md +38 -42
- package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/authorization.md +18 -7
- package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/authproxy.md +30 -0
- package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/frontend.md +12 -9
- package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/local-development.md +9 -9
- package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/observable-emission-guards.md +8 -5
- package/package/corpus/skills/cratis-arc-authentication-authorization-and-identity/references/tenancy.md +20 -4
- package/package/corpus/skills/cratis-arc-command/SKILL.md +32 -10
- package/package/corpus/skills/cratis-arc-command/references/command-result.md +12 -5
- package/package/corpus/skills/cratis-arc-command/references/decisions-and-routing.md +95 -0
- package/package/corpus/skills/cratis-arc-command/references/generated-values.md +3 -2
- package/package/corpus/skills/cratis-arc-command/references/handler-shapes.md +8 -8
- package/package/corpus/skills/cratis-arc-command/references/proxy-generation.md +22 -3
- package/package/corpus/skills/cratis-arc-command/references/read-model-injection.md +13 -1
- package/package/corpus/skills/cratis-arc-command-execution/SKILL.md +19 -9
- package/package/corpus/skills/cratis-arc-command-kotlin/SKILL.md +44 -18
- package/package/corpus/skills/cratis-arc-command-kotlin/references/read-model-naming.md +29 -0
- package/package/corpus/skills/cratis-arc-command-operation/SKILL.md +10 -9
- package/package/corpus/skills/cratis-arc-command-operation/references/execution-and-recovery.md +2 -2
- package/package/corpus/skills/cratis-arc-command-operation/references/testing.md +4 -3
- package/package/corpus/skills/cratis-arc-command-typescript/SKILL.md +42 -22
- package/package/corpus/skills/cratis-arc-command-typescript/references/chronicle-events.md +36 -5
- package/package/corpus/skills/cratis-arc-command-typescript/references/command-operations.md +114 -0
- package/package/corpus/skills/cratis-arc-command-typescript/references/hosting-and-storage.md +37 -16
- package/package/corpus/skills/cratis-arc-command-typescript/references/identity-and-introspection.md +88 -0
- package/package/corpus/skills/cratis-arc-command-typescript/references/observability-and-host-scopes.md +25 -0
- package/package/corpus/skills/cratis-arc-command-typescript/references/proxy-generation.md +35 -4
- package/package/corpus/skills/cratis-arc-command-typescript/references/slice-layout.md +11 -0
- package/package/corpus/skills/cratis-arc-command-typescript/verification.json +8 -1
- package/package/corpus/skills/cratis-arc-command-validation/SKILL.md +49 -19
- package/package/corpus/skills/cratis-arc-ef-core-migration/SKILL.md +12 -6
- package/package/corpus/skills/cratis-arc-go/SKILL.md +148 -0
- package/package/corpus/skills/cratis-arc-go/references/queries.md +80 -0
- package/package/corpus/skills/cratis-arc-hosting/SKILL.md +96 -0
- package/package/corpus/skills/cratis-arc-hosting/references/integrations-and-publish.md +80 -0
- package/package/corpus/skills/cratis-arc-identity-and-tenancy-kotlin/SKILL.md +137 -0
- package/package/corpus/skills/cratis-arc-observable-query-http/SKILL.md +20 -2
- package/package/corpus/skills/cratis-arc-query-kotlin/SKILL.md +26 -6
- package/package/corpus/skills/cratis-arc-query-paging/SKILL.md +25 -20
- package/package/corpus/skills/cratis-arc-query-typescript/SKILL.md +32 -6
- package/package/corpus/skills/cratis-arc-query-typescript/references/storage-observation-and-compliance.md +66 -0
- package/package/corpus/skills/cratis-arc-query-typescript/verification.json +5 -1
- package/package/corpus/skills/cratis-arc-react-page/SKILL.md +24 -13
- package/package/corpus/skills/cratis-arc-react-page/references/data-page.md +20 -10
- package/package/corpus/skills/cratis-arc-react-page/references/data-tables.md +17 -3
- package/package/corpus/skills/cratis-arc-react-page/references/dialogs.md +14 -3
- package/package/corpus/skills/cratis-arc-react-page/references/from-screenplay.md +6 -1
- package/package/corpus/skills/cratis-arc-react-page/references/provenance.md +1 -1
- package/package/corpus/skills/cratis-arc-react-page/references/queries-and-commands.md +11 -1
- package/package/corpus/skills/cratis-arc-react-page/verification.json +6 -1
- package/package/corpus/skills/cratis-arc-spring-data-kotlin/SKILL.md +163 -0
- package/package/corpus/skills/cratis-arc-testing-kotlin/SKILL.md +131 -0
- package/package/corpus/skills/cratis-arc-validation-kotlin/SKILL.md +44 -11
- package/package/corpus/skills/cratis-arc-validation-typescript/SKILL.md +5 -3
- package/package/corpus/skills/cratis-chronicle-cli-operations/SKILL.md +79 -25
- package/package/corpus/skills/cratis-chronicle-cli-operations/references/command-effects.md +57 -0
- package/package/corpus/skills/cratis-chronicle-client-dotnet/SKILL.md +87 -99
- package/package/corpus/skills/cratis-chronicle-client-dotnet/references/additional-surfaces.md +65 -0
- package/package/corpus/skills/cratis-chronicle-client-dotnet/references/client-construction.md +42 -0
- package/package/corpus/skills/cratis-chronicle-client-dotnet/references/compatibility-check.md +12 -0
- package/package/corpus/skills/cratis-chronicle-client-dotnet/references/discovery.md +43 -19
- package/package/corpus/skills/cratis-chronicle-client-dotnet/references/hosting.md +29 -1
- package/package/corpus/skills/cratis-chronicle-client-elixir/SKILL.md +158 -162
- package/package/corpus/skills/cratis-chronicle-client-elixir/references/append-api.md +36 -15
- package/package/corpus/skills/cratis-chronicle-client-elixir/references/compliance.md +32 -0
- package/package/corpus/skills/cratis-chronicle-client-elixir/references/connections.md +56 -0
- package/package/corpus/skills/cratis-chronicle-client-elixir/references/event-sources.md +64 -0
- package/package/corpus/skills/cratis-chronicle-client-elixir/references/pitfalls.md +25 -0
- package/package/corpus/skills/cratis-chronicle-client-elixir/references/projections.md +48 -0
- package/package/corpus/skills/cratis-chronicle-client-elixir/references/upgrading.md +34 -0
- package/package/corpus/skills/cratis-chronicle-client-elixir/references/variants.md +13 -5
- package/package/corpus/skills/cratis-chronicle-client-elixir/verification.json +23 -0
- package/package/corpus/skills/cratis-chronicle-client-go/SKILL.md +162 -0
- package/package/corpus/skills/cratis-chronicle-client-go/references/projections.md +73 -0
- package/package/corpus/skills/cratis-chronicle-client-kotlin/SKILL.md +87 -88
- package/package/corpus/skills/cratis-chronicle-client-kotlin/references/connection-lifecycle.md +13 -0
- package/package/corpus/skills/cratis-chronicle-client-kotlin/references/discovery-and-registration.md +14 -4
- package/package/corpus/skills/cratis-chronicle-client-kotlin/references/event-sources.md +65 -0
- package/package/corpus/skills/cratis-chronicle-client-kotlin/references/options.md +29 -0
- package/package/corpus/skills/cratis-chronicle-client-kotlin/references/spring-boot.md +13 -0
- package/package/corpus/skills/cratis-chronicle-client-kotlin/references/variants.md +5 -4
- package/package/corpus/skills/cratis-chronicle-client-typescript/SKILL.md +165 -156
- package/package/corpus/skills/cratis-chronicle-client-typescript/references/read-models-and-projections.md +54 -11
- package/package/corpus/skills/cratis-chronicle-client-typescript/references/testing.md +126 -0
- package/package/corpus/skills/cratis-chronicle-client-typescript/references/variants.md +3 -5
- package/package/corpus/skills/cratis-chronicle-client-typescript/verification.json +19 -0
- package/package/corpus/skills/cratis-chronicle-compliance/SKILL.md +36 -13
- package/package/corpus/skills/cratis-chronicle-decision-reads/SKILL.md +110 -0
- package/package/corpus/skills/cratis-chronicle-decision-reads/references/admission-and-ownership.md +57 -0
- package/package/corpus/skills/cratis-chronicle-decision-reads/verification.json +12 -0
- package/package/corpus/skills/cratis-chronicle-event-constraints/SKILL.md +58 -19
- package/package/corpus/skills/cratis-chronicle-event-constraints/references/closing-streams.md +73 -0
- package/package/corpus/skills/cratis-chronicle-event-modeling/SKILL.md +32 -3
- package/package/corpus/skills/cratis-chronicle-event-specifications/SKILL.md +18 -5
- package/package/corpus/skills/cratis-chronicle-event-type-migration/SKILL.md +32 -2
- package/package/corpus/skills/cratis-chronicle-hosting/SKILL.md +134 -0
- package/package/corpus/skills/cratis-chronicle-hosting/references/operations.md +89 -0
- package/package/corpus/skills/cratis-chronicle-hosting/verification.json +14 -0
- package/package/corpus/skills/cratis-chronicle-mcp-inspection/SKILL.md +93 -66
- package/package/corpus/skills/cratis-chronicle-mcp-inspection/references/blocked-tools.md +21 -7
- package/package/corpus/skills/cratis-chronicle-mcp-inspection/references/deployment.md +77 -0
- package/package/corpus/skills/cratis-chronicle-mcp-inspection/references/observational-tools.md +46 -4
- package/package/corpus/skills/cratis-chronicle-multi-tenancy/SKILL.md +15 -1
- package/package/corpus/skills/cratis-chronicle-projection/SKILL.md +44 -10
- package/package/corpus/skills/cratis-chronicle-projection/references/fluent-builder.md +7 -1
- package/package/corpus/skills/cratis-chronicle-projection/references/model-bound-attributes.md +8 -0
- package/package/corpus/skills/cratis-chronicle-reactor/SKILL.md +85 -105
- package/package/corpus/skills/cratis-chronicle-reactor/references/specifications.md +20 -1
- package/package/corpus/skills/cratis-chronicle-read-model/SKILL.md +2 -2
- package/package/corpus/skills/cratis-chronicle-read-model/references/queries.md +35 -16
- package/package/corpus/skills/cratis-chronicle-read-model-specifications/SKILL.md +15 -3
- package/package/corpus/skills/cratis-chronicle-reducer/SKILL.md +23 -4
- package/package/corpus/skills/cratis-chronicle-web-workbench/SKILL.md +40 -15
- package/package/corpus/skills/cratis-cli-terminal-workbench/SKILL.md +20 -6
- package/package/corpus/skills/cratis-code-review/SKILL.md +25 -3
- package/package/corpus/skills/cratis-components-accessibility/SKILL.md +20 -4
- package/package/corpus/skills/cratis-components-schema-editor/SKILL.md +40 -28
- package/package/corpus/skills/cratis-components-schema-editor/references/tree-layout.md +62 -0
- package/package/corpus/skills/cratis-components-schema-editor/verification.json +14 -0
- package/package/corpus/skills/cratis-components-stepper-command-dialog/SKILL.md +16 -8
- package/package/corpus/skills/cratis-components-styling/SKILL.md +57 -20
- package/package/corpus/skills/cratis-components-styling/verification.json +13 -0
- package/package/corpus/skills/cratis-components-toolbar/SKILL.md +37 -7
- package/package/corpus/skills/cratis-components-toolbar/verification.json +12 -0
- package/package/corpus/skills/cratis-engineering-csharp-conventions/SKILL.md +6 -0
- package/package/corpus/skills/cratis-engineering-csharp-conventions/references/exceptions-logging-and-di.md +5 -3
- package/package/corpus/skills/cratis-fundamentals-concept/SKILL.md +19 -6
- package/package/corpus/skills/cratis-fundamentals-concept/references/typescript-concepts.md +97 -0
- package/package/corpus/skills/cratis-fundamentals-concept/verification.json +4 -1
- package/package/corpus/skills/cratis-fundamentals-concept-go/SKILL.md +112 -0
- package/package/corpus/skills/cratis-fundamentals-type-discovery/SKILL.md +54 -17
- package/package/corpus/skills/cratis-fundamentals-type-discovery/verification.json +14 -0
- package/package/corpus/skills/cratis-lens-browser-extension/SKILL.md +55 -28
- package/package/corpus/skills/cratis-performance-review/SKILL.md +5 -2
- package/package/corpus/skills/cratis-release-notes/SKILL.md +3 -1
- package/package/corpus/skills/cratis-screenplay-automations-and-translations/SKILL.md +5 -4
- package/package/corpus/skills/cratis-screenplay-command-surface/SKILL.md +5 -6
- package/package/corpus/skills/cratis-screenplay-command-surface/references/compliance.md +24 -6
- package/package/corpus/skills/cratis-screenplay-command-surface/references/enum-numbers.md +4 -2
- package/package/corpus/skills/cratis-screenplay-command-surface/references/generated-values-and-responses.md +4 -1
- package/package/corpus/skills/cratis-screenplay-event-modeling/SKILL.md +3 -2
- package/package/corpus/skills/cratis-screenplay-event-modeling/references/parsed-not-runnable.md +2 -2
- package/package/corpus/skills/cratis-screenplay-legacy-extraction/SKILL.md +1 -0
- package/package/corpus/skills/cratis-screenplay-legacy-extraction/references/generate-notes.md +34 -4
- package/package/corpus/skills/cratis-screenplay-model-authoring/SKILL.md +5 -3
- package/package/corpus/skills/cratis-screenplay-model-authoring/references/language-reference.md +1 -1
- package/package/corpus/skills/cratis-screenplay-model-authoring/references/mcp-tools.md +4 -2
- package/package/corpus/skills/cratis-screenplay-model-authoring/references/property-links.md +42 -3
- package/package/corpus/skills/cratis-screenplay-model-authoring/verification.json +3 -1
- package/package/corpus/skills/cratis-screenplay-render-and-gap-fill/references/gap-fill-handoff.md +3 -1
- package/package/corpus/skills/cratis-screenplay-scenario-coverage/SKILL.md +3 -1
- package/package/corpus/skills/cratis-screenplay-specifications/references/examples-and-routes.md +48 -0
- package/package/corpus/skills/cratis-screenplay-specifications/verification.json +3 -1
- package/package/corpus/skills/cratis-screenplay-streams-and-consistency/SKILL.md +4 -2
- package/package/corpus/skills/cratis-screenplay-streams-and-consistency/references/streams-example.md +5 -4
- package/package/corpus/skills/cratis-screenplay-toolchain/SKILL.md +8 -6
- package/package/corpus/skills/cratis-screenplay-toolchain/references/cheat-sheet-example.md +2 -2
- package/package/corpus/skills/cratis-screenplay-toolchain/references/diagnostics.md +4 -2
- package/package/corpus/skills/cratis-screenplay-toolchain/references/doc-contradictions.md +1 -1
- package/package/corpus/skills/cratis-screenplay-toolchain/references/executable-subset.md +16 -11
- package/package/corpus/skills/cratis-screenplay-toolchain/references/renderable-subset.md +5 -2
- package/package/corpus/skills/cratis-screenplay-toolchain/references/screenplay-contract.json +1329 -32
- package/package/corpus/skills/cratis-screenplay-toolchain/references/screenplay-contract.version +1 -1
- package/package/corpus/skills/cratis-screenplay-toolchain/references/verdicts.md +2 -2
- package/package/corpus/skills/cratis-screenplay-toolchain/references/versions.md +23 -7
- package/package/corpus/skills/cratis-screenplay-toolchain/verification.json +1 -1
- package/package/corpus/skills/cratis-screenplay-ui-composition/SKILL.md +2 -0
- package/package/corpus/skills/cratis-screenplay-ui-composition/references/screen-composition-contract.md +27 -9
- package/package/corpus/skills/cratis-security-review/SKILL.md +9 -3
- package/package/corpus/skills/cratis-security-review/references/arc-boundaries.md +59 -0
- package/package/corpus/skills/cratis-specification-by-example/SKILL.md +7 -0
- package/package/corpus/skills/cratis-specifications-csharp/SKILL.md +43 -11
- package/package/corpus/skills/cratis-specifications-csharp/references/application-scenarios.md +16 -4
- package/package/corpus/skills/cratis-specifications-csharp/references/csharp-patterns.md +18 -5
- package/package/corpus/skills/cratis-specifications-csharp/references/integration-specs.md +21 -0
- package/package/corpus/skills/cratis-specifications-csharp/references/shared-lifecycle.md +34 -0
- package/package/corpus/skills/cratis-specifications-csharp/verification.json +13 -0
- package/package/corpus/skills/cratis-specifications-typescript/SKILL.md +14 -5
- package/package/corpus/skills/cratis-specifications-typescript/verification.json +12 -0
- package/package/corpus/skills/cratis-stage-rendering-and-sandbox/SKILL.md +8 -2
- package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/admission.md +6 -3
- package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/rendered-application.md +10 -1
- package/package/corpus/skills/cratis-stage-rendering-and-sandbox/references/scene-runtime.md +75 -0
- package/package/corpus/skills/cratis-stage-rendering-and-sandbox/verification.json +5 -0
- package/package/corpus/skills/cratis-studio-mcp-safety-guidance/SKILL.md +14 -1
- package/package/profile-catalog.json +68 -1
- package/package.json +1 -1
- 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.
|
|
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
|
-
|
|
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
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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
|
-
|
|
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
|
|
158
|
-
| `
|
|
159
|
-
| `
|
|
160
|
-
| `
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
`RequireAuthentication
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
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.
|
|
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.
|
|
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
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
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.
|
|
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.
|
|
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'` |
|
|
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?)` |
|
|
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
|
|
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`
|
|
44
|
-
|
|
45
|
-
|
|
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.**
|
|
106
|
-
|
|
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.
|
|
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
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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
|
|
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.
|
|
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
|
-
-
|
|
108
|
-
|
|
109
|
-
|
|
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
|
-
|
|
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
|
|
86
|
-
|
|
87
|
-
|
|
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.
|
|
30
|
-
| `Cratis.Arc.Chronicle` | `22.
|
|
31
|
-
| `Cratis.Arc.ProxyGenerator.Build` | `22.
|
|
32
|
-
| `Cratis.Fundamentals` | `7.
|
|
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.
|
|
34
|
+
| `@cratis/arc` | `22.75.0` | `ICommand`, `CommandResult`, `ValidationResult` |
|
|
35
35
|
|
|
36
|
-
>
|
|
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
|
|
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.
|
|
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.
|
|
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`
|
|
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.
|
|
47
|
-
`Error` blocks
|
|
48
|
-
|
|
49
|
-
`
|
|
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.
|
|
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.
|
|
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
|