aw-spec-cli 0.1.7 → 0.1.9

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 (261) hide show
  1. package/assets/.appweaver/DESIGN-FORMAT.md +200 -0
  2. package/assets/.appweaver/ORCH-DIALECT.md +156 -0
  3. package/assets/.appweaver/RULE-PARTITION.md +175 -0
  4. package/assets/.appweaver/STACK-PROFILES.md +461 -0
  5. package/assets/.appweaver/ai-rules.md +180 -0
  6. package/assets/.appweaver/domain.json +1 -0
  7. package/assets/.appweaver/extensions/.registry +19 -0
  8. package/assets/.appweaver/extensions/agent-context/README.md +57 -0
  9. package/assets/.appweaver/extensions/agent-context/agent-context-config.yml +4 -0
  10. package/assets/.appweaver/extensions/agent-context/commands/aw-spec.agent-context.update.md +26 -0
  11. package/assets/.appweaver/extensions/agent-context/extension.yml +37 -0
  12. package/assets/.appweaver/extensions/agent-context/scripts/bash/update-agent-context.sh +201 -0
  13. package/assets/.appweaver/extensions/agent-context/scripts/powershell/update-agent-context.ps1 +237 -0
  14. package/assets/.appweaver/extensions.yml +16 -0
  15. package/assets/.appweaver/feature.json +3 -0
  16. package/assets/.appweaver/init-options.json +9 -0
  17. package/assets/.appweaver/integration.json +15 -0
  18. package/assets/.appweaver/integrations/aw-spec.manifest.json +9 -0
  19. package/assets/.appweaver/interpreter/run-skill.py +1176 -0
  20. package/assets/.appweaver/memory/constitution.md +50 -0
  21. package/assets/.appweaver/orchestrator/.smoke-out/smoke.md +6 -0
  22. package/assets/.appweaver/orchestrator/AGENT-PROFILE.md +94 -0
  23. package/assets/.appweaver/orchestrator/README.md +300 -0
  24. package/assets/.appweaver/orchestrator/adapters/claude_agent_sdk.py +74 -0
  25. package/assets/.appweaver/orchestrator/adapters/google_antigravity.py +74 -0
  26. package/assets/.appweaver/orchestrator/modules/delta-design.orch.yaml +105 -0
  27. package/assets/.appweaver/orchestrator/modules/delta-spec.orch.yaml +101 -0
  28. package/assets/.appweaver/orchestrator/modules/domain-select.orch.yaml +90 -0
  29. package/assets/.appweaver/orchestrator/modules/lane-gate.orch.yaml +126 -0
  30. package/assets/.appweaver/orchestrator/modules/tech-select.orch.yaml +123 -0
  31. package/assets/.appweaver/orchestrator/orchestrator.py +1721 -0
  32. package/assets/.appweaver/orchestrator/rev-templates/ai-rules.reference.md +40 -0
  33. package/assets/.appweaver/orchestrator/rev-templates/delta-design-template.skeleton.md +101 -0
  34. package/assets/.appweaver/orchestrator/rev-templates/design-template.skeleton.md +245 -0
  35. package/assets/.appweaver/orchestrator/rev-templates/domain-constitution.skeleton.md +63 -0
  36. package/assets/.appweaver/orchestrator/rev-templates/domain-requirements.skeleton.md +48 -0
  37. package/assets/.appweaver/orchestrator/rev-templates/domain-rule-bindings.skeleton.md +59 -0
  38. package/assets/.appweaver/orchestrator/rev-templates/domain-rule-file.skeleton.md +39 -0
  39. package/assets/.appweaver/orchestrator/rev-templates/frontend-rule-file.skeleton.md +63 -0
  40. package/assets/.appweaver/orchestrator/rev-templates/tech-rule-bindings.skeleton.md +116 -0
  41. package/assets/.appweaver/orchestrator/rev-templates/technical-constitution.skeleton.md +106 -0
  42. package/assets/.appweaver/orchestrator/rev-templates/technical-rule-file.skeleton.md +54 -0
  43. package/assets/.appweaver/orchestrator/rev-templates/ui-constitution.skeleton.md +125 -0
  44. package/assets/.appweaver/orchestrator/rev-templates/ui-delta-design-template.skeleton.md +123 -0
  45. package/assets/.appweaver/orchestrator/rev-templates/ui-design-template.skeleton.md +294 -0
  46. package/assets/.appweaver/orchestrator/workflows/_smoke.orch.yaml +160 -0
  47. package/assets/.appweaver/orchestrator/workflows/aw-spec-add-component.orch.yaml +270 -0
  48. package/assets/.appweaver/orchestrator/workflows/aw-spec-adopt.orch.yaml +934 -0
  49. package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-delta-design.orch.yaml +251 -0
  50. package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-design.orch.yaml +265 -0
  51. package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice.orch.yaml +437 -0
  52. package/assets/.appweaver/orchestrator/workflows/aw-spec-build.orch.yaml +197 -0
  53. package/assets/.appweaver/orchestrator/workflows/aw-spec-characterize.orch.yaml +475 -0
  54. package/assets/.appweaver/orchestrator/workflows/aw-spec-close-delta.orch.yaml +181 -0
  55. package/assets/.appweaver/orchestrator/workflows/aw-spec-constitution.orch.yaml +727 -0
  56. package/assets/.appweaver/orchestrator/workflows/aw-spec-demo.orch.yaml +100 -0
  57. package/assets/.appweaver/orchestrator/workflows/aw-spec-dependency-tree.orch.yaml +69 -0
  58. package/assets/.appweaver/orchestrator/workflows/aw-spec-deploy.orch.yaml +85 -0
  59. package/assets/.appweaver/orchestrator/workflows/aw-spec-design-ui.orch.yaml +386 -0
  60. package/assets/.appweaver/orchestrator/workflows/aw-spec-design.orch.yaml +382 -0
  61. package/assets/.appweaver/orchestrator/workflows/aw-spec-finalize-delta.orch.yaml +462 -0
  62. package/assets/.appweaver/orchestrator/workflows/aw-spec-foundation.orch.yaml +265 -0
  63. package/assets/.appweaver/orchestrator/workflows/aw-spec-implement-delta.orch.yaml +253 -0
  64. package/assets/.appweaver/orchestrator/workflows/aw-spec-implement-ui.orch.yaml +267 -0
  65. package/assets/.appweaver/orchestrator/workflows/aw-spec-implement.orch.yaml +287 -0
  66. package/assets/.appweaver/orchestrator/workflows/aw-spec-inventory.orch.yaml +238 -0
  67. package/assets/.appweaver/orchestrator/workflows/aw-spec-onboard.orch.yaml +1822 -0
  68. package/assets/.appweaver/orchestrator/workflows/aw-spec-parity.orch.yaml +293 -0
  69. package/assets/.appweaver/orchestrator/workflows/aw-spec-run.orch.yaml +194 -0
  70. package/assets/.appweaver/orchestrator/workflows/aw-spec-select-domain.orch.yaml +83 -0
  71. package/assets/.appweaver/orchestrator/workflows/aw-spec-select-feature.orch.yaml +128 -0
  72. package/assets/.appweaver/orchestrator/workflows/aw-spec-select-stack.orch.yaml +296 -0
  73. package/assets/.appweaver/orchestrator/workflows/aw-spec-specify.orch.yaml +439 -0
  74. package/assets/.appweaver/scripts/bash/aw-inventory.sh +17 -0
  75. package/assets/.appweaver/scripts/bash/aw-parity.sh +13 -0
  76. package/assets/.appweaver/scripts/bash/aw-rev-constitution.sh +13 -0
  77. package/assets/.appweaver/scripts/bash/aw-spec-actions.sh +2626 -0
  78. package/assets/.appweaver/scripts/bash/aw-xref.sh +15 -0
  79. package/assets/.appweaver/scripts/bash/common.sh +533 -0
  80. package/assets/.appweaver/scripts/powershell/aw-inventory.ps1 +17 -0
  81. package/assets/.appweaver/scripts/powershell/aw-parity.ps1 +13 -0
  82. package/assets/.appweaver/scripts/powershell/aw-rev-constitution.ps1 +13 -0
  83. package/assets/.appweaver/scripts/powershell/aw-spec-actions.ps1 +2232 -0
  84. package/assets/.appweaver/scripts/powershell/aw-xref.ps1 +15 -0
  85. package/assets/.appweaver/scripts/python/aw-component-catalog.py +121 -0
  86. package/assets/.appweaver/scripts/python/aw-inventory.py +1180 -0
  87. package/assets/.appweaver/scripts/python/aw-parity.py +380 -0
  88. package/assets/.appweaver/scripts/python/aw-rev-constitution.py +329 -0
  89. package/assets/.appweaver/scripts/python/aw-stack.py +1251 -0
  90. package/assets/.appweaver/scripts/python/aw-xref.py +1330 -0
  91. package/assets/.appweaver/scripts/python/validate_okf.py +352 -0
  92. package/assets/.appweaver/stack-profiles/angular.json +16 -0
  93. package/assets/.appweaver/stack-profiles/blazor-wasm.json +17 -0
  94. package/assets/.appweaver/stack-profiles/dotnet-webapi.json +15 -0
  95. package/assets/.appweaver/stack-profiles/go-chi.json +14 -0
  96. package/assets/.appweaver/stack-profiles/java-spring.json +16 -0
  97. package/assets/.appweaver/stack-profiles/nextjs.json +16 -0
  98. package/assets/.appweaver/stack-profiles/node-express.json +15 -0
  99. package/assets/.appweaver/stack-profiles/python-fastapi.json +16 -0
  100. package/assets/.appweaver/stack-profiles/react-vite.json +17 -0
  101. package/assets/.appweaver/stack-profiles/sveltekit.json +16 -0
  102. package/assets/.appweaver/stack-profiles/vue-vite.json +17 -0
  103. package/assets/.appweaver/stacks.json +3 -0
  104. package/assets/.appweaver/templates/constitution-domain-template.md +116 -0
  105. package/assets/.appweaver/templates/constitution-technical-template.md +108 -0
  106. package/assets/.appweaver/templates/constitution-ui-template.md +116 -0
  107. package/assets/.appweaver/templates/delta-design-template.md +69 -0
  108. package/assets/.appweaver/templates/delta-spec-template.md +63 -0
  109. package/assets/.appweaver/templates/design-template.md +383 -0
  110. package/assets/.appweaver/templates/okf-concept-template.md +114 -0
  111. package/assets/.appweaver/templates/parity-manifest-template.json +49 -0
  112. package/assets/.appweaver/templates/source-map-template.md +85 -0
  113. package/assets/.appweaver/templates/spec-template.md +309 -0
  114. package/assets/.appweaver/templates/ui-design-template.md +273 -0
  115. package/assets/foundations/dotnet/ModularMonolith/ModularMonolith.Reference.pack.txt +25248 -0
  116. package/assets/foundations/dotnet/ModularMonolith/ModularMonolith.pack.txt +5726 -0
  117. package/assets/foundations/dotnet/ModularMonolith/pack-foundation.ps1 +145 -0
  118. package/assets/foundations/dotnet/ModularMonolith/pack-foundation.sh +196 -0
  119. package/assets/foundations/dotnet/ModularMonolith/pack-reference-foundation.ps1 +157 -0
  120. package/assets/foundations/dotnet/ModularMonolith/pack-reference-foundation.sh +209 -0
  121. package/assets/foundations/dotnet/ModularMonolith/unpack-foundation.ps1 +126 -0
  122. package/assets/foundations/dotnet/ModularMonolith/unpack-foundation.sh +217 -0
  123. package/assets/foundations/dotnet/ModularMonolith/unpack-reference-foundation.ps1 +129 -0
  124. package/assets/foundations/dotnet/ModularMonolith/unpack-reference-foundation.sh +218 -0
  125. package/assets/foundations/dotnet/VerticalSlice/VerticalSlice.Reference.pack.txt +19318 -0
  126. package/assets/foundations/dotnet/VerticalSlice/VerticalSlice.pack.txt +2833 -0
  127. package/assets/foundations/dotnet/VerticalSlice/pack-foundation.ps1 +145 -0
  128. package/assets/foundations/dotnet/VerticalSlice/pack-foundation.sh +196 -0
  129. package/assets/foundations/dotnet/VerticalSlice/pack-reference-foundation.ps1 +157 -0
  130. package/assets/foundations/dotnet/VerticalSlice/pack-reference-foundation.sh +209 -0
  131. package/assets/foundations/dotnet/VerticalSlice/unpack-foundation.ps1 +126 -0
  132. package/assets/foundations/dotnet/VerticalSlice/unpack-foundation.sh +217 -0
  133. package/assets/foundations/dotnet/VerticalSlice/unpack-reference-foundation.ps1 +129 -0
  134. package/assets/foundations/dotnet/VerticalSlice/unpack-reference-foundation.sh +218 -0
  135. package/assets/foundations/dotnet/components/Email/README.md +119 -0
  136. package/assets/foundations/dotnet/components/Email/ReferenceEndpoints/SendEmailEndpoint.cs +84 -0
  137. package/assets/foundations/dotnet/components/Email/integration.md +300 -0
  138. package/assets/foundations/dotnet/components/Jobs/README.md +113 -0
  139. package/assets/foundations/dotnet/components/Jobs/integration.md +259 -0
  140. package/assets/foundations/dotnet/components/QrGenerator/README.md +85 -0
  141. package/assets/foundations/dotnet/components/QrGenerator/ReferenceEndpoints/GenerateQrEndpoint.cs +57 -0
  142. package/assets/foundations/dotnet/components/QrGenerator/integration.md +230 -0
  143. package/assets/foundations/dotnet/components/README.md +74 -0
  144. package/assets/guardrails/README.md +222 -0
  145. package/assets/guardrails/domain/healthcare/ai-rules.domain.md +34 -0
  146. package/assets/guardrails/domain/healthcare/api-versioning.domain.md +17 -0
  147. package/assets/guardrails/domain/healthcare/auditing.domain.md +97 -0
  148. package/assets/guardrails/domain/healthcare/authorization.domain.md +26 -0
  149. package/assets/guardrails/domain/healthcare/clinical-terms.md +20 -0
  150. package/assets/guardrails/domain/healthcare/coding-standards.domain.md +26 -0
  151. package/assets/guardrails/domain/healthcare/consent.md +19 -0
  152. package/assets/guardrails/domain/healthcare/cqrs.domain.md +12 -0
  153. package/assets/guardrails/domain/healthcare/data-classification.domain.md +28 -0
  154. package/assets/guardrails/domain/healthcare/dependency-policy.domain.md +11 -0
  155. package/assets/guardrails/domain/healthcare/dicom.md +15 -0
  156. package/assets/guardrails/domain/healthcare/domain-constitution.md +119 -0
  157. package/assets/guardrails/domain/healthcare/domain-driven-design.domain.md +28 -0
  158. package/assets/guardrails/domain/healthcare/eventing.domain.md +18 -0
  159. package/assets/guardrails/domain/healthcare/fhir.md +36 -0
  160. package/assets/guardrails/domain/healthcare/folder-structure.domain.md +25 -0
  161. package/assets/guardrails/domain/healthcare/hipaa.md +34 -0
  162. package/assets/guardrails/domain/healthcare/hl7.md +15 -0
  163. package/assets/guardrails/domain/healthcare/ihe-conformance.md +31 -0
  164. package/assets/guardrails/domain/healthcare/integration-terms.md +21 -0
  165. package/assets/guardrails/domain/healthcare/persistence.domain.md +20 -0
  166. package/assets/guardrails/domain/healthcare/terminology.md +30 -0
  167. package/assets/guardrails/domain/healthcare/testing.domain.md +15 -0
  168. package/assets/guardrails/domain/healthcare/ux/accessibility-standards.md +36 -0
  169. package/assets/guardrails/domain/healthcare/ux/content-design.md +32 -0
  170. package/assets/guardrails/domain/healthcare/ux/interaction-states.md +44 -0
  171. package/assets/guardrails/domain/healthcare/ux/journey-mapping.md +40 -0
  172. package/assets/guardrails/domain/healthcare/vertical-slices.domain.md +18 -0
  173. package/assets/guardrails/domain/healthcare/zero-trust.domain.md +12 -0
  174. package/assets/guardrails/domain/pharma/ai-rules.domain.md +32 -0
  175. package/assets/guardrails/domain/pharma/api-versioning.domain.md +20 -0
  176. package/assets/guardrails/domain/pharma/atc.md +22 -0
  177. package/assets/guardrails/domain/pharma/auditing.domain.md +90 -0
  178. package/assets/guardrails/domain/pharma/authorization.domain.md +25 -0
  179. package/assets/guardrails/domain/pharma/coding-standards.domain.md +28 -0
  180. package/assets/guardrails/domain/pharma/cqrs.domain.md +16 -0
  181. package/assets/guardrails/domain/pharma/data-classification.domain.md +24 -0
  182. package/assets/guardrails/domain/pharma/data-provenance.md +21 -0
  183. package/assets/guardrails/domain/pharma/dependency-policy.domain.md +11 -0
  184. package/assets/guardrails/domain/pharma/domain-constitution.md +113 -0
  185. package/assets/guardrails/domain/pharma/domain-driven-design.domain.md +36 -0
  186. package/assets/guardrails/domain/pharma/domain-requirements.sample.md +103 -0
  187. package/assets/guardrails/domain/pharma/eventing.domain.md +18 -0
  188. package/assets/guardrails/domain/pharma/fhir.md +31 -0
  189. package/assets/guardrails/domain/pharma/folder-structure.domain.md +26 -0
  190. package/assets/guardrails/domain/pharma/hl7.md +17 -0
  191. package/assets/guardrails/domain/pharma/idmp.md +26 -0
  192. package/assets/guardrails/domain/pharma/integration-terms.md +21 -0
  193. package/assets/guardrails/domain/pharma/ndc.md +28 -0
  194. package/assets/guardrails/domain/pharma/persistence.domain.md +23 -0
  195. package/assets/guardrails/domain/pharma/pharma-terms.md +27 -0
  196. package/assets/guardrails/domain/pharma/product-lifecycle.domain.md +30 -0
  197. package/assets/guardrails/domain/pharma/regulatory-compliance.md +19 -0
  198. package/assets/guardrails/domain/pharma/terminology.md +32 -0
  199. package/assets/guardrails/domain/pharma/testing.domain.md +19 -0
  200. package/assets/guardrails/domain/pharma/vertical-slices.domain.md +17 -0
  201. package/assets/guardrails/domain/pharma/zero-trust.domain.md +12 -0
  202. package/assets/guardrails/projects/dotnet-default-project/domain/domain-requirements.md +58 -0
  203. package/assets/guardrails/projects/dotnet-default-project/domain-rule-bindings.md +113 -0
  204. package/assets/guardrails/projects/dotnet-default-project/frontend/ui-requirements.md +43 -0
  205. package/assets/guardrails/projects/dotnet-default-project/service/technical-requirements.md +40 -0
  206. package/assets/guardrails/projects/dotnet-default-project/tech-rule-bindings.md +263 -0
  207. package/assets/guardrails/requirement-spec.txt +27 -0
  208. package/assets/guardrails/technology/dotnet-webapi/PACKAGING.md +184 -0
  209. package/assets/guardrails/technology/dotnet-webapi/api-versioning.md +44 -0
  210. package/assets/guardrails/technology/dotnet-webapi/auditing.md +96 -0
  211. package/assets/guardrails/technology/dotnet-webapi/authorization-matrix.md +14 -0
  212. package/assets/guardrails/technology/dotnet-webapi/authorization.md +39 -0
  213. package/assets/guardrails/technology/dotnet-webapi/clean-architecture.md +54 -0
  214. package/assets/guardrails/technology/dotnet-webapi/coding-standards.md +87 -0
  215. package/assets/guardrails/technology/dotnet-webapi/cqrs.md +63 -0
  216. package/assets/guardrails/technology/dotnet-webapi/data-classification.md +38 -0
  217. package/assets/guardrails/technology/dotnet-webapi/dependency-policy.md +40 -0
  218. package/assets/guardrails/technology/dotnet-webapi/domain-driven-design.md +91 -0
  219. package/assets/guardrails/technology/dotnet-webapi/eventing.md +57 -0
  220. package/assets/guardrails/technology/dotnet-webapi/examples/api-versioning.md +75 -0
  221. package/assets/guardrails/technology/dotnet-webapi/examples/auditing.md +84 -0
  222. package/assets/guardrails/technology/dotnet-webapi/examples/authorization.md +68 -0
  223. package/assets/guardrails/technology/dotnet-webapi/examples/clean-architecture.md +37 -0
  224. package/assets/guardrails/technology/dotnet-webapi/examples/cqrs.md +97 -0
  225. package/assets/guardrails/technology/dotnet-webapi/examples/domain-driven-design.md +141 -0
  226. package/assets/guardrails/technology/dotnet-webapi/examples/eventing.md +46 -0
  227. package/assets/guardrails/technology/dotnet-webapi/examples/persistence.md +207 -0
  228. package/assets/guardrails/technology/dotnet-webapi/examples/vertical-slices.md +151 -0
  229. package/assets/guardrails/technology/dotnet-webapi/examples/zero-trust.md +48 -0
  230. package/assets/guardrails/technology/dotnet-webapi/folder-structure.md +61 -0
  231. package/assets/guardrails/technology/dotnet-webapi/modular-monolith.md +47 -0
  232. package/assets/guardrails/technology/dotnet-webapi/persistence.md +82 -0
  233. package/assets/guardrails/technology/dotnet-webapi/technology-constitution.md +162 -0
  234. package/assets/guardrails/technology/dotnet-webapi/testing.md +55 -0
  235. package/assets/guardrails/technology/dotnet-webapi/vertical-slices.md +70 -0
  236. package/assets/guardrails/technology/dotnet-webapi/zero-trust.md +48 -0
  237. package/assets/guardrails/technology/java-spring/README.md +62 -0
  238. package/assets/guardrails/technology/nextjs/accessibility-implementation.md +56 -0
  239. package/assets/guardrails/technology/nextjs/api-client.md +56 -0
  240. package/assets/guardrails/technology/nextjs/api-integration.dotnet-webapi.md +174 -0
  241. package/assets/guardrails/technology/nextjs/api-integration.java-spring.md +203 -0
  242. package/assets/guardrails/technology/nextjs/auth-session.md +68 -0
  243. package/assets/guardrails/technology/nextjs/client-security.md +69 -0
  244. package/assets/guardrails/technology/nextjs/component-architecture.md +60 -0
  245. package/assets/guardrails/technology/nextjs/component-conventions.md +58 -0
  246. package/assets/guardrails/technology/nextjs/design-system.md +60 -0
  247. package/assets/guardrails/technology/nextjs/error-handling.md +72 -0
  248. package/assets/guardrails/technology/nextjs/forms-and-validation.md +75 -0
  249. package/assets/guardrails/technology/nextjs/frontend-testing.md +94 -0
  250. package/assets/guardrails/technology/nextjs/i18n.md +57 -0
  251. package/assets/guardrails/technology/nextjs/observability.md +67 -0
  252. package/assets/guardrails/technology/nextjs/performance-budgets.md +66 -0
  253. package/assets/guardrails/technology/nextjs/routing-navigation.md +52 -0
  254. package/assets/guardrails/technology/nextjs/state-management.md +70 -0
  255. package/assets/guardrails/technology/nextjs/ui-constitution.md +166 -0
  256. package/dist/commands/init.js +2 -2
  257. package/dist/commands/init.js.map +1 -1
  258. package/dist/utils/copy-assets.js +8 -8
  259. package/dist/utils/copy-assets.js.map +1 -1
  260. package/package.json +1 -1
  261. package/assets/docs/pharma-constitution.my-ref.md +0 -86
@@ -0,0 +1,39 @@
1
+ # Authorization Standards
2
+
3
+ > Pure technology (domain-agnostic) — domain roles & matrix in [[authorization.domain]]. NON-NEGOTIABLE. Commands: `/aw-spec-design`.
4
+
5
+ ## Authorization model
6
+
7
+ - Authorization is **role-based AND scope-based** — both MUST pass.
8
+ - Per-route authorization is declared per endpoint via `Roles(...)` + scope evaluation,
9
+ documented in an authorization matrix.
10
+ - Identity comes from an external IdP via `.AddAppWeaverSecurity(...)` — local identity stores
11
+ forbidden (see [[zero-trust]]).
12
+ - (The concrete role set and scope syntax are domain-specific — see [[authorization.domain]].)
13
+
14
+ ## Policy evaluation
15
+
16
+ - Endpoints inherit `SecureFastEndpoint<TRequest, TResponse>` and MUST override
17
+ `GetSecurityCachePolicy()` to declare `SecurityLevel` and `CachePolicy`.
18
+ - Mutating endpoints MUST use `CachePolicy.NoStore`.
19
+ - Sensitive-data read endpoints MUST use `CachePolicy.NoStore`.
20
+ - Field-level redaction (minimum-necessary) lives in **projection extensions**, not
21
+ controllers (see [[data-classification]]; domain specifics in [[authorization.domain]]).
22
+
23
+ ## Endpoint authorization patterns
24
+
25
+ - `AllowAnonymous()` is permitted **only** for infrastructure/discovery endpoints
26
+ (`/.well-known`, `/health`, `/alive`, service metadata) and during initial scaffolding
27
+ before merge to a protected branch.
28
+ - `AllowAnonymous()` on sensitive-data or mutating endpoints in any CI-protected branch is a
29
+ Forbidden Pattern (CI grep gate; see [[coding-standards]]).
30
+
31
+ ## Canonical example
32
+
33
+ The worked `<SampleProjectName>` example for these rules lives in
34
+ `guardrails/technology/dotnet-webapi/examples/authorization.md`, mapped for `design`. The
35
+ constitution set maps the rules without it.
36
+
37
+ ## Related
38
+
39
+ - [[zero-trust]] · [[auditing]] · [[data-classification]] · [[authorization.domain]]
@@ -0,0 +1,54 @@
1
+ # Clean Architecture Standards
2
+
3
+ > Pure technology (domain-agnostic). NON-NEGOTIABLE. Commands: `/aw-spec-design`, `/aw-spec-build`.
4
+
5
+ ## Dependency direction
6
+
7
+ Dependencies flow **inward only**:
8
+
9
+ ```
10
+ API -> Application (Features) -> Domain <- Infrastructure
11
+ ```
12
+
13
+ The Domain is the innermost ring; everything depends on it and it depends on nothing.
14
+
15
+ ## Layer responsibilities
16
+
17
+ - **API** — HTTP surface (FastEndpoints). Translates transport to/from mediator
18
+ messages. MUST NOT contain business logic.
19
+ - **Application (Features)** — Command/Query handlers, validators, orchestration.
20
+ Dispatched via `IMediator`. MUST NOT depend on API frameworks or concrete EF Core types.
21
+ - **Domain** — aggregates, entities, value objects, domain events, specifications.
22
+ Framework-agnostic.
23
+ - **Infrastructure** — EF Core, external service clients, persistence configuration.
24
+ Depends inward on Domain abstractions.
25
+
26
+ ## Allowed dependencies / annotations in Domain
27
+
28
+ The Domain layer is framework-agnostic. The **only** allowed annotations are:
29
+
30
+ - `[NotMapped]`
31
+ - `[ValueObject<T>]` (Vogen)
32
+ - `System.ComponentModel.DataAnnotations.Schema`
33
+
34
+ ## Infrastructure boundaries
35
+
36
+ - EF Core mapping lives **only** in `{Module}/Persistence/<Aggregate>Configuration.cs` and is
37
+ applied via `ApplyConfigurationsFromAssembly`.
38
+ - **Endpoints MUST NOT** call repositories, `DbContext`, or `IUnitOfWork` directly; they
39
+ **MUST** call `IMediator.Send(...)`.
40
+ - **Application Features MUST NOT** depend on API frameworks or concrete EF Core types.
41
+ - Direct `DbContext` access from Endpoints or Application Features (outside the
42
+ repository / specification surface) is FORBIDDEN.
43
+
44
+ ## Canonical example
45
+
46
+ The worked `<SampleProjectName>` example for these rules lives in
47
+ `guardrails/technology/dotnet-webapi/examples/clean-architecture.md`, mapped for `design` and
48
+ `build`. The constitution set maps the rules without it.
49
+
50
+ ## Related
51
+
52
+ - [[cqrs]] — how the Application layer dispatches work
53
+ - [[persistence]] — repository + specification surface, EF Core conventions
54
+ - [[vertical-slices]] — physical organization of the layers per feature
@@ -0,0 +1,87 @@
1
+ # Coding Standards
2
+
3
+ > Pure technology (domain-agnostic) — domain forbidden patterns & CI gates in [[coding-standards.domain]]. Commands: `/aw-spec-implement`, `/aw-spec-implement-delta`, `/aw-spec-build`, `/aw-spec-analyze-slice`.
4
+
5
+ ## Naming conventions
6
+
7
+ - Solution and projects: `<SampleProjectName>.<Role>` (e.g. `<SampleProjectName>.Api`,
8
+ `<SampleProjectName>.AppHost`, `<SampleProjectName>.ServiceDefaults`).
9
+ - Namespaces mirror the folder path exactly; **file-scoped namespaces only**.
10
+ - Aggregates: `class <Aggregate> : EntityBase<<Aggregate>Id>, IAggregateRoot,
11
+ IFullAuditedObject, ISoftDeletable, IConcurrencyTracked, IHasDomainEvents,
12
+ INamedEntity<<Aggregate>Id>`.
13
+ - Commands/Queries: `record <Verb><Aggregate>Command(...) : ICommand<Result<TDto>>`.
14
+ - DTOs: `record <Aggregate>Dto { public required Guid Id { get; init; } ... }` — no setters;
15
+ required init for non-nullable members.
16
+
17
+ ## Nullable & language rules
18
+
19
+ - C# language version: latest LTS; **nullable reference types ENABLED**; implicit usings
20
+ ENABLED; **`TreatWarningsAsErrors` for Release**.
21
+
22
+ ## Async conventions
23
+
24
+ - Every I/O-bound method ends with `Async` and accepts a `CancellationToken` as the **last
25
+ parameter**.
26
+ - `async void` is forbidden outside event handlers.
27
+ - Blocking calls (`.Result`, `.Wait()`, `Task.Run` to fake async) in request-handling paths
28
+ are FORBIDDEN.
29
+
30
+ ## Error / exception conventions
31
+
32
+ - Exceptions are thrown by the **Domain only** (`DomainException`,
33
+ `InvariantViolationException`). Application code returns `Result<T>` (see [[cqrs]]).
34
+ - Never catch-all `catch (Exception)` that swallows or rewraps without rethrow, except in the
35
+ central exception handler.
36
+ - Never return HTTP 200 with an error body — use correct status codes (4xx client, 5xx server,
37
+ 409 concurrency).
38
+
39
+ ## Documentation expectations
40
+
41
+ - XML doc comments on public types and aggregate methods.
42
+ - Inline comments only where intent is non-obvious. Commented-out code MUST be removed before
43
+ merge.
44
+ - Do not write inline rationale comments explaining pattern choices — the constitution is the
45
+ rationale (see [[ai-rules]]).
46
+
47
+ ## Forbidden patterns (generic; rejected at review, build-warning where statically detectable)
48
+
49
+ 1. MediatR — use `AppWeaver.Mediator` (see [[dependency-policy]]).
50
+ 2. AutoMapper / Mapster reflection mapping — hand-written `ToDto()` only.
51
+ 3. Anemic domain models (see [[domain-driven-design]]).
52
+ 4. Repository as data-access god object (see [[persistence]]).
53
+ 5. Cross-aggregate EF navigation properties — strongly-typed ID only.
54
+ 6. Hard-coded connection strings, secrets, ports, or issuer URLs in source (see [[zero-trust]]).
55
+ 7. Static service locator — use constructor DI.
56
+ 8. Direct `DbContext` access from Endpoints or Features outside repo/spec surface.
57
+ 9. Blocking calls in request paths.
58
+ 10. Catch-all that swallows/rewraps without rethrow (outside central handler).
59
+ 11. `AllowAnonymous()` on sensitive-data/mutating endpoints in a CI-protected branch.
60
+ 12. Logging/emitting secrets, tokens, keys, or payment-card data (see [[data-classification]]).
61
+ 13. Multiple aggregate mutations in one transaction (see [[cqrs]], [[eventing]]).
62
+ 14. `DateTime.UtcNow` / `Guid.NewGuid()` in aggregates/handlers/SUT — use `IClock` /
63
+ `IGuidGenerator` (see [[testing]]).
64
+ 15. HTTP 200 with an error body.
65
+ 16. Analytics/reporting by querying the OLTP DB directly — emit events (see [[eventing]]).
66
+
67
+ > Domain-specific forbidden patterns are in [[coding-standards.domain]].
68
+
69
+ ## Quality gates (CI) — generic, must pass before merge
70
+
71
+ 1. `dotnet build` succeeds with `TreatWarningsAsErrors=true` for Release.
72
+ 2. `dotnet test` passes for UnitTests + IntegrationTests.
73
+ 3. Code coverage on changed files meets the Testing Profile threshold (see [[testing]]).
74
+ 4. EF Core migrations apply cleanly to a fresh PostgreSQL instance (see [[persistence]]).
75
+ 5. OpenAPI document generation succeeds; diff reviewed for breaking changes.
76
+ 6. AsyncAPI regenerates cleanly for any domain-event contract change (see [[eventing]]).
77
+ 7. Static analysis (Roslyn analyzers, nullable warnings, banned-API analyzer) — zero errors.
78
+ 8. Grep checks: no `AllowAnonymous()` on production endpoints, no hard-coded secrets, no
79
+ MediatR/AutoMapper references.
80
+ 9. Constitution compliance review checked off in the PR template.
81
+
82
+ > Domain-specific CI gates are in [[coding-standards.domain]].
83
+
84
+ ## Related
85
+
86
+ - [[dependency-policy]] · [[api-versioning]] · [[domain-driven-design]] · [[cqrs]] ·
87
+ [[persistence]] · [[testing]] · [[ai-rules]] · [[coding-standards.domain]]
@@ -0,0 +1,63 @@
1
+ # CQRS + Mediator Standards
2
+
3
+ > Pure technology (domain-agnostic) — domain additions in [[cqrs.domain]]. NON-NEGOTIABLE. Commands: `/aw-spec-design`.
4
+
5
+ ## Command / query patterns
6
+
7
+ - All application logic is dispatched through **`AppWeaver.Mediator`** (NOT MediatR).
8
+ - **Commands:** `record XxxCommand(...) : ICommand<Result<TDto>>` or `ICommand<Result>`.
9
+ - **Queries:** `record XxxQuery(...) : IQuery<Result<TDto>>`.
10
+ - Handlers use **primary-constructor DI** and return `ValueTask<Result<T>>`.
11
+
12
+ ## Mediator conventions
13
+
14
+ - Endpoints call `IMediator.Send(...)` — never repositories/`DbContext`/`IUnitOfWork` directly.
15
+ - Raw `Guid` parameters at the Application boundary **MUST be wrapped** into strongly-typed
16
+ IDs at the handler edge.
17
+
18
+ ## Pipeline behaviors
19
+
20
+ Enabled at startup, in order:
21
+
22
+ 1. Logging behavior
23
+ 2. FluentValidation behavior
24
+
25
+ > Additional cross-cutting behaviors (e.g. domain access-audit behaviors) may be appended —
26
+ > see [[cqrs.domain]] for the domain audit-pipeline behavior.
27
+
28
+ ## Result pattern
29
+
30
+ - Errors are returned as `Result<T>.Failure(new Error(code, message, status, resource))`.
31
+ - **Exceptions MUST NOT** be used for expected business outcomes (validation, not-found,
32
+ conflict, concurrency). `DomainException` is reserved for invariant violations and is
33
+ caught by the centralized exception handler.
34
+ - **Error code** MUST be a stable dot-namespaced slug — e.g. `resource.not_found`,
35
+ `concurrency.conflict`, `resource.duplicate`.
36
+ - **resource** MUST be the kebab-case resource name.
37
+
38
+ ## Handler responsibilities
39
+
40
+ - **Read handlers** inject `IReadRepository<TAggregate>`.
41
+ - **Write handlers** inject `IRepository<TAggregate>` + `IUnitOfWork` (+ `IPublisher`
42
+ when domain events are produced).
43
+ - Validators check **request shape only**; invariants are enforced inside the aggregate.
44
+ - No business logic in handlers (anemic-domain anti-pattern — see [[domain-driven-design]]).
45
+
46
+ ## Transaction handling
47
+
48
+ - Write handlers **MUST** wrap mutating work in
49
+ `IUnitOfWork.ExecuteInTransactionAsync(..., IsolationLevel.ReadCommitted, ct)` and call
50
+ `SaveChangesAsync` **inside** the lambda.
51
+ - They **MUST** publish domain events and call `ClearDomainEvents()` before returning.
52
+ - **One command mutates one aggregate per transaction** — cross-aggregate effects flow
53
+ through domain events or follow-up commands (see [[eventing]]).
54
+
55
+ ## Canonical example
56
+
57
+ The worked `<SampleProjectName>` example for these rules lives in
58
+ `guardrails/technology/dotnet-webapi/examples/cqrs.md`, mapped for `design`. The constitution
59
+ set maps the rules without it.
60
+
61
+ ## Related
62
+
63
+ - [[clean-architecture]] · [[persistence]] · [[eventing]] · [[domain-driven-design]] · [[cqrs.domain]]
@@ -0,0 +1,38 @@
1
+ # Data Classification Standards
2
+
3
+ > Pure technology (domain-agnostic) — domain data categories in [[data-classification.domain]]. NON-NEGOTIABLE. Commands: `/aw-spec-design`.
4
+
5
+ ## Classification framework
6
+
7
+ - Every data element is assigned a **sensitivity class**; controls (encryption, masking,
8
+ logging, export) are applied per class.
9
+ - The concrete sensitivity taxonomy is project/domain-specific — see
10
+ [[data-classification.domain]] for the domain taxonomy.
11
+
12
+ ## Masking rules
13
+
14
+ - Field-level redaction is applied in **projection extensions**, not controllers
15
+ (minimum-necessary by role/scope — see [[authorization]]).
16
+
17
+ ## Encryption requirements
18
+
19
+ - AES-256 at rest (DB TDE + customer-managed key); TLS 1.2+ in transit (1.3 target);
20
+ encrypted backups.
21
+ - **Application-level field encryption** for the most sensitive fields (the concrete field
22
+ list is domain-specific — see [[data-classification.domain]]).
23
+
24
+ ## Logging restrictions
25
+
26
+ - **NEVER** log or emit in metrics/traces: authentication tokens, password material, private
27
+ keys, or full payment-card data.
28
+ (Domain-sensitive elements — PHI, SSN, government IDs — see [[data-classification.domain]].)
29
+
30
+ ## Export restrictions
31
+
32
+ - Production data MUST NOT be copied to non-production environments without an approved
33
+ de-identification / anonymization step.
34
+ - (Domain de-identification / anonymization specifics — see [[data-classification.domain]].)
35
+
36
+ ## Related
37
+
38
+ - [[auditing]] · [[authorization]] · [[zero-trust]] · [[data-classification.domain]]
@@ -0,0 +1,40 @@
1
+ # Dependency Policy
2
+
3
+ > Pure technology (domain-agnostic) — domain package rules in [[dependency-policy.domain]]. Commands: `/aw-spec-implement`, `/aw-spec-implement-delta`.
4
+
5
+ ## Package governance
6
+
7
+ - **All package versions are governed by `Directory.Packages.props`** (Central Package
8
+ Management). `PackageReference` entries in `.csproj` MUST NOT specify a `Version`.
9
+ - New dependencies are added via `dotnet add package`.
10
+
11
+ ## Approved / preferred packages
12
+
13
+ - Mediator: **`AppWeaver.Mediator`**.
14
+ - Mapping: **hand-written `ToDto()` extension methods** (no reflection mapper).
15
+ - Observability: **`AppWeaver.ServiceDefaults`** (OpenTelemetry + Serilog + resilience +
16
+ discovery) — see [[auditing]].
17
+ - Validation: FluentValidation (via the mediator pipeline behavior; see [[cqrs]]).
18
+
19
+ ## Banned packages
20
+
21
+ - **MediatR** — MUST NOT appear in any `Directory.Packages.props` entry (CI grep gate).
22
+ - **AutoMapper / Mapster** (reflection mapping) — forbidden (see [[coding-standards]]).
23
+ - Any logging package that ships analytics/telemetry exfiltration by default — rejected.
24
+
25
+ ## Supply-chain rules
26
+
27
+ - New dependencies are reviewed for **license and supply-chain risk** before adoption.
28
+ - AI agents **MUST NOT** introduce new top-level dependencies; new framework capabilities are
29
+ requested explicitly by the developer (see [[ai-rules]]).
30
+ - Do not create speculative abstractions (single-implementation interfaces, generic wrappers
31
+ around existing framework types) — YAGNI is enforced.
32
+
33
+ ## Licensing expectations
34
+
35
+ - Dependencies must carry a license compatible with the intended commercial deployment;
36
+ copyleft licenses that would force source disclosure of the service are rejected.
37
+
38
+ ## Related
39
+
40
+ - [[coding-standards]] · [[cqrs]] · [[auditing]] · [[ai-rules]] · [[dependency-policy.domain]]
@@ -0,0 +1,91 @@
1
+ # Domain-Driven Design Standards (Tactical Patterns)
2
+
3
+ > Pure technology (domain-agnostic) — generic DDD tactical patterns; the business model, canonical aggregates + invariants are in [[domain-driven-design.domain]]. NON-NEGOTIABLE. Commands: `/aw-spec-specify`.
4
+
5
+ > Note: DDD is a domain-modelling methodology, but the rules here are domain-agnostic and
6
+ > reusable, so the file sits in the technology corpus and is mapped on the technical tier. The
7
+ > business-specific model is in the companion `.domain.md`, in the active domain corpus.
8
+
9
+ ## Ubiquitous language & bounded contexts
10
+
11
+ - Use a consistent ubiquitous language across each bounded context.
12
+ - Each bounded context = one module with `Domain / Features / Persistence / Shared`
13
+ (see [[modular-monolith]]).
14
+
15
+ ## Aggregate design
16
+
17
+ - Every entity exposed to the Application layer is reached through an **Aggregate Root**.
18
+ - Aggregate roots implement `IAggregateRoot`, `EntityBase<TId>`, and the
19
+ audit/soft-delete/concurrency/domain-event interfaces they need:
20
+ `IFullAuditedObject` or `IAuditableEntityBase`, `ISoftDeletable`, `IConcurrencyTracked`,
21
+ `IHasDomainEvents`, `INamedEntity<TId>` when listable.
22
+
23
+ ### Aggregate root responsibilities
24
+
25
+ - Enforce all invariants for the aggregate.
26
+ - Own the lifecycle of its child entities.
27
+ - Raise domain events for state transitions.
28
+
29
+ ### Child entity ownership
30
+
31
+ - Child entities implement `IAggregateChild` and expose `GetAggregateRoot()`.
32
+ - They are mutated **only** through methods on the aggregate root.
33
+
34
+ ## Transactional / consistency boundaries
35
+
36
+ - **Transaction boundary equals aggregate boundary**: a single command mutates a single
37
+ aggregate per transaction.
38
+ - Cross-aggregate effects flow through **domain events** or **follow-up commands**
39
+ (see [[eventing]], [[cqrs]]).
40
+
41
+ ## Strongly typed IDs
42
+
43
+ - IDs are **strongly-typed Vogen value objects** (`<Aggregate>Id` as
44
+ `[ValueObject<Guid>] partial struct`).
45
+ - Raw `Guid` parameters at the Application boundary **MUST be wrapped** at the handler edge.
46
+
47
+ ## Value objects
48
+
49
+ - Value Objects are **sealed**, have **private constructors**, **validate in the constructor**,
50
+ throw `DomainException` on invariant violations, and expose a `From(...)` factory.
51
+
52
+ ## Domain events
53
+
54
+ - Derive from `DomainEventBase`, are immutable, added inside aggregate methods via
55
+ `AddDomainEvent(...)`, published explicitly by command handlers. See [[eventing]].
56
+
57
+ ## Domain services, repositories, specifications
58
+
59
+ - Invariants are enforced **inside the aggregate**; validators check request shape only.
60
+ - Repository usage is limited to `IRepository<T>` / `IReadRepository<T>` + `Specification<T>`.
61
+ - Specification pattern: query composition lives in the Domain. See [[persistence]].
62
+
63
+ ## Domain exception handling
64
+
65
+ - Exceptions are thrown by the Domain only (`DomainException`, `InvariantViolationException`).
66
+ Application code returns `Result<T>` (see [[cqrs]]).
67
+
68
+ ## Encapsulation, immutability, audit-awareness
69
+
70
+ - **Rich domain model** — no public setters on aggregates, no business logic in handlers.
71
+ - Soft-delete and audit behavior are first-class on protected aggregates
72
+ (see [[persistence]], [[auditing]]).
73
+
74
+ ## Anti-patterns (FORBIDDEN)
75
+
76
+ - **Anemic domain models** — no public setters, no "manager/service" classes mutating
77
+ aggregate state from outside, no primitive-typed IDs, no business logic in handlers.
78
+ - Cross-aggregate EF navigation properties — reference by strongly-typed ID only.
79
+ - Cross-bounded-context interaction except via Shared DTOs / `IMediator` / anti-corruption
80
+ adapters.
81
+
82
+ ## Canonical example
83
+
84
+ The worked `<SampleProjectName>` example for these rules lives in
85
+ `guardrails/technology/dotnet-webapi/examples/domain-driven-design.md`, mapped for `specify`.
86
+ The constitution set maps the rules without it.
87
+
88
+ ## Related
89
+
90
+ - [[modular-monolith]] · [[clean-architecture]] · [[cqrs]] · [[persistence]] ·
91
+ [[eventing]] · [[domain-driven-design.domain]]
@@ -0,0 +1,57 @@
1
+ # Eventing Standards
2
+
3
+ > Pure technology (domain-agnostic) — domain additions in [[eventing.domain]]. Commands: `/aw-spec-design`.
4
+
5
+ ## Domain events
6
+
7
+ - Domain Events derive from `DomainEventBase`, are **immutable**, and are added **inside**
8
+ aggregate methods via `AddDomainEvent(...)`.
9
+ - They are published **explicitly** by command handlers: `foreach` over `entity.DomainEvents`,
10
+ then `ClearDomainEvents()` before returning. See [[cqrs]].
11
+ - Cross-aggregate effects flow through domain events or follow-up commands — never a
12
+ multi-aggregate transaction.
13
+
14
+ ## CloudEvents conventions
15
+
16
+ - Asynchronous propagation of domain events to downstream consumers uses a **durable event
17
+ stream**: **CloudEvents** over the configured broker (e.g. Azure Service Bus, AWS SQS/SNS,
18
+ or RabbitMQ).
19
+ - Each module owns its **public events**; downstream consumers subscribe to them rather than
20
+ reading the OLTP database.
21
+
22
+ ## Event immutability
23
+
24
+ - Published events are immutable facts. Consumers build their own read models; they
25
+ **MUST NOT** query the source OLTP database directly.
26
+ - Analytics / reporting is built from emitted events — **never** by querying the OLTP DB
27
+ directly.
28
+
29
+ ## Event versioning
30
+
31
+ - The service publishes a versioned, machine-readable **AsyncAPI** document for event
32
+ contracts.
33
+ - Breaking changes to a domain-event contract are **MAJOR** version bumps and require the
34
+ AsyncAPI document to regenerate cleanly (CI gate). See [[api-versioning]].
35
+
36
+ ## Broker integration patterns
37
+
38
+ - The message broker is declared as an Aspire resource and referenced via `.WithReference(...)`;
39
+ connection details are discovered through Aspire, never hard-coded.
40
+ - Trace context **MUST** propagate across `IMediator.Send`, `HttpClient`, and EF Core; bypassing
41
+ the framework's `HttpClientFactory` is forbidden.
42
+ (Outbound domain-protocol propagation is covered in [[eventing.domain]].)
43
+
44
+ ## Inbound integration rule (generic)
45
+
46
+ - Inbound integrations flow through **Interop adapters** that translate to internal commands;
47
+ they **MUST NOT** write directly to aggregates. (Domain feed types in [[eventing.domain]].)
48
+
49
+ ## Canonical example
50
+
51
+ The worked `<SampleProjectName>` example for these rules lives in
52
+ `guardrails/technology/dotnet-webapi/examples/eventing.md`, mapped for `design`. The
53
+ constitution set maps the rules without it.
54
+
55
+ ## Related
56
+
57
+ - [[cqrs]] · [[modular-monolith]] · [[api-versioning]] · [[eventing.domain]]
@@ -0,0 +1,75 @@
1
+ # API Versioning Policy — canonical example
2
+
3
+ > The worked `<SampleProjectName>` example for
4
+ > `guardrails/technology/dotnet-webapi/api-versioning.md`. It is reference material for the
5
+ > phases that generate code — mapped for `design` — and carries no rule of its own: where this
6
+ > example and the rule file disagree, the rule file wins.
7
+ >
8
+ > It is deliberately absent from the `## /aw-spec-constitution` set. The constitution is a
9
+ > thin authority document — one declarative line and a `→` pointer per principle — and has no
10
+ > use for sample code.
11
+
12
+ ## Canonical example (agent reference — `<SampleProjectName>` sample)
13
+
14
+ ETag round-trip: the endpoint reads `If-Match` on update and sets the `ETag` on success;
15
+ the handler compares the token and translates an EF conflict to `409 concurrency.conflict`:
16
+
17
+ ```csharp
18
+ // Endpoint (PUT /projects/{id:guid})
19
+ var id = Route<Guid>("id");
20
+ var token = HttpContext.Request.GetIfMatchBase64Token(); // extract If-Match
21
+
22
+ var result = await _mediator.Send(new UpdateProjectCommand(
23
+ id, req.Name, req.Description, req.StartDate, req.EndDate, req.OwnerId, token), ct);
24
+
25
+ if (result.IsSuccess && !string.IsNullOrWhiteSpace(result.Value?.RowVersionBase64))
26
+ HttpContext.Response.SetETagFromBase64(result.Value!.RowVersionBase64); // set ETag
27
+ return result;
28
+ ```
29
+
30
+ ```csharp
31
+ // Handler — compare the supplied token, and catch EF's concurrency exception
32
+ var current = entity.RowVersion is { Length: > 0 } rv ? Convert.ToBase64String(rv) : string.Empty;
33
+ if (string.IsNullOrWhiteSpace(request.RowVersionBase64) ||
34
+ !string.Equals(current, request.RowVersionBase64, StringComparison.Ordinal))
35
+ return Result<ProjectDto>.Failure(new Error(
36
+ "concurrency.conflict", "Resource was modified by another process. Reload and retry.",
37
+ 409, "projects"));
38
+
39
+ entity.Update(request.Name, request.Description, request.StartDate, request.EndDate, ownerId);
40
+ await _repo.UpdateAsync(entity, ct);
41
+
42
+ try { await _uow.SaveChangesAsync(ct); }
43
+ catch (DbUpdateConcurrencyException)
44
+ {
45
+ return Result<ProjectDto>.Failure(new Error(
46
+ "concurrency.conflict", "Resource was modified by another process. Reload and retry.",
47
+ 409, "projects"));
48
+ }
49
+ ```
50
+
51
+ ETag token helpers — strong tokens; strip `W/` weak prefix and quotes on read:
52
+
53
+ ```csharp
54
+ // <SampleProjectName>.Service/Utilities/HttpRequestETagExtensions.cs
55
+ public static string GetIfMatchBase64Token(this HttpRequest request, string? fallback = null)
56
+ {
57
+ var token = request.Headers.IfMatch.FirstOrDefault();
58
+ return !string.IsNullOrWhiteSpace(token) ? SanitizeETagToken(token) : (fallback ?? string.Empty);
59
+ }
60
+
61
+ public static string SanitizeETagToken(string? raw)
62
+ {
63
+ if (string.IsNullOrWhiteSpace(raw)) return string.Empty;
64
+ var token = raw.Trim();
65
+ if (token.StartsWith("W/")) token = token[2..].Trim(); // strip weak prefix
66
+ return token.Trim('"'); // strip quotes
67
+ }
68
+
69
+ // On success the endpoint sets the strong ETag from the DTO's RowVersionBase64:
70
+ HttpContext.Response.SetETagFromBase64(result.Value!.RowVersionBase64);
71
+ ```
72
+
73
+ ## Related
74
+
75
+ - Rule file: `guardrails/technology/dotnet-webapi/api-versioning.md`
@@ -0,0 +1,84 @@
1
+ # Auditing & Observability Standards — canonical example
2
+
3
+ > The worked `<SampleProjectName>` example for `guardrails/technology/dotnet-webapi/auditing.md`.
4
+ > It is reference material for the phases that generate code — mapped for `design` — and
5
+ > carries no rule of its own: where this example and the rule file disagree, the rule file
6
+ > wins.
7
+ >
8
+ > It is deliberately absent from the `## /aw-spec-constitution` set. The constitution is a
9
+ > thin authority document — one declarative line and a `→` pointer per principle — and has no
10
+ > use for sample code.
11
+
12
+ ## Canonical example (agent reference — `<SampleProjectName>` sample)
13
+
14
+ ```csharp
15
+ // Basic — lifecycle stamps only
16
+ public sealed class Category :
17
+ AggregateRootBase<CategoryId>, IAggregateRoot,
18
+ IAuditedObject // creation + modification
19
+ {
20
+ public DateTimeOffset CreatedOn { get; set; }
21
+ public string CreatedBy { get; set; } = default!;
22
+ public DateTimeOffset? ModifiedOn { get; set; }
23
+ public string? ModifiedBy { get; set; }
24
+ }
25
+
26
+ // Advanced — full lifecycle + field-level (before/after) tracking
27
+ public sealed class Project :
28
+ AggregateRootBase<ProjectId>, IAggregateRoot,
29
+ IFullAuditedObject, // ICreationAudited + IModificationAudited + IDeletionAudited
30
+ IFieldAudited, // opt-in to field-level (before/after) auditing
31
+ ISoftDeletable, IConcurrencyTracked, IHasDomainEvents
32
+ {
33
+ public DateTimeOffset CreatedOn { get; set; }
34
+ public string CreatedBy { get; set; } = default!;
35
+ public DateTimeOffset? ModifiedOn { get; set; }
36
+ public string? ModifiedBy { get; set; }
37
+ public bool IsDeleted { get; set; }
38
+ public DateTimeOffset? DeletedOn { get; set; }
39
+ public string? DeletedBy { get; set; }
40
+ // ...
41
+ }
42
+ ```
43
+
44
+ The DbContext applies audit (plus soft-delete/tenant) behaviors centrally:
45
+
46
+ ```csharp
47
+ // OnModelCreating — see [[persistence]] for the full DbContext
48
+ modelBuilder.ApplyCrossCuttingBehaviors(this); // wires audit interceptors + filters
49
+ ```
50
+
51
+ Composition — enable auditing on the repository stack (one `EnableAdvancedAuditing()` registers
52
+ the interceptor that serves **both** levels; per-aggregate level is decided by the interfaces
53
+ above) and route audit records to a separate, append-only store (schema `Auditing`, prefix
54
+ `Audit_`):
55
+
56
+ ```csharp
57
+ // <SampleProjectName>.Service/Extensions/InfrastructureServiceRegistration.cs
58
+ services.AddRepositories(builder => builder
59
+ .UseSingleDbContextEFRepositories<ApplicationDbContext>(/* ... */)
60
+ .EnableSoftDelete()
61
+ .EnableAdvancedAuditing() // AdvancedAuditingSaveChangesInterceptor
62
+ .Done(), o => o.Provider = "EfCore");
63
+
64
+ services.AddDataStore(b => b.UseEfCoreDataStore(/* ... */), o =>
65
+ {
66
+ o.Strategy = DataStoreStrategy.Shared; // infra tables (audit, tenancy) in one store
67
+ o.TablePrefix = "AppWeaver_";
68
+ o.AutoMigrate = true;
69
+ });
70
+
71
+ services.AddAuditing(b => b
72
+ .UseEfCoreAuditing(o =>
73
+ {
74
+ o.TablePrefix = "Audit_";
75
+ o.SchemaName = "Auditing";
76
+ o.ExcludeShadowProperties = true;
77
+ })
78
+ .UseAppWeaverDataStore(),
79
+ o => { o.IsEnabled = true; o.EnableFieldLevelAuditing = true; }); // field-level = Advanced
80
+ ```
81
+
82
+ ## Related
83
+
84
+ - Rule file: `guardrails/technology/dotnet-webapi/auditing.md`