azcodr 1.5.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/.agents/hooks.json +42 -42
  2. package/.agents/hooks.json.example +42 -42
  3. package/.agents/mcp_config.json.example +29 -29
  4. package/.agents/scripts/safety_guard.sh +143 -34
  5. package/.agents/scripts/verify_completion.sh +90 -27
  6. package/.agents/skills/agentic-architect/SKILL.md +125 -125
  7. package/.agents/skills/agentic-architect/references/agents_md_template.md +62 -62
  8. package/.agents/skills/agentic-architect/references/refinement_workflow.md +32 -32
  9. package/.agents/skills/agentic-architect/references/skill_architecture_inquiry.md +63 -63
  10. package/.agents/skills/agentic-architect/references/skill_template.md +56 -56
  11. package/.agents/skills/agentic-architect/scripts/validate_agentic_configs.sh +402 -402
  12. package/.agents/skills/clean-code-refactor/SKILL.md +91 -91
  13. package/.agents/skills/clean-code-refactor/references/clean_code_smells.md +27 -27
  14. package/.agents/skills/clean-code-refactor/references/design_patterns_ts.md +65 -65
  15. package/.agents/skills/compliance-audit/SKILL.md +120 -120
  16. package/.agents/skills/compliance-audit/references/owasp_top10_controls.md +16 -16
  17. package/.agents/skills/compliance-audit/references/soc2_iso_controls.md +28 -28
  18. package/.agents/skills/lets-build/SKILL.md +173 -173
  19. package/.agents/skills/lets-build/references/architecture_interview_matrix.md +115 -115
  20. package/.agents/skills/lets-build/references/hexagonal_bootstrap_scaffolds.md +160 -160
  21. package/.agents/skills/lets-build/references/project_readme_template.md +79 -79
  22. package/.agents/skills/lets-build/scripts/bootstrap_workspace.sh +419 -255
  23. package/.agents/skills/product-analyst/SKILL.md +154 -154
  24. package/.agents/skills/product-analyst/references/backlog_ordering_techniques.md +107 -107
  25. package/.agents/skills/product-analyst/references/gherkin_patterns.md +46 -46
  26. package/.agents/skills/product-analyst/references/invest_checklist.md +38 -38
  27. package/.agents/skills/product-analyst/references/okr_alignment_guide.md +76 -76
  28. package/.agents/skills/product-analyst/references/smart_tasks.md +59 -59
  29. package/.agents/skills/relentless-questioner/SKILL.md +128 -128
  30. package/.agents/skills/relentless-questioner/references/adaptive_question_trees.md +102 -102
  31. package/.editorconfig +19 -19
  32. package/.github/workflows/ci.yml +167 -78
  33. package/.github/workflows/publish.yml +200 -0
  34. package/.gitignore +40 -25
  35. package/AGENTS.md +103 -102
  36. package/LICENSE +21 -21
  37. package/README.md +168 -165
  38. package/bin/azcodr.js +14 -228
  39. package/docs/knowledge/ubiquitous_language.md +31 -18
  40. package/docs/rules/agentic_configuration.md +259 -259
  41. package/docs/rules/api_architecture.md +179 -179
  42. package/docs/rules/authentication.md +76 -76
  43. package/docs/rules/authorization.md +75 -75
  44. package/docs/rules/caching.md +69 -69
  45. package/docs/rules/clean_code.md +62 -62
  46. package/docs/rules/cloud_native.md +41 -41
  47. package/docs/rules/cqrs.md +203 -203
  48. package/docs/rules/database_design.md +125 -125
  49. package/docs/rules/database_operations.md +69 -69
  50. package/docs/rules/design_patterns.md +98 -98
  51. package/docs/rules/devops_ci_cd.md +76 -76
  52. package/docs/rules/domain_driven_design.md +122 -122
  53. package/docs/rules/error_handling.md +54 -52
  54. package/docs/rules/feature_flags.md +59 -59
  55. package/docs/rules/frontend_architecture.md +157 -157
  56. package/docs/rules/multitenancy_architecture.md +98 -98
  57. package/docs/rules/product_ownership.md +127 -127
  58. package/docs/rules/project_management.md +49 -49
  59. package/docs/rules/relentless_questioning.md +52 -52
  60. package/docs/rules/requirements_engineering.md +98 -98
  61. package/docs/rules/security_compliance.md +53 -53
  62. package/docs/rules/server_driven_ui.md +88 -88
  63. package/docs/rules/test_driven_development.md +185 -185
  64. package/docs/rules/transactional_email.md +27 -27
  65. package/docs/rules/type_safety.md +65 -65
  66. package/docs/rules/ui_ux_architecture.md +150 -150
  67. package/docs/rules/workflow_state_machines.md +117 -117
  68. package/lib/cli-parse.js +51 -0
  69. package/lib/cli-target.js +109 -0
  70. package/lib/cli.js +180 -0
  71. package/lib/errors.js +28 -0
  72. package/lib/git.js +29 -0
  73. package/lib/guards.js +96 -0
  74. package/lib/index.d.ts +199 -134
  75. package/lib/index.js +5 -5
  76. package/lib/links.js +123 -0
  77. package/lib/permissions.js +44 -0
  78. package/lib/repo.js +90 -0
  79. package/lib/scaffold.js +238 -448
  80. package/memory.md +119 -36
  81. package/package.json +65 -62
  82. package/scripts/test_coverage.js +66 -38
  83. package/scripts/validate/adr.js +151 -0
  84. package/scripts/validate/io.js +84 -0
  85. package/scripts/validate/links.js +167 -0
  86. package/scripts/validate/parity.js +124 -0
  87. package/scripts/validate/root.js +184 -0
  88. package/scripts/validate/rules.js +44 -0
  89. package/scripts/validate/skills.js +96 -0
  90. package/scripts/validate/text.js +29 -0
  91. package/scripts/validate-cli.js +13 -0
  92. package/scripts/validate.js +140 -258
  93. package/.github/copilot-instructions.md +0 -1
@@ -1,157 +1,157 @@
1
- # Frontend Architecture & Client State Management
2
-
3
- > **Core Mandate:** Enforce production-grade client architecture: accessible headless component primitives, WCAG 2.2 Level AA compliance, asynchronous server-state cache synchronization and deduplication, declarative contract schema form validation, bidirectional URL navigation synchronization, explicit 5-tier state separation, and symmetrical design tokens.
4
-
5
- ---
6
-
7
- ## 1. The YAGNI Gate: Semantic Markup & Headless Primitives vs. Premature Sprawl
8
-
9
- Frontend engineering is frequently derailed by two opposing anti-patterns: **reinventing the wheel** (hand-rolling custom dialogs and bespoke CSS architectures) or **premature framework sprawl** (installing heavy global state machines for simple data flows).
10
-
11
- ```mermaid
12
- flowchart TD
13
- subgraph Gate ["Frontend Architecture YAGNI Gate"]
14
- B1["1. SIMPLE BASELINE (Day 1)"]
15
- B1_D["• Semantic HTML/markup styled with utility classes.<br/>• Battle-tested accessible headless primitives (Radix, Melt, Kobalte, PrimeVue).<br/>• Zero bespoke CSS architectures, unstyled div modals, or Redux."]
16
-
17
- B2["2. ANTI-TRIGGERS (Strictly Forbidden)"]
18
- B2_D["• Headless backends, REST/gRPC microservices, or cloud workers.<br/>• Terminal CLI utilities, embedded libraries, or game engines.<br/>• Monolithic global state stores (Redux, MobX, Pinia) before separating server cache."]
19
-
20
- B3["3. THE TIPPING POINT (Graduation Threshold)"]
21
- B3_D["• Dynamic client interfaces with asynchronous server data fetching.<br/>• Multi-step declarative form submissions and complex workflows.<br/>• Strict WCAG 2.2 AA accessibility, focus trapping, and keyboard navigation."]
22
-
23
- B1 --- B1_D
24
- B2 --- B2_D
25
- B3 --- B3_D
26
- end
27
- ```
28
-
29
- ---
30
-
31
- ## 2. The Asymmetry Law: Outside-In Discovery vs. Inside-Out Execution
32
-
33
- A fundamental architectural question is: **Does the User Interface dictate Business Logic, or does Business Logic dictate the UI?**
34
-
35
- The answer is governed by the **Outside-In Discovery vs. Inside-Out Execution Asymmetry**:
36
-
37
- ```mermaid
38
- flowchart LR
39
- subgraph Discovery ["Outside-In Discovery (Phase 1 & 2)"]
40
- UI["User Interface & Interaction Model<br/>(Web GUI, Mobile, or Terminal CLI)"]
41
- UC["Inbound Driving Port<br/>(Use Case / Command DTO)"]
42
- UI -->|"Discovers Required Capabilities"| UC
43
- end
44
-
45
- subgraph Execution ["Inside-Out Execution (Phase 3 & 4)"]
46
- DM["Domain Core & Invariants<br/>(100% UI-Agnostic Rules & State Machines)"]
47
- AD["Outbound Driven Adapters<br/>(Database, Email, External Services)"]
48
- UC -->|"Executes Isolated Logic"| DM
49
- DM -->|"Persists / Notifies"| AD
50
- end
51
- ```
52
-
53
- ### 1. Outside-In Discovery (Why Interaction Must Be Refined Early)
54
- - The user's operational mental model, workflow steps, and interaction touchpoints (whether Web forms, CLI flags, or API endpoints) **guide the discovery of system capabilities**.
55
- - If business logic is authored in a vacuum without interaction analysis, engineers build speculative methods and database models that do not align with user journeys (**The Anemic Core Antipattern**).
56
- - *Mandate:* In Phase 1 (Requirements) and Phase 2 (Domain Analysis), interaction models and wireframe workflows must be refined early via [`product-analyst`](../../.agents/skills/product-analyst/SKILL.md) and [`ui_ux_architecture.md`](./ui_ux_architecture.md).
57
-
58
- ### 2. Inside-Out Execution (Why Domain Logic Remains Pure)
59
- - Once discovered, **business invariants are 100% decoupled from the UI**.
60
- - A business rule (e.g. *"An invoice cannot be paid twice"*, *"Discount cannot exceed 50%"*) must never live in a React `onClick` handler, a component hook, or a CLI flag parser (**The Smart UI Antipattern**).
61
- - The presentation layer merely parses user interaction into a plain **Command DTO** and calls an **Application Use Case** (Driving Port).
62
- - If the Web UI is replaced with a CLI or a background job, the core domain logic requires **zero modifications**.
63
-
64
- ### 3. What If a Project Has No UI? (Headless Topologies)
65
- - For Headless Backends, Daemon Workers, and Embedded Systems:
66
- - The **API Schema (OpenAPI / gRPC Protobuf) or Function Signature IS the UI**.
67
- - For a CLI Utility, the **Command Pipeline (flags, stdin/stdout, exit codes)** IS the UI.
68
- - The principle remains identical: the external interface defines the boundary contract, while the internal engine enforces pure invariants.
69
-
70
- ---
71
-
72
- ## 3. Component Primitives, Headless Accessibility & WCAG 2.2 Standards
73
-
74
- - **Accessible Headless Primitives**: All interactive UI components (dialogs, dropdowns, selects, tabs, tooltips, popovers) must decouple behavioral accessibility (focus trapping, keyboard navigation, ARIA states) from visual presentation using headless primitives:
75
- - *React:* `@radix-ui` / `shadcn/ui` in `@/components/ui/`
76
- - *Vue:* `radix-vue` / `shadcn-vue` or `primevue`
77
- - *Svelte:* `melt-ui` / `bits-ui`
78
- - *Solid:* `@kobalte/core`
79
- - *Angular:* `@angular/cdk/a11y`
80
- - **Zero Unstyled Raw Elements**: Never create unstyled raw HTML modals, dropdowns, or custom select tags using raw `<div>` tags and ad-hoc mouse-only click handlers.
81
- - **Focus Management & Trapping**:
82
- - Modal dialogs must trap keyboard focus within the dialog container while open.
83
- - Closing a dialog must return keyboard focus deterministically to the triggering element.
84
- - **Visible Focus Indicators**: Never remove default outline rings (`outline: none`) without providing an explicit, high-contrast replacement (`focus-visible:ring-2 focus-visible:ring-offset-2`).
85
- - **Dynamic Content & ARIA Live Regions**:
86
- - Asynchronous notifications, toast alerts, and status updates must use `role="status"` or `aria-live="polite"` so screen readers announce changes without interrupting the user.
87
- - Critical error alerts must use `role="alert"` or `aria-live="assertive"`.
88
- - **Strict Prohibition of Native Dialogs**: Browser-native `window.alert()` and `window.confirm()` are strictly forbidden. Use accessible headless dialogs (`<ConfirmDialog />`).
89
- - **Utility Styling & Class Merging (`cn` helper)**: Combine utility classes using deterministic class merging (e.g., `clsx` and `tailwind-merge` via `cn(...)`) to allow clean prop overrides and consistent theming.
90
-
91
- ---
92
-
93
- ## 4. Server-State Cache Synchronization & Invalidation
94
-
95
- - **Decoupling Remote Cache from Local State**: Server state (owned remotely, asynchronous, shared across clients) must never be treated as local synchronous client state.
96
- - **Mandatory Cache Synchronization Engine**: Asynchronous data fetching, caching, deduplication, and background revalidation must use a dedicated cache synchronization manager (e.g., TanStack Query, SWR, or RTK Query in React; Pinia Colada or VueUse `useFetch` in Vue; Superforms or SvelteKit load functions in Svelte; Angular Signals with HttpClient).
97
- - **Elimination of Raw Lifecycle Fetch Loops**:
98
- - *Anti-Pattern:* Uncoordinated manual fetching in component lifecycles (`useEffect(() => { fetch().then(...) })`, `onMounted`, `ngOnInit`) with hand-rolled `isLoading` and `error` boolean states.
99
- - *Standard Pattern (Query Hook / Cache Invalidation):*
100
- ```tsx
101
- const { data: resources, isLoading, error } = useQuery({
102
- queryKey: ['resources', tenantId],
103
- queryFn: () => api.getResources(tenantId),
104
- });
105
- ```
106
- - **Declarative Mutations & Cache Invalidation**:
107
- - Mutations must declare side-effects that explicitly invalidate affected cache keys rather than imperatively splicing local component state arrays:
108
- ```tsx
109
- const queryClient = useQueryClient();
110
- const createResourceMutation = useMutation({
111
- mutationFn: (newResource: CreateResourceInput) => api.createResource(newResource),
112
- onSuccess: () => {
113
- queryClient.invalidateQueries({ queryKey: ['resources'] });
114
- },
115
- });
116
- ```
117
- - **Hierarchical Query Keys**: Format query keys hierarchically as structured tuples: `['entity', id, ...filters]`, e.g., `['orders', orderId]`, `['users', tenantId]`.
118
-
119
- ---
120
-
121
- ## 5. Form State Management & Fail-Fast Schema Validation
122
-
123
- - **Mandatory Schema Validation**: Every form submission must be validated against a formal declarative schema (Zod, Valibot, standard-schema, or framework validator) that mirrors shared DTO/input contracts.
124
- - **Dedicated Form State Engines**: Use dedicated form engines (React Hook Form, TanStack Form, VeeValidate, Superforms, Angular Reactive Forms) that track field dirty states, touched states, and asynchronous validation without triggering full component tree re-renders.
125
- - **Zero Unvalidated Multi-Field Objects**:
126
- - *Anti-Pattern:* Unvalidated ad-hoc dictionary state (`useState({ name: '', email: '' })`) with manual string checking in submit handlers.
127
- - *Standard Pattern:*
128
- ```tsx
129
- const form = useForm<CreateUserInput>({
130
- resolver: zodResolver(createUserSchema),
131
- defaultValues: { name: '', email: '' },
132
- });
133
- ```
134
- - **Accessible Error Linking**: Form inputs must bind validation errors to `aria-invalid="true"` and `aria-describedby="<field>-error"`. Every input must have an associated semantic `<label>`.
135
-
136
- ---
137
-
138
- ## 6. The 5-Tier State Hierarchy & Bidirectional URL Navigation
139
-
140
- Never dump all application state into a single global state container. Enforce strict categorical separation across 5 distinct lifecycles:
141
-
142
- 1. **Server State (Remote Cache)**: Managed exclusively by the query cache engine; invalidated by resource keys.
143
- 2. **URL State (Navigation / Search / Pagination / Filters)**:
144
- - Must synchronize bidirectionally with URL search parameters (`useSearchParams`) to ensure deep linkability, bookmarkability, and seamless browser history (back/forward) navigation.
145
- - Standard format: `?tab=security&page=2&limit=25&sort=createdAt&order=desc&status=ACTIVE`.
146
- - Modals and drawers representing actionable entities must synchronize with the URL (e.g. `?modal=edit-user&userId=123`).
147
- 3. **Form State (Transient Edits)**: Managed by form validation engines; discarded after submission or reset.
148
- 4. **Local Component State (Ephemeral UI)**: Managed by primitive local component state (`useState`, `ref`, `$state`) strictly for local UI toggles (dropdown open, accordion expanded, hover).
149
- 5. **Global Application State (Session / Context)**: Managed by lightweight client stores (Zustand, Pinia, Context, Signals) strictly for cross-cutting session data (current user, tenant context, active feature flags).
150
- 6. **Data Grids & Large Tables**: When building sortable, paginated, or virtualized tables, standardize on headless table engines (TanStack Table, AG Grid) with row virtualization for datasets exceeding 100 rows.
151
-
152
- ---
153
-
154
- ## 7. Theme Architecture & Symmetrical Design Tokens
155
-
156
- - **Symmetric Design Tokens**: Ensure foundational CSS variables (`--background`, `--foreground`, `--card`, `--border`, `--popover`) are symmetrically declared across `:root` and `.dark`. Omitted root tokens in `.dark` result in unstyled backgrounds and illegible text when switching themes.
157
- - **System Preference Detection & Reactive Synchronization**: `ThemeProvider` implementations must listen to `window.matchMedia('(prefers-color-scheme: dark)')` with dynamic event listeners so OS appearance toggles seamlessly propagate in real-time, and synchronize `document.documentElement.style.colorScheme = resolvedTheme` to ensure browser-native elements (scrollbars, input widgets) match the active theme.
1
+ # Frontend Architecture & Client State Management
2
+
3
+ > **Core Mandate:** Enforce production-grade client architecture: accessible headless component primitives, WCAG 2.2 Level AA compliance, asynchronous server-state cache synchronization and deduplication, declarative contract schema form validation, bidirectional URL navigation synchronization, explicit 5-tier state separation, and symmetrical design tokens.
4
+
5
+ ---
6
+
7
+ ## 1. The YAGNI Gate: Semantic Markup & Headless Primitives vs. Premature Sprawl
8
+
9
+ Frontend engineering is frequently derailed by two opposing anti-patterns: **reinventing the wheel** (hand-rolling custom dialogs and bespoke CSS architectures) or **premature framework sprawl** (installing heavy global state machines for simple data flows).
10
+
11
+ ```mermaid
12
+ flowchart TD
13
+ subgraph Gate ["Frontend Architecture YAGNI Gate"]
14
+ B1["1. SIMPLE BASELINE (Day 1)"]
15
+ B1_D["• Semantic HTML/markup styled with utility classes.<br/>• Battle-tested accessible headless primitives (Radix, Melt, Kobalte, PrimeVue).<br/>• Zero bespoke CSS architectures, unstyled div modals, or Redux."]
16
+
17
+ B2["2. ANTI-TRIGGERS (Strictly Forbidden)"]
18
+ B2_D["• Headless backends, REST/gRPC microservices, or cloud workers.<br/>• Terminal CLI utilities, embedded libraries, or game engines.<br/>• Monolithic global state stores (Redux, MobX, Pinia) before separating server cache."]
19
+
20
+ B3["3. THE TIPPING POINT (Graduation Threshold)"]
21
+ B3_D["• Dynamic client interfaces with asynchronous server data fetching.<br/>• Multi-step declarative form submissions and complex workflows.<br/>• Strict WCAG 2.2 AA accessibility, focus trapping, and keyboard navigation."]
22
+
23
+ B1 --- B1_D
24
+ B2 --- B2_D
25
+ B3 --- B3_D
26
+ end
27
+ ```
28
+
29
+ ---
30
+
31
+ ## 2. The Asymmetry Law: Outside-In Discovery vs. Inside-Out Execution
32
+
33
+ A fundamental architectural question is: **Does the User Interface dictate Business Logic, or does Business Logic dictate the UI?**
34
+
35
+ The answer is governed by the **Outside-In Discovery vs. Inside-Out Execution Asymmetry**:
36
+
37
+ ```mermaid
38
+ flowchart LR
39
+ subgraph Discovery ["Outside-In Discovery (Phase 1 & 2)"]
40
+ UI["User Interface & Interaction Model<br/>(Web GUI, Mobile, or Terminal CLI)"]
41
+ UC["Inbound Driving Port<br/>(Use Case / Command DTO)"]
42
+ UI -->|"Discovers Required Capabilities"| UC
43
+ end
44
+
45
+ subgraph Execution ["Inside-Out Execution (Phase 3 & 4)"]
46
+ DM["Domain Core & Invariants<br/>(100% UI-Agnostic Rules & State Machines)"]
47
+ AD["Outbound Driven Adapters<br/>(Database, Email, External Services)"]
48
+ UC -->|"Executes Isolated Logic"| DM
49
+ DM -->|"Persists / Notifies"| AD
50
+ end
51
+ ```
52
+
53
+ ### 1. Outside-In Discovery (Why Interaction Must Be Refined Early)
54
+ - The user's operational mental model, workflow steps, and interaction touchpoints (whether Web forms, CLI flags, or API endpoints) **guide the discovery of system capabilities**.
55
+ - If business logic is authored in a vacuum without interaction analysis, engineers build speculative methods and database models that do not align with user journeys (**The Anemic Core Antipattern**).
56
+ - *Mandate:* In Phase 1 (Requirements) and Phase 2 (Domain Analysis), interaction models and wireframe workflows must be refined early via [`product-analyst`](../../.agents/skills/product-analyst/SKILL.md) and [`ui_ux_architecture.md`](./ui_ux_architecture.md).
57
+
58
+ ### 2. Inside-Out Execution (Why Domain Logic Remains Pure)
59
+ - Once discovered, **business invariants are 100% decoupled from the UI**.
60
+ - A business rule (e.g. *"An invoice cannot be paid twice"*, *"Discount cannot exceed 50%"*) must never live in a React `onClick` handler, a component hook, or a CLI flag parser (**The Smart UI Antipattern**).
61
+ - The presentation layer merely parses user interaction into a plain **Command DTO** and calls an **Application Use Case** (Driving Port).
62
+ - If the Web UI is replaced with a CLI or a background job, the core domain logic requires **zero modifications**.
63
+
64
+ ### 3. What If a Project Has No UI? (Headless Topologies)
65
+ - For Headless Backends, Daemon Workers, and Embedded Systems:
66
+ - The **API Schema (OpenAPI / gRPC Protobuf) or Function Signature IS the UI**.
67
+ - For a CLI Utility, the **Command Pipeline (flags, stdin/stdout, exit codes)** IS the UI.
68
+ - The principle remains identical: the external interface defines the boundary contract, while the internal engine enforces pure invariants.
69
+
70
+ ---
71
+
72
+ ## 3. Component Primitives, Headless Accessibility & WCAG 2.2 Standards
73
+
74
+ - **Accessible Headless Primitives**: All interactive UI components (dialogs, dropdowns, selects, tabs, tooltips, popovers) must decouple behavioral accessibility (focus trapping, keyboard navigation, ARIA states) from visual presentation using headless primitives:
75
+ - *React:* `@radix-ui` / `shadcn/ui` in `@/components/ui/`
76
+ - *Vue:* `radix-vue` / `shadcn-vue` or `primevue`
77
+ - *Svelte:* `melt-ui` / `bits-ui`
78
+ - *Solid:* `@kobalte/core`
79
+ - *Angular:* `@angular/cdk/a11y`
80
+ - **Zero Unstyled Raw Elements**: Never create unstyled raw HTML modals, dropdowns, or custom select tags using raw `<div>` tags and ad-hoc mouse-only click handlers.
81
+ - **Focus Management & Trapping**:
82
+ - Modal dialogs must trap keyboard focus within the dialog container while open.
83
+ - Closing a dialog must return keyboard focus deterministically to the triggering element.
84
+ - **Visible Focus Indicators**: Never remove default outline rings (`outline: none`) without providing an explicit, high-contrast replacement (`focus-visible:ring-2 focus-visible:ring-offset-2`).
85
+ - **Dynamic Content & ARIA Live Regions**:
86
+ - Asynchronous notifications, toast alerts, and status updates must use `role="status"` or `aria-live="polite"` so screen readers announce changes without interrupting the user.
87
+ - Critical error alerts must use `role="alert"` or `aria-live="assertive"`.
88
+ - **Strict Prohibition of Native Dialogs**: Browser-native `window.alert()` and `window.confirm()` are strictly forbidden. Use accessible headless dialogs (`<ConfirmDialog />`).
89
+ - **Utility Styling & Class Merging (`cn` helper)**: Combine utility classes using deterministic class merging (e.g., `clsx` and `tailwind-merge` via `cn(...)`) to allow clean prop overrides and consistent theming.
90
+
91
+ ---
92
+
93
+ ## 4. Server-State Cache Synchronization & Invalidation
94
+
95
+ - **Decoupling Remote Cache from Local State**: Server state (owned remotely, asynchronous, shared across clients) must never be treated as local synchronous client state.
96
+ - **Mandatory Cache Synchronization Engine**: Asynchronous data fetching, caching, deduplication, and background revalidation must use a dedicated cache synchronization manager (e.g., TanStack Query, SWR, or RTK Query in React; Pinia Colada or VueUse `useFetch` in Vue; Superforms or SvelteKit load functions in Svelte; Angular Signals with HttpClient).
97
+ - **Elimination of Raw Lifecycle Fetch Loops**:
98
+ - *Anti-Pattern:* Uncoordinated manual fetching in component lifecycles (`useEffect(() => { fetch().then(...) })`, `onMounted`, `ngOnInit`) with hand-rolled `isLoading` and `error` boolean states.
99
+ - *Standard Pattern (Query Hook / Cache Invalidation):*
100
+ ```tsx
101
+ const { data: resources, isLoading, error } = useQuery({
102
+ queryKey: ['resources', tenantId],
103
+ queryFn: () => api.getResources(tenantId),
104
+ });
105
+ ```
106
+ - **Declarative Mutations & Cache Invalidation**:
107
+ - Mutations must declare side-effects that explicitly invalidate affected cache keys rather than imperatively splicing local component state arrays:
108
+ ```tsx
109
+ const queryClient = useQueryClient();
110
+ const createResourceMutation = useMutation({
111
+ mutationFn: (newResource: CreateResourceInput) => api.createResource(newResource),
112
+ onSuccess: () => {
113
+ queryClient.invalidateQueries({ queryKey: ['resources'] });
114
+ },
115
+ });
116
+ ```
117
+ - **Hierarchical Query Keys**: Format query keys hierarchically as structured tuples: `['entity', id, ...filters]`, e.g., `['orders', orderId]`, `['users', tenantId]`.
118
+
119
+ ---
120
+
121
+ ## 5. Form State Management & Fail-Fast Schema Validation
122
+
123
+ - **Mandatory Schema Validation**: Every form submission must be validated against a formal declarative schema (Zod, Valibot, standard-schema, or framework validator) that mirrors shared DTO/input contracts.
124
+ - **Dedicated Form State Engines**: Use dedicated form engines (React Hook Form, TanStack Form, VeeValidate, Superforms, Angular Reactive Forms) that track field dirty states, touched states, and asynchronous validation without triggering full component tree re-renders.
125
+ - **Zero Unvalidated Multi-Field Objects**:
126
+ - *Anti-Pattern:* Unvalidated ad-hoc dictionary state (`useState({ name: '', email: '' })`) with manual string checking in submit handlers.
127
+ - *Standard Pattern:*
128
+ ```tsx
129
+ const form = useForm<CreateUserInput>({
130
+ resolver: zodResolver(createUserSchema),
131
+ defaultValues: { name: '', email: '' },
132
+ });
133
+ ```
134
+ - **Accessible Error Linking**: Form inputs must bind validation errors to `aria-invalid="true"` and `aria-describedby="<field>-error"`. Every input must have an associated semantic `<label>`.
135
+
136
+ ---
137
+
138
+ ## 6. The 5-Tier State Hierarchy & Bidirectional URL Navigation
139
+
140
+ Never dump all application state into a single global state container. Enforce strict categorical separation across 5 distinct lifecycles:
141
+
142
+ 1. **Server State (Remote Cache)**: Managed exclusively by the query cache engine; invalidated by resource keys.
143
+ 2. **URL State (Navigation / Search / Pagination / Filters)**:
144
+ - Must synchronize bidirectionally with URL search parameters (`useSearchParams`) to ensure deep linkability, bookmarkability, and seamless browser history (back/forward) navigation.
145
+ - Standard format: `?tab=security&page=2&limit=25&sort=createdAt&order=desc&status=ACTIVE`.
146
+ - Modals and drawers representing actionable entities must synchronize with the URL (e.g. `?modal=edit-user&userId=123`).
147
+ 3. **Form State (Transient Edits)**: Managed by form validation engines; discarded after submission or reset.
148
+ 4. **Local Component State (Ephemeral UI)**: Managed by primitive local component state (`useState`, `ref`, `$state`) strictly for local UI toggles (dropdown open, accordion expanded, hover).
149
+ 5. **Global Application State (Session / Context)**: Managed by lightweight client stores (Zustand, Pinia, Context, Signals) strictly for cross-cutting session data (current user, tenant context, active feature flags).
150
+ 6. **Data Grids & Large Tables**: When building sortable, paginated, or virtualized tables, standardize on headless table engines (TanStack Table, AG Grid) with row virtualization for datasets exceeding 100 rows.
151
+
152
+ ---
153
+
154
+ ## 7. Theme Architecture & Symmetrical Design Tokens
155
+
156
+ - **Symmetric Design Tokens**: Ensure foundational CSS variables (`--background`, `--foreground`, `--card`, `--border`, `--popover`) are symmetrically declared across `:root` and `.dark`. Omitted root tokens in `.dark` result in unstyled backgrounds and illegible text when switching themes.
157
+ - **System Preference Detection & Reactive Synchronization**: `ThemeProvider` implementations must listen to `window.matchMedia('(prefers-color-scheme: dark)')` with dynamic event listeners so OS appearance toggles seamlessly propagate in real-time, and synchronize `document.documentElement.style.colorScheme = resolvedTheme` to ensure browser-native elements (scrollbars, input widgets) match the active theme.
@@ -1,98 +1,98 @@
1
- # Multi-Tenancy Architecture, Isolation & Extensibility
2
-
3
- > **Core Mandate:** Enforce tenant context resolution from trusted cryptographic tokens, strict data isolation across the 4 tenancy models, leak-proof PostgreSQL Row-Level Security (RLS), and YAGNI-gated tenant extensibility (dynamic JSON schemas and sandboxed pluggable logic).
4
-
5
- ---
6
-
7
- ## 1. The Multi-Tenancy YAGNI Gate: Single-Tenant vs. Shared SaaS
8
-
9
- Multi-tenancy introduces significant operational complexity: tenant routing, cross-tenant data leak risks, noisy neighbor resource starvation, and complex database migrations. **Never force multi-tenant abstractions onto applications that execute in single-tenant boundaries.**
10
-
11
- ```mermaid
12
- flowchart TD
13
- subgraph MultiTenancyGate["Multi-Tenancy YAGNI Gate"]
14
- B1["1. Simple Baseline (Day 1)<br/>• Single-tenant application architecture<br/>• Standard database tables without tenant foreign keys<br/>• Zero RLS policies, tenant interceptors, or dynamic schemas"]
15
- B2["2. Anti-Triggers (Forbidden)<br/>• Single-tenant on-premise deployments or dedicated instances<br/>• Internal employee enterprise tools, developer CLIs, or games<br/>• Early-stage prototypes validating core domain logic"]
16
- B3["3. The Tipping Point (Graduation)<br/>• Multi-tenant B2B SaaS where independent organizations share infrastructure<br/>• Strict legal, SOC 2, and regulatory mandates prohibiting cross-tenant data leakage"]
17
- B1 -->|Forbidden if single-tenant| B2
18
- B1 -->|Triggered by B2B SaaS requirements| B3
19
- end
20
- ```
21
-
22
- ---
23
-
24
- ## 2. Tenant Context Resolution
25
-
26
- Tenant identity must be resolved at the edge/gateway from **cryptographically verified session context**, never from spoofable client input:
27
-
28
- ```mermaid
29
- flowchart LR
30
- Req["Incoming Request"] --> Auth["Auth Middleware<br/>Extract Verified tenantId from JWT"]
31
- Auth --> Ctx["AsyncLocalStorage / Context"]
32
- Ctx --> DB["Database Connection<br/>SET LOCAL app.current_tenant_id"]
33
- Ctx --> Audit["Audit / Event Log<br/>Tagged with tenantId"]
34
- ```
35
-
36
- ### Invariants:
37
- 1. **Never Trust Raw Query/Body Parameters**: Never accept `?tenantId=...` or `{ tenantId: "..." }` on public mutations without validating that the authenticated session owns that tenant.
38
- 2. **Ambient Context Propagation**: Bind the resolved `tenantId` to an ambient request context (e.g. `AsyncLocalStorage` in Node, `ThreadLocal` in Java, `context.Context` in Go) to prevent passing tenant IDs manually through every service layer.
39
-
40
- ---
41
-
42
- ## 3. The 4 Universal Data Isolation Models
43
-
44
- Choose the isolation model matching your security classification and cost profile:
45
-
46
- | Model | Isolation Mechanism | Operational Trade-off | Compliance Target |
47
- |---|---|---|---|
48
- | **1. Pooled with RLS** | Shared DB, shared schema; tables partitioned by `tenant_id` + Postgres RLS. | Lowest infrastructure cost, highest engineering rigor required. | Standard B2B SaaS, SOC 2 Type II. |
49
- | **2. Silo Schema** | Shared DB, separate database schema per tenant (`tenant_acme.*`). | High isolation; complex schema migrations across hundreds of schemas. | Regulated SaaS, HIPAA, FinTech. |
50
- | **3. Silo Database** | Separate physical or logical database instance per tenant. | Highest cost and isolation; zero cross-tenant blast radius. | Enterprise Dedicated, PCI-DSS Level 1. |
51
- | **4. App-Level Interceptor** | Shared DB, ORM/query builder automatically appends `WHERE tenant_id = :id`. | Brittle; human error in ad-hoc raw SQL queries bypasses isolation. | Forbidden for high-security applications. |
52
-
53
- ---
54
-
55
- ## 4. PostgreSQL Row-Level Security (RLS) Invariants
56
-
57
- When using **Model 1 (Pooled with RLS)**, enforce data isolation at the database engine level so that even a buggy or malicious application query cannot access another tenant's rows:
58
-
59
- ### 1. Dual-Lock Table Setup
60
- Every table containing tenant-scoped data must enable and force RLS:
61
- ```sql
62
- ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
63
- ALTER TABLE orders FORCE ROW LEVEL SECURITY;
64
- ```
65
- *(The `FORCE` clause ensures that table owners and superusers are also bound by the policy).*
66
-
67
- ### 2. Session Context Binding
68
- The application connection pool must initialize the tenant session variable inside every transactional checkout:
69
- ```sql
70
- -- Executed inside transaction before running queries
71
- SELECT set_config('app.current_tenant_id', :tenantId, true);
72
- ```
73
-
74
- ### 3. Declarative Tenant Isolation Policy
75
- ```sql
76
- CREATE POLICY tenant_isolation_policy ON orders
77
- AS RESTRICTIVE
78
- FOR ALL
79
- TO application_user
80
- USING (tenant_id = NULLIF(current_setting('app.current_tenant_id', true), '')::UUID)
81
- WITH CHECK (tenant_id = NULLIF(current_setting('app.current_tenant_id', true), '')::UUID);
82
- ```
83
-
84
- ---
85
-
86
- ## 5. Advanced Tenant Extensibility (YAGNI Gated)
87
-
88
- ### 5.1. Dynamic Schemas (Runtime Custom Fields)
89
- - **Tipping Point:** External enterprise tenants require self-service custom fields without engineering running relational DDL migrations.
90
- - **Hybrid Storage Pattern:** Core relational columns for shared invariants + `custom_attributes JSONB` validated against **JSON Schema Draft 2020-12** stored per tenant.
91
- - **Fail-Fast Schema Validation:** Custom field inputs must be validated against the tenant's compiled JSON schema before database persistence.
92
-
93
- ### 5.2. Pluggable Tenant Logic (Sandboxed Scripting)
94
- - **Tipping Point:** Enterprise tenants require custom business logic (tax calculation, approval routing) executed at runtime.
95
- - **Zero Raw `eval()`**: Never execute tenant code via raw `eval()`, Python `exec()`, or NodeJS VM isolates.
96
- - **Safe Sandboxing**:
97
- - *Simple Expressions:* Use **Common Expression Language (CEL)** (Google) for safe, deterministic boolean and mathematical evaluation.
98
- - *Complex Logic:* Compile tenant extension plugins to **WebAssembly (Wasm)** executed via Wasmer or Wasmtime with strict CPU time and memory quotas.
1
+ # Multi-Tenancy Architecture, Isolation & Extensibility
2
+
3
+ > **Core Mandate:** Enforce tenant context resolution from trusted cryptographic tokens, strict data isolation across the 4 tenancy models, leak-proof PostgreSQL Row-Level Security (RLS), and YAGNI-gated tenant extensibility (dynamic JSON schemas and sandboxed pluggable logic).
4
+
5
+ ---
6
+
7
+ ## 1. The Multi-Tenancy YAGNI Gate: Single-Tenant vs. Shared SaaS
8
+
9
+ Multi-tenancy introduces significant operational complexity: tenant routing, cross-tenant data leak risks, noisy neighbor resource starvation, and complex database migrations. **Never force multi-tenant abstractions onto applications that execute in single-tenant boundaries.**
10
+
11
+ ```mermaid
12
+ flowchart TD
13
+ subgraph MultiTenancyGate["Multi-Tenancy YAGNI Gate"]
14
+ B1["1. Simple Baseline (Day 1)<br/>• Single-tenant application architecture<br/>• Standard database tables without tenant foreign keys<br/>• Zero RLS policies, tenant interceptors, or dynamic schemas"]
15
+ B2["2. Anti-Triggers (Forbidden)<br/>• Single-tenant on-premise deployments or dedicated instances<br/>• Internal employee enterprise tools, developer CLIs, or games<br/>• Early-stage prototypes validating core domain logic"]
16
+ B3["3. The Tipping Point (Graduation)<br/>• Multi-tenant B2B SaaS where independent organizations share infrastructure<br/>• Strict legal, SOC 2, and regulatory mandates prohibiting cross-tenant data leakage"]
17
+ B1 -->|Forbidden if single-tenant| B2
18
+ B1 -->|Triggered by B2B SaaS requirements| B3
19
+ end
20
+ ```
21
+
22
+ ---
23
+
24
+ ## 2. Tenant Context Resolution
25
+
26
+ Tenant identity must be resolved at the edge/gateway from **cryptographically verified session context**, never from spoofable client input:
27
+
28
+ ```mermaid
29
+ flowchart LR
30
+ Req["Incoming Request"] --> Auth["Auth Middleware<br/>Extract Verified tenantId from JWT"]
31
+ Auth --> Ctx["AsyncLocalStorage / Context"]
32
+ Ctx --> DB["Database Connection<br/>SET LOCAL app.current_tenant_id"]
33
+ Ctx --> Audit["Audit / Event Log<br/>Tagged with tenantId"]
34
+ ```
35
+
36
+ ### Invariants:
37
+ 1. **Never Trust Raw Query/Body Parameters**: Never accept `?tenantId=...` or `{ tenantId: "..." }` on public mutations without validating that the authenticated session owns that tenant.
38
+ 2. **Ambient Context Propagation**: Bind the resolved `tenantId` to an ambient request context (e.g. `AsyncLocalStorage` in Node, `ThreadLocal` in Java, `context.Context` in Go) to prevent passing tenant IDs manually through every service layer.
39
+
40
+ ---
41
+
42
+ ## 3. The 4 Universal Data Isolation Models
43
+
44
+ Choose the isolation model matching your security classification and cost profile:
45
+
46
+ | Model | Isolation Mechanism | Operational Trade-off | Compliance Target |
47
+ |---|---|---|---|
48
+ | **1. Pooled with RLS** | Shared DB, shared schema; tables partitioned by `tenant_id` + Postgres RLS. | Lowest infrastructure cost, highest engineering rigor required. | Standard B2B SaaS, SOC 2 Type II. |
49
+ | **2. Silo Schema** | Shared DB, separate database schema per tenant (`tenant_acme.*`). | High isolation; complex schema migrations across hundreds of schemas. | Regulated SaaS, HIPAA, FinTech. |
50
+ | **3. Silo Database** | Separate physical or logical database instance per tenant. | Highest cost and isolation; zero cross-tenant blast radius. | Enterprise Dedicated, PCI-DSS Level 1. |
51
+ | **4. App-Level Interceptor** | Shared DB, ORM/query builder automatically appends `WHERE tenant_id = :id`. | Brittle; human error in ad-hoc raw SQL queries bypasses isolation. | Forbidden for high-security applications. |
52
+
53
+ ---
54
+
55
+ ## 4. PostgreSQL Row-Level Security (RLS) Invariants
56
+
57
+ When using **Model 1 (Pooled with RLS)**, enforce data isolation at the database engine level so that even a buggy or malicious application query cannot access another tenant's rows:
58
+
59
+ ### 1. Dual-Lock Table Setup
60
+ Every table containing tenant-scoped data must enable and force RLS:
61
+ ```sql
62
+ ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
63
+ ALTER TABLE orders FORCE ROW LEVEL SECURITY;
64
+ ```
65
+ *(The `FORCE` clause ensures that table owners and superusers are also bound by the policy).*
66
+
67
+ ### 2. Session Context Binding
68
+ The application connection pool must initialize the tenant session variable inside every transactional checkout:
69
+ ```sql
70
+ -- Executed inside transaction before running queries
71
+ SELECT set_config('app.current_tenant_id', :tenantId, true);
72
+ ```
73
+
74
+ ### 3. Declarative Tenant Isolation Policy
75
+ ```sql
76
+ CREATE POLICY tenant_isolation_policy ON orders
77
+ AS RESTRICTIVE
78
+ FOR ALL
79
+ TO application_user
80
+ USING (tenant_id = NULLIF(current_setting('app.current_tenant_id', true), '')::UUID)
81
+ WITH CHECK (tenant_id = NULLIF(current_setting('app.current_tenant_id', true), '')::UUID);
82
+ ```
83
+
84
+ ---
85
+
86
+ ## 5. Advanced Tenant Extensibility (YAGNI Gated)
87
+
88
+ ### 5.1. Dynamic Schemas (Runtime Custom Fields)
89
+ - **Tipping Point:** External enterprise tenants require self-service custom fields without engineering running relational DDL migrations.
90
+ - **Hybrid Storage Pattern:** Core relational columns for shared invariants + `custom_attributes JSONB` validated against **JSON Schema Draft 2020-12** stored per tenant.
91
+ - **Fail-Fast Schema Validation:** Custom field inputs must be validated against the tenant's compiled JSON schema before database persistence.
92
+
93
+ ### 5.2. Pluggable Tenant Logic (Sandboxed Scripting)
94
+ - **Tipping Point:** Enterprise tenants require custom business logic (tax calculation, approval routing) executed at runtime.
95
+ - **Zero Raw `eval()`**: Never execute tenant code via raw `eval()`, Python `exec()`, or NodeJS VM isolates.
96
+ - **Safe Sandboxing**:
97
+ - *Simple Expressions:* Use **Common Expression Language (CEL)** (Google) for safe, deterministic boolean and mathematical evaluation.
98
+ - *Complex Logic:* Compile tenant extension plugins to **WebAssembly (Wasm)** executed via Wasmer or Wasmtime with strict CPU time and memory quotas.