azcodr 1.3.0 → 1.5.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 (72) hide show
  1. package/.agents/hooks.json.example +42 -0
  2. package/.agents/mcp_config.json.example +24 -0
  3. package/.agents/scripts/safety_guard.sh +16 -0
  4. package/.agents/scripts/verify_completion.sh +13 -0
  5. package/.agents/skills/agentic-architect/SKILL.md +15 -8
  6. package/.agents/skills/agentic-architect/references/agents_md_template.md +6 -3
  7. package/.agents/skills/agentic-architect/references/skill_architecture_inquiry.md +1 -1
  8. package/.agents/skills/agentic-architect/references/skill_template.md +2 -1
  9. package/.agents/skills/agentic-architect/scripts/validate_agentic_configs.sh +189 -6
  10. package/.agents/skills/clean-code-refactor/SKILL.md +6 -6
  11. package/.agents/skills/compliance-audit/SKILL.md +1 -1
  12. package/.agents/skills/lets-build/SKILL.md +22 -7
  13. package/.agents/skills/lets-build/references/architecture_interview_matrix.md +8 -2
  14. package/.agents/skills/lets-build/references/hexagonal_bootstrap_scaffolds.md +53 -6
  15. package/.agents/skills/lets-build/references/project_readme_template.md +4 -4
  16. package/.agents/skills/lets-build/scripts/bootstrap_workspace.sh +181 -36
  17. package/.agents/skills/product-analyst/SKILL.md +13 -2
  18. package/.agents/skills/relentless-questioner/SKILL.md +13 -5
  19. package/.agents/skills/relentless-questioner/references/adaptive_question_trees.md +18 -0
  20. package/.gitignore +2 -0
  21. package/AGENTS.md +25 -40
  22. package/README.md +27 -40
  23. package/bin/azcodr.js +9 -4
  24. package/docs/rules/agentic_configuration.md +123 -32
  25. package/docs/rules/api_architecture.md +179 -0
  26. package/docs/rules/caching.md +30 -13
  27. package/docs/rules/cloud_native.md +10 -12
  28. package/docs/rules/cqrs.md +203 -0
  29. package/docs/rules/database_design.md +125 -0
  30. package/docs/rules/database_operations.md +56 -14
  31. package/docs/rules/design_patterns.md +18 -11
  32. package/docs/rules/devops_ci_cd.md +76 -0
  33. package/docs/rules/domain_driven_design.md +17 -13
  34. package/docs/rules/feature_flags.md +21 -4
  35. package/docs/rules/frontend_architecture.md +157 -0
  36. package/docs/rules/multitenancy_architecture.md +98 -0
  37. package/docs/rules/product_ownership.md +22 -27
  38. package/docs/rules/relentless_questioning.md +4 -0
  39. package/docs/rules/requirements_engineering.md +16 -14
  40. package/docs/rules/security_compliance.md +53 -0
  41. package/docs/rules/server_driven_ui.md +20 -3
  42. package/docs/rules/test_driven_development.md +119 -62
  43. package/docs/rules/type_safety.md +65 -0
  44. package/docs/rules/ui_ux_architecture.md +33 -30
  45. package/docs/rules/workflow_state_machines.md +20 -3
  46. package/lib/scaffold.js +117 -5
  47. package/memory.md +12 -131
  48. package/package.json +2 -2
  49. package/docs/rules/accessibility.md +0 -31
  50. package/docs/rules/advanced_api_patterns.md +0 -104
  51. package/docs/rules/api_versioning.md +0 -113
  52. package/docs/rules/application_security.md +0 -23
  53. package/docs/rules/architecture_decision_records.md +0 -42
  54. package/docs/rules/compliance.md +0 -25
  55. package/docs/rules/container_infrastructure.md +0 -32
  56. package/docs/rules/continuous_deployment.md +0 -24
  57. package/docs/rules/continuous_integration.md +0 -20
  58. package/docs/rules/continuous_learning.md +0 -29
  59. package/docs/rules/database_integrity.md +0 -80
  60. package/docs/rules/database_migrations.md +0 -41
  61. package/docs/rules/database_performance.md +0 -44
  62. package/docs/rules/database_transactions.md +0 -81
  63. package/docs/rules/devsecops.md +0 -33
  64. package/docs/rules/multitenancy_isolation.md +0 -88
  65. package/docs/rules/react.md +0 -78
  66. package/docs/rules/rest_api_conventions.md +0 -46
  67. package/docs/rules/tenant_dynamic_schemas.md +0 -88
  68. package/docs/rules/tenant_pluggable_logic.md +0 -59
  69. package/docs/rules/test_isolation.md +0 -26
  70. package/docs/rules/typescript.md +0 -55
  71. package/docs/rules/ui_navigation.md +0 -20
  72. package/docs/rules/workspace_isolation.md +0 -25
@@ -1,80 +0,0 @@
1
- # Database Integrity, Constraints & Defensive Design
2
-
3
- > **Core Mandate:** Enforce data integrity via explicit foreign key delete semantics, domain CHECK constraints, interval exclusion constraints, partial unique indexes for soft deletes, and Universal Total Audit accountability.
4
-
5
- ---
6
-
7
- ## 1. Foreign Key `ON DELETE` Semantics
8
-
9
- - **Default to `RESTRICT`**: For critical domain entities, tenant records, and financial ledgers to prevent accidental cascade destruction.
10
- - **Use `CASCADE` Strictly**: For direct, owned child records (e.g. `OrderItem` owned by `Order`).
11
- - **Use `SET NULL`**: When foreign relations are optional.
12
-
13
- ---
14
-
15
- ## 2. Domain CHECK Constraints & Interval Exclusion
16
-
17
- - **Domain Invariants**:
18
- ```sql
19
- ALTER TABLE "Invoice" ADD CONSTRAINT chk_invoice_positive_amount CHECK (amount >= 0);
20
- ALTER TABLE "Subscription" ADD CONSTRAINT chk_sub_dates CHECK (end_date >= start_date);
21
- ```
22
- - **Prevent Overlapping Reservations**:
23
- ```sql
24
- CREATE EXTENSION IF NOT EXISTS btree_gist;
25
- ALTER TABLE "RoomReservation" ADD CONSTRAINT no_overlapping_reservations
26
- EXCLUDE USING gist (room_id WITH =, reservation_period WITH &&);
27
- ```
28
-
29
- ---
30
-
31
- ## 3. Soft Delete Unique Constraint Trap
32
-
33
- A standard `UNIQUE(email)` constraint fails when an active user signs up with the email of a soft-deleted record.
34
- - **Mandatory Standard**: Always use partial unique indexes for soft-deleted tables:
35
- ```sql
36
- CREATE UNIQUE INDEX idx_users_email_active ON "User"(email) WHERE deleted_at IS NULL;
37
- ```
38
-
39
- ---
40
-
41
- ## 4. Relational Foreign Key Invariants & UI Mapping
42
-
43
- - **Mandatory Existence Validation:** The application and domain layers must defensively assert foreign key target existence prior to child entity persistence. If a referenced parent entity does not exist, return an RFC 7807 problem detail (`400 Bad Request` or `404 Not Found`).
44
- - **No Raw Identifier Text Inputs:** User interfaces must never expose raw string or UUID input fields for foreign key references. Associations must be selected via accessible dropdown selectors (`shadcn/ui` `<Select>`) displaying human-readable contextual metadata (names, labels, numbers, pricing).
45
- - **Complete Lifecycle CRUD:** All relational entities must provide complete CRUD functionality (Create, Read/Detail, Update/Transition, Delete/Archive) before being considered feature-complete.
46
-
47
- ---
48
-
49
- ## 5. Mandatory Universal Audit Columns
50
-
51
- Every stateful entity across all relational schemas, ORMs, and persistence layers must maintain strict audit accountability.
52
-
53
- ### The Canonical 6 Total Audit Fields:
54
- All mutable database tables, domain entities, and models must define the total audit suite:
55
- 1. **`createdAt` / `created_at`** (`TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP`): Immutable timestamp when the record was initially created.
56
- 2. **`createdBy` / `created_by`** (`VARCHAR/TEXT NOT NULL DEFAULT 'SYSTEM'`): The user ID (`User.id`) of the authenticated actor who created the record, or `'SYSTEM'` for automated background tasks, seeds, or system bootstrap.
57
- 3. **`updatedAt` / `updated_at`** (`TIMESTAMP WITH TIME ZONE NOT NULL`): Timestamp automatically updated on every record mutation.
58
- 4. **`updatedBy` / `updated_by`** (`VARCHAR/TEXT NOT NULL DEFAULT 'SYSTEM'`): The user ID (`User.id`) of the authenticated actor who performed the most recent mutation, or `'SYSTEM'` for automated workflows.
59
- 5. **`deletedAt` / `deleted_at`** (`TIMESTAMP WITH TIME ZONE NULL`): Timestamp when the record was soft-deleted/archived. Null for active records.
60
- 6. **`deletedBy` / `deleted_by`** (`VARCHAR/TEXT NULL`): The user ID (`User.id`) of the authenticated actor who performed or authorized deletion, or `'SYSTEM'`.
61
-
62
- All queries for active records MUST filter `WHERE deletedAt IS NULL` (or ORM equivalent). Paired with partial unique indexes `WHERE deleted_at IS NULL` where uniqueness constraints apply.
63
-
64
- ### Append-Only Immutable Ledgers / Log Streams:
65
- Pure financial ledgers (e.g. `PaymentLedgerEntry`, `JournalEntry`) and event outbox streams are strictly immutable. They require:
66
- - **`createdAt` / `created_at`** (`NOT NULL DEFAULT CURRENT_TIMESTAMP`)
67
- - **`createdBy` / `created_by`** (`NOT NULL DEFAULT 'SYSTEM'`)
68
- - *Mutations and soft-deletes are prohibited*: `updatedAt`, `updatedBy`, `deletedAt`, and `deletedBy` are omitted because records are append-only. Financial adjustments must be recorded as offsetting ledger entries.
69
-
70
- ---
71
-
72
- ## 6. Semi-Structured Evolution & Cryptographic Audit Trails
73
-
74
- - **Non-Destructive Schema Evolution via JSON**: For contractual covenants, dynamic conditions, or variable metadata subject to rapid domain iteration, employ semi-structured JSON fields (`termsJson`, `metadataJson`) validated against JSON Schema rather than premature table migrations.
75
- - **Cryptographic Electronic Signatures & Execution Auditing**: Legal agreements and execution records require defensible evidence beyond a boolean `isSigned` flag. All executed agreements must capture:
76
- 1. Typed signer legal name and designated role.
77
- 2. ISO 8601 UTC execution timestamp.
78
- 3. Authenticated actor ID (`userId`).
79
- 4. Client network IP address and User-Agent string.
80
- 5. Deterministic cryptographic checksum / hash of the executed terms.
@@ -1,41 +0,0 @@
1
- # Zero-Downtime Database Migrations (Expand-Contract)
2
-
3
- > **Core Mandate:** Enforce versioned declarative migrations, zero-downtime expand-contract schema evolutions, non-blocking concurrent index creation, and two-phase constraint validation.
4
-
5
- ---
6
-
7
- ## 1. Universal Versioned & Declarative Migrations
8
-
9
- - **Strict Version Control**: All database modifications must occur via versioned migration engines (**Atlas**, **Flyway**, **Liquibase**, or **Goose**).
10
- - **Prohibited Actions**: Strictly forbid unversioned schema-push commands or raw manual DDL in staging or production environments.
11
- - **Automated CI Validation**: CI pipelines must lint migrations for breaking changes, lock timeouts, and full-table scans before merging schema PRs.
12
-
13
- ---
14
-
15
- ## 2. Safe Column Additions & Deprecations (Expand-Contract)
16
-
17
- Never rename or drop a column in a single deployment step. Follow the 5-phase protocol:
18
- 1. **Phase 1 (Expand):** Add the new column as nullable or with a non-locking default.
19
- 2. **Phase 2 (Double-Write):** Deploy application version writing to both old and new columns; reads continue from the old column.
20
- 3. **Phase 3 (Backfill):** Run batched background jobs backfilling historical rows from the old column to the new column in bounded batches (e.g. 500–1000 rows).
21
- 4. **Phase 4 (Switch Read):** Deploy application reading and writing solely to the new column.
22
- 5. **Phase 5 (Contract):** In the subsequent release, drop the old column and legacy constraints from the database.
23
-
24
- ---
25
-
26
- ## 3. Concurrent Non-Blocking Indexing & Constraint Validation
27
-
28
- - **Concurrent Indexes**: Always construct indexes non-blockingly (`CREATE INDEX CONCURRENTLY` in PostgreSQL, `ALGORITHM=INPLACE, LOCK=NONE` in MySQL) to avoid locking read/write traffic:
29
- ```sql
30
- CREATE INDEX CONCURRENTLY idx_orders_customer_created
31
- ON orders (customer_id, created_at DESC);
32
- ```
33
- - **Two-Phase Constraints**: Attach foreign keys and check constraints without scanning historical rows upfront, then validate asynchronously:
34
- ```sql
35
- -- Step 1: Attach foreign key without blocking writes
36
- ALTER TABLE orders ADD CONSTRAINT fk_orders_tenant
37
- FOREIGN KEY (tenant_id) REFERENCES tenants(id) NOT VALID;
38
-
39
- -- Step 2: Validate constraint concurrently
40
- ALTER TABLE orders VALIDATE CONSTRAINT fk_orders_tenant;
41
- ```
@@ -1,44 +0,0 @@
1
- # Database Performance & N+1 Prevention
2
-
3
- > **Core Mandate:** Eliminate N+1 query bottlenecks via explicit relation batching, enforce strict composite indexing, size connection pools scientifically, and terminate runaway queries with statement timeouts.
4
-
5
- ---
6
-
7
- ## 1. N+1 Query Elimination
8
-
9
- - **Prohibit Iterative Queries in Loops**: Never query child collections inside iteration loops.
10
- ```
11
- ❌ FORBIDDEN:
12
- parents = query("SELECT id FROM parent_table")
13
- for p in parents:
14
- children = query("SELECT * FROM child_table WHERE parent_id = :id", p.id)
15
- ```
16
- - **Batching & Eager Fetching**: Always fetch related entities via single `JOIN` statements or batched `IN` clauses (`WHERE parent_id IN (...)`).
17
- ```
18
- ✅ CORRECT:
19
- parents = query("SELECT id FROM parent_table")
20
- children = query("SELECT * FROM child_table WHERE parent_id IN (:ids)", parents.map(id))
21
- ```
22
- - **Universal DataLoader Pattern**: For decentralized domain resolvers or GraphQL pipelines, employ language-native DataLoader ports to batch and deduplicate entity lookups within an execution cycle.
23
-
24
- ---
25
-
26
- ## 2. Multi-Tenant Indexing Strategy
27
-
28
- - **Tenant-Leading Composite Indexes**:
29
- Every multi-tenant query pattern must be backed by a composite index where `tenant_id` is the primary leading column:
30
- ```sql
31
- CREATE INDEX idx_orders_tenant_created ON orders (tenant_id, created_at DESC);
32
- CREATE UNIQUE INDEX uq_orders_tenant_number ON orders (tenant_id, order_number);
33
- ```
34
- - **Covering Indexes**:
35
- Include frequently projected columns in index definitions (`INCLUDE (status, total_amount)` in engines that support index-only scans) to avoid secondary table lookups.
36
-
37
- ---
38
-
39
- ## 3. Connection Pooling & Statement Timeouts
40
-
41
- - **Scientific Pool Sizing Formula**:
42
- $$\text{max\_connections} = (\text{CPU Cores} \times 2) + \text{Effective Disk / Spindle Count}$$
43
- - **Transaction-Scoped Pooling**: Use lightweight connection poolers (e.g. PgBouncer, ProxySQL, or HikariCP) in transaction pooling mode to support thousands of concurrent client connections without memory exhaustion.
44
- - **Defensive Statement Timeout**: Enforce strict statement timeouts (e.g. 5 seconds) at the connection pool or gateway layer to terminate unindexed runaway queries before they degrade the cluster.
@@ -1,81 +0,0 @@
1
- # Database Transactions, ACID Atomicity & Outbox Pattern
2
-
3
- > **Core Mandate:** Enforce full ACID transactional atomicity, appropriate isolation levels, defensive timeouts, deadlock prevention, and eliminate the dual-write problem via the Transactional Outbox pattern.
4
-
5
- ---
6
-
7
- ## 1. ANSI SQL Transaction Isolation Levels
8
-
9
- 1. **`Read Committed` (Default):** Guarantees statements see only committed data (eliminates dirty reads). Suitable for standard CRUD operations.
10
- 2. **`Repeatable Read` (Snapshot Isolation):** All operations within the transaction see the exact same database snapshot taken at transaction start. Mandatory for multi-entity financial calculations, ledger balance transfers, and inventory decrement operations.
11
- 3. **`Serializable`:** Strict serializability. Prevents phantom reads and write skew. Mandatory for complex booking and seat allocation operations. Requires application-level retry loops with jittered exponential backoff to handle serialization failures.
12
-
13
- ---
14
-
15
- ## 2. Defensive Timeouts & Deadlock Prevention
16
-
17
- Prevent hung transactions or lock waits from starving database connection pools across any engine:
18
-
19
- ```sql
20
- SET lock_timeout = '3s'; -- Abort if lock cannot be acquired within 3s
21
- SET statement_timeout = '10s'; -- Abort queries running longer than 10s
22
- SET idle_in_transaction_session_timeout = '30s'; -- Abort hung transactions idle for > 30s
23
- ```
24
-
25
- ### Deterministic Lock Ordering
26
- Always acquire locks on entities in a globally consistent order across application services (e.g. sort resource IDs lexicographically before issuing `SELECT ... FOR UPDATE`) to prevent circular wait deadlocks.
27
-
28
- ---
29
-
30
- ## 3. Abstract Unit of Work & Transaction Boundaries
31
-
32
- Application services must control transaction boundaries via an abstract **Unit of Work** port, keeping domain logic decoupled from concrete ORMs:
33
-
34
- ```
35
- ┌────────────────────────────────────────────────────────┐
36
- │ Unit of Work Port Contract (Agnostic Specification) │
37
- ├────────────────────────────────────────────────────────┤
38
- │ executeTransaction(options, transactionCallback): │
39
- │ options: │
40
- │ isolationLevel: READ_COMMITTED | REPEATABLE_READ │
41
- │ timeoutMs: integer (default 10000) │
42
- │ maxWaitMs: integer (default 5000) │
43
- │ behavior: │
44
- │ 1. Begin transaction on scoped connection │
45
- │ 2. Execute callback with transactional context │
46
- │ 3. On error: Rollback and propagate domain error │
47
- │ 4. On success: Commit atomically │
48
- └────────────────────────────────────────────────────────┘
49
- ```
50
-
51
- ---
52
-
53
- ## 4. Eliminating Dual-Writes: Transactional Outbox Pattern
54
-
55
- Never write to the database and publish to a message broker sequentially. Persist the domain mutation and the event record atomically within the same database transaction:
56
-
57
- ```sql
58
- CREATE TABLE outbox_events (
59
- id VARCHAR(64) PRIMARY KEY,
60
- tenant_id VARCHAR(64) NOT NULL,
61
- aggregate_type VARCHAR(64) NOT NULL,
62
- aggregate_id VARCHAR(64) NOT NULL,
63
- event_type VARCHAR(128) NOT NULL,
64
- payload TEXT NOT NULL,
65
- status VARCHAR(32) NOT NULL DEFAULT 'PENDING',
66
- created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP
67
- );
68
-
69
- CREATE INDEX idx_outbox_pending ON outbox_events(status, created_at);
70
- ```
71
-
72
- ### Asynchronous Outbox Relaying
73
- - **Change Data Capture (CDC)**: Stream transaction logs directly to Kafka/NATS using tools like **Debezium**.
74
- - **Polling Worker**: Run background workers executing non-blocking polling:
75
- ```sql
76
- SELECT * FROM outbox_events
77
- WHERE status = 'PENDING'
78
- ORDER BY created_at ASC
79
- LIMIT 100
80
- FOR UPDATE SKIP LOCKED;
81
- ```
@@ -1,33 +0,0 @@
1
- # DevSecOps, Secret Scanning & SBOM Standards
2
-
3
- > **Core Mandate:** Enforce automated pre-commit secret gating, CycloneDX SBOM generation, polyglot SAST via Semgrep, and container/lockfile scanning with Trivy.
4
-
5
- ---
6
-
7
- ## 1. Automated Pre-Commit Secret Gating
8
-
9
- - Run open-source secret scanning (**`gitleaks`** or **`secretlint`**) on every staged commit via pre-commit hooks.
10
- - Never bypass git commit hooks (`--no-verify`). Strictly forbid committing credentials, private keys, certificates, or API tokens to version control.
11
-
12
- ---
13
-
14
- ## 2. Software Bill of Materials (SBOM) Generation
15
-
16
- - Generate reproducible **CycloneDX 1.6** or **SPDX** SBOMs for all build artifacts using open-source **`syft`**:
17
- ```bash
18
- syft dir:. -o cyclonedx-json=sbom.json
19
- ```
20
- - Archive the generated `sbom.json` alongside release binaries and container registries.
21
- - Sign release artifacts and container images cryptographically using **Cosign** (Sigstore) with SLSA provenance attestation.
22
-
23
- ---
24
-
25
- ## 3. Polyglot SAST & Vulnerability Scanning
26
-
27
- - **Static Analysis (SAST)**: Standardize on **Semgrep** for cross-language security and quality linting across Go, Rust, Python, Java, and TypeScript.
28
- - **Dependency & Container CVE Scanning**: Scan lockfiles (`go.mod`, `Cargo.lock`, `package-lock.json`, `poetry.lock`, `pom.xml`) and OCI container base images using open-source **`trivy`** and **`grype`**:
29
- ```bash
30
- trivy fs --severity HIGH,CRITICAL .
31
- grype sbom:sbom.json
32
- ```
33
- - Any unpatched `HIGH` or `CRITICAL` Common Vulnerabilities and Exposures (CVE) halts the continuous integration pipeline immediately.
@@ -1,88 +0,0 @@
1
- # Multi-Tenancy Context Resolution & Data Isolation Models
2
-
3
- > **Core Mandate:** Enforce multi-tenancy isolation through dynamic context resolution combined with database-agnostic isolation models (AST query interceptors, RLS, schema namespaces, or connection routing) as an immutable backstop.
4
-
5
- ---
6
-
7
- ## 1. Multi-Tenant Context Resolution
8
-
9
- Resolve tenant identity dynamically in an inbound gateway or middleware pipeline in strict priority order:
10
- 1. **Host Subdomain**: `subdomain.app.com` (extracted via hostname regex).
11
- 2. **Explicit Headers**: `X-Tenant-ID: <uuid>` or `X-Tenant-Slug: <slug>`.
12
- 3. **Path Prefix**: `/t/:tenantSlug/...`.
13
- 4. **JWT Claim Fallback**: Authenticated token `tid` (tenant ID) claim.
14
-
15
- *Validation:* If the resolved tenant does not exist or is in `SUSPENDED` status, immediately return **`403 Forbidden`** (`TENANT_SUSPENDED` or `TENANT_INVALID`). Propagate `TenantContext` across service calls using standard W3C Baggage headers or request contexts.
16
-
17
- - **Fail-Closed Multi-Tenancy Invariant**: Never trust client-supplied tenant headers (`X-Tenant-ID`) without cryptographically verifying that the authenticated session actor actually belongs to the requested tenant organization/workspace. Mismatched tenant headers must immediately fail closed with HTTP 403 `FORBIDDEN_TENANT_ACCESS`.
18
-
19
- ---
20
-
21
- ## 2. Four Universal Data Isolation Models
22
-
23
- Never rely solely on application developers remembering to manually append `WHERE tenant_id = ?`. Standardize on one of four architectural isolation strategies:
24
-
25
- ```mermaid
26
- flowchart TD
27
- Request["Inbound Request (TenantContext)"] --> Strategy{"Isolation Strategy"}
28
-
29
- Strategy -->|"Model 1: Discriminator AST"| AST["Query Interceptor / AST Rewriter\n(Automatically injects tenant_id into AST before DB execution)"]
30
- Strategy -->|"Model 2: Engine RLS"| RLS["Row-Level Security (RLS)\n(Database session config: current_setting / session variable)"]
31
- Strategy -->|"Model 3: Schema Namespace"| Schema["Schema-per-Tenant\n(SET search_path / USE tenant_schema)"]
32
- Strategy -->|"Model 4: Instance Routing"| Pool["Database-per-Tenant\n(Connection pool router per tenant ID)"]
33
-
34
- AST --> Database[(Any Relational / Document DB)]
35
- RLS --> Database
36
- Schema --> Database
37
- Pool --> Database
38
- ```
39
-
40
- ### Model 1: Universal AST Query Interceptor (Engine-Agnostic)
41
- The persistence layer interceptor parses the query Abstract Syntax Tree (AST) at runtime and automatically enforces `tenant_id = current_tenant` for all reads and mutations. Compatible with all ANSI SQL and NoSQL engines.
42
-
43
- ### Model 2: Database Row-Level Security (RLS)
44
- For engines supporting native RLS (e.g. PostgreSQL, Oracle):
45
- ```sql
46
- ALTER TABLE "Order" ENABLE ROW LEVEL SECURITY;
47
- ALTER TABLE "Order" FORCE ROW LEVEL SECURITY;
48
-
49
- CREATE POLICY order_tenant_isolation ON "Order"
50
- FOR ALL
51
- USING (tenant_id = current_setting('app.tenant_id', true)::uuid)
52
- WITH CHECK (tenant_id = current_setting('app.tenant_id', true)::uuid);
53
- ```
54
- > [!IMPORTANT]
55
- > **Connection Pool Safety:** Always set `is_local = true` when configuring session variables (`set_config('app.tenant_id', id, true)`). This restricts settings strictly to the current database transaction, preventing cross-tenant leakage in connection pools.
56
-
57
- ### Model 3: Schema-per-Tenant
58
- Separate schemas per tenant within a shared database instance (`tenant_acme`, `tenant_globex`). Routing dynamically sets the active search path per transaction.
59
-
60
- ### Model 4: Database-per-Tenant
61
- Dedicated physical database instances per enterprise tenant, selected by a dynamic connection pool resolver based on resolved tenant metadata.
62
-
63
- ---
64
-
65
- ## 3. Polyglot Adapter Interceptor Contract
66
-
67
- Adapters in any language (Go, Rust, Python, Java, TypeScript) must expose an interceptor wrapping the data access layer:
68
-
69
- ```
70
- ┌────────────────────────────────────────────────────────┐
71
- │ Context Interceptor Contract (Pseudocode / Polyglot) │
72
- ├────────────────────────────────────────────────────────┤
73
- │ onQueryExecution(query, tenantContext): │
74
- │ assert(tenantContext != null, "MissingTenantContext")│
75
- │ if adapter.supportsRLS(): │
76
- │ execute("SET LOCAL app.tenant_id = :tenantId") │
77
- │ else if adapter.supportsAST(): │
78
- │ query.addPredicate(EQUALS("tenant_id", tenantId)) │
79
- │ return execute(query) │
80
- └────────────────────────────────────────────────────────┘
81
- ```
82
-
83
- ---
84
-
85
- ## 4. Tenant Lifecycle Management
86
-
87
- - **Atomic Provisioning**: Tenant creation must run inside an atomic transaction (provision tenant record, seed default RBAC roles `ADMIN`/`MEMBER`, assign subscription tier).
88
- - **GDPR Cascading Deletion**: Deleting a tenant triggers an asynchronous job that cascade purges or pseudonymizes all tenant records, ensuring zero orphaned data.
@@ -1,78 +0,0 @@
1
- # React & Modern Frontend Architecture
2
-
3
- > **Core Mandate:** Enforce modern, production-grade React standards across all web interfaces: `shadcn/ui` with Radix UI primitives, TanStack Query for server-state caching, React Hook Form / TanStack Form with Zod validation, and zero ad-hoc `useState` forms or raw `useEffect` fetch loops.
4
-
5
- ---
6
-
7
- ## 1. Component Library & Styling (`shadcn/ui` + Radix UI)
8
-
9
- - **Accessible Radix Primitives**: All interactive UI components (dialogs, dropdowns, selects, tabs, tooltips, popovers) must be built on `@radix-ui` headless primitives or `shadcn/ui` components located in `@/components/ui/`.
10
- - **Zero Unstyled Raw Elements**: Never create unstyled raw HTML modals, dropdowns, or custom select tags.
11
- - **Tailwind Utility Styling (`cn` helper)**: Combine Tailwind utility classes using `clsx` and `tailwind-merge` (`cn(...)`) to allow clean prop overrides and consistent theming.
12
- - **Strict Prohibition of Native Dialogs**: As mandated in [`docs/rules/accessibility.md`](./accessibility.md), `window.alert()` and `window.confirm()` are strictly forbidden. Use accessible Radix UI dialogs (`<ConfirmDialog />`).
13
-
14
- ---
15
-
16
- ## 2. Server State & Data Fetching (TanStack Query)
17
-
18
- - **Mandatory TanStack Query**: All asynchronous data fetching, caching, and mutation must use **TanStack Query (`@tanstack/react-query`)**.
19
- - **No Raw `useEffect` Fetch Loops**:
20
- - *Anti-Pattern:* `useEffect(() => { fetch(...).then(setData) }, [])` with manual `loading` and `error` state.
21
- - *Standard Pattern:*
22
- ```tsx
23
- const { data: resources, isLoading, error } = useQuery({
24
- queryKey: ['resources', tenantId],
25
- queryFn: () => api.getResources(),
26
- });
27
- ```
28
- - **Declarative Mutations & Invalidation**:
29
- - Mutations must define `useMutation` with `onSuccess` cache invalidation:
30
- ```tsx
31
- const queryClient = useQueryClient();
32
- const createResourceMutation = useMutation({
33
- mutationFn: (newResource: CreateResourceInput) => api.createResource(newResource),
34
- onSuccess: () => {
35
- queryClient.invalidateQueries({ queryKey: ['resources'] });
36
- },
37
- });
38
- ```
39
- - **Query Key Conventions**: Format query keys hierarchically as tuples: `['entity', id, ...filters]`, e.g., `['orders', orderId]`, `['users', tenantId]`.
40
-
41
- ---
42
-
43
- ## 3. Form State Management & Validation (Zod + Form Engines)
44
-
45
- - **Mandatory Schema Validation**: Every form submission must be validated against a formal **Zod schema** (`z.object({ ... })`) that mirrors the shared DTO/input contracts from shared packages.
46
- - **Form State Engines**: Use **React Hook Form (`react-hook-form` + `@hookform/resolvers/zod`)** or **TanStack Form (`@tanstack/react-form`)**.
47
- - **Zero Unvalidated `useState` Multi-Field Objects**:
48
- - *Anti-Pattern:*
49
- ```tsx
50
- const [form, setForm] = useState({ name: '', email: '' });
51
- // manual validation in submit handler...
52
- ```
53
- - *Standard Pattern:*
54
- ```tsx
55
- const form = useForm<CreateUserInput>({
56
- resolver: zodResolver(createUserSchema),
57
- defaultValues: { name: '', email: '' },
58
- });
59
- ```
60
- - **Accessible Error Linking**: Form inputs must bind validation errors to `aria-invalid="true"` and `aria-describedby="<field>-error"`.
61
-
62
- ---
63
-
64
- ## 4. State Separation & Data Tables
65
-
66
- - **State Hierarchy**:
67
- 1. **Server State (Remote)**: Manage exclusively with **TanStack Query**.
68
- 2. **URL State (Search / Pagination / Filters)**: Manage in URL search params per [`docs/rules/ui_navigation.md`](./ui_navigation.md).
69
- 3. **Form State (Transient Edits)**: Manage via **React Hook Form / TanStack Form**.
70
- 4. **Global Client State (Session/UI)**: Manage via **Zustand** (or React Context for theme/auth).
71
- - **Data Grids & Tables**: When building sortable, paginated, or virtualized tables, standardize on **TanStack Table (`@tanstack/react-table`)**.
72
-
73
- ---
74
-
75
- ## 5. Theme Architecture & Design Token Completeness
76
-
77
- - **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.
78
- - **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,46 +0,0 @@
1
- # REST API Design & Response Conventions
2
-
3
- > **Core Mandate:** Enforce standardized RESTful conventions, proper HTTP status codes, enumeration masking, and consistent subresource routing.
4
-
5
- ---
6
-
7
- ## 1. HTTP Status Code Conventions
8
-
9
- - **`200 OK`**: Successful GET, PUT, or PATCH requests returning modified state.
10
- - **`201 Created`**: Successful resource creation via POST (must include `Location` header or created entity).
11
- - **`204 No Content`**: Successful DELETE operations or operations returning no body.
12
- - **`400 Bad Request`**: Malformed payload or validation schema failure.
13
- - **`401 Unauthorized`**: Missing, expired, or invalid authentication credentials.
14
- - **`403 Forbidden`**: Authenticated caller lacks permissions, tenant is suspended, or action targets protected system roles.
15
- - **`404 Not Found`**: Resource does not exist or belongs to another tenant (enumeration masking).
16
- - **`409 Conflict`**: Unique constraint collision or concurrent optimistic lock conflict.
17
- - **`422 Unprocessable Entity`**: Semantic domain violation.
18
- - **`429 Too Many Requests`**: Rate limit exceeded.
19
- - **`500 Internal Server Error`**: Unexpected server error.
20
-
21
- ---
22
-
23
- ## 2. Cross-Tenant Enumeration Masking
24
-
25
- - If an authenticated user attempts to access a resource ID belonging to a different tenant, the API must return **`404 Not Found`** (rather than `403 Forbidden`) to prevent leaking the existence of other tenants' records.
26
-
27
- ---
28
-
29
- ## 3. Subresource Endpoints & Pluralization
30
-
31
- - Always use pluralized nouns for resources (e.g. `/api/v1/users`, `/api/v1/orders`).
32
- - Use nested subresources for closely owned relations:
33
- - `/api/v1/roles/:id/permissions`
34
- - `/api/v1/tenants/:id/members`
35
-
36
- ---
37
-
38
- ## 4. Full Lifecycle Resource CRUD & Route Tolerances
39
-
40
- - **Full Lifecycle Support:** All primary resource endpoints must provide comprehensive CRUD capabilities before completion:
41
- - `GET /api/v1/<resources>`: List with pagination and tenant filtering.
42
- - `GET /api/v1/<resources>/:id`: Detailed record by ID.
43
- - `POST /api/v1/<resources>`: Create new entity returning `201 Created`.
44
- - `PUT /api/v1/<resources>/:id` or `PATCH`: Update attributes or mutate state machine status.
45
- - `DELETE /api/v1/<resources>/:id`: Remove or archive returning `204 No Content`.
46
- - **Defensive Route Tolerances for Infrastructure Probes:** Operational probes (`/healthz`, `/readyz`) must defensively support trailing slashes (`/healthz/`) and common typos (`/healtz/`) to prevent reverse proxy routing mismatches between frontend dev servers (e.g. Vite) and ingress gateways.
@@ -1,88 +0,0 @@
1
- # Multi-Tenant Schema Extensibility & Virtual Entities
2
-
3
- > **Core Mandate:** Enforce dynamic schema extensibility via hybrid relational columns and validated JSON Schema (Draft 2020-12), prohibiting sparse nullable columns and branch-specific migrations in shared databases.
4
-
5
- ---
6
-
7
- ## 1. Hybrid Core + JSON/Document Extensibility
8
-
9
- Store universal relational attributes in standard typed columns. Store tenant-specific custom fields in a semi-structured `custom_attributes` column governed by tenant-scoped JSON Schemas:
10
-
11
- ```sql
12
- CREATE TABLE customers (
13
- id VARCHAR(64) PRIMARY KEY,
14
- tenant_id VARCHAR(64) NOT NULL,
15
- first_name VARCHAR(100) NOT NULL,
16
- last_name VARCHAR(100) NOT NULL,
17
- email VARCHAR(255) NOT NULL,
18
- custom_attributes TEXT NOT NULL DEFAULT '{}',
19
- created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP
20
- );
21
-
22
- CREATE TABLE tenant_schema_definitions (
23
- id VARCHAR(64) PRIMARY KEY,
24
- tenant_id VARCHAR(64) NOT NULL,
25
- entity_name VARCHAR(50) NOT NULL,
26
- json_schema TEXT NOT NULL,
27
- version INT NOT NULL DEFAULT 1,
28
- UNIQUE(tenant_id, entity_name)
29
- );
30
- ```
31
-
32
- ### Runtime Validation Contract (JSON Schema Draft 2020-12)
33
- Validate all inbound custom attribute payloads at runtime against the tenant's compiled JSON Schema before persisting mutations:
34
-
35
- ```
36
- ┌────────────────────────────────────────────────────────┐
37
- │ Dynamic Schema Validator Contract (Agnostic) │
38
- ├────────────────────────────────────────────────────────┤
39
- │ validateCustomAttributes(schemaDef, data): │
40
- │ compiledValidator = compileJsonSchema(schemaDef) │
41
- │ result = compiledValidator.validate(data) │
42
- │ if !result.isValid: │
43
- │ return Failure(ValidationError(result.errors)) │
44
- │ return Success(data) │
45
- └────────────────────────────────────────────────────────┘
46
- ```
47
- Supported natively by open-source engines in every major language (`valico` in Rust, `gojsonschema` in Go, `jsonschema` in Python, `networknt` in Java, `ajv` in Node).
48
-
49
- ---
50
-
51
- ## 2. Meta-Schema Catalog for Virtual Custom Entities
52
-
53
- When tenants define completely custom entities/tables dynamically without deploying code:
54
-
55
- ```sql
56
- CREATE TABLE tenant_entities (
57
- id VARCHAR(64) PRIMARY KEY,
58
- tenant_id VARCHAR(64) NOT NULL,
59
- name VARCHAR(64) NOT NULL,
60
- display_name VARCHAR(128) NOT NULL,
61
- schema_definition TEXT NOT NULL,
62
- UNIQUE(tenant_id, name)
63
- );
64
-
65
- CREATE TABLE tenant_records (
66
- id VARCHAR(64) PRIMARY KEY,
67
- tenant_id VARCHAR(64) NOT NULL,
68
- entity_id VARCHAR(64) NOT NULL REFERENCES tenant_entities(id) ON DELETE CASCADE,
69
- data TEXT NOT NULL DEFAULT '{}',
70
- created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP
71
- );
72
- ```
73
-
74
- ---
75
-
76
- ## 3. Indexing Strategies for Dynamic Custom Attributes
77
-
78
- 1. **Virtual / Generated Columns**: For high-throughput queried fields inside dynamic attributes, project them into virtual/generated columns and attach standard B-tree indexes:
79
- ```sql
80
- ALTER TABLE customers ADD COLUMN vat_number VARCHAR(64)
81
- GENERATED ALWAYS AS (custom_attributes->>'vat_number') STORED;
82
- CREATE INDEX idx_customers_vat ON customers (tenant_id, vat_number);
83
- ```
84
- 2. **Functional / Expression Indexes**: Index specific nested attributes directly on engines that support expression indexes:
85
- ```sql
86
- CREATE INDEX idx_customers_po ON customers (tenant_id, ((custom_attributes->>'po_number')::text));
87
- ```
88
- 3. **Inverted Indexes**: Use generalized inverted indexing (e.g. GIN in PostgreSQL) for arbitrary key-value path searches.
@@ -1,59 +0,0 @@
1
- # Pluggable Multi-Tenant Business Logic & Workflows
2
-
3
- > **Core Mandate:** Eliminate `if-tenant` conditional branching via Strategy registries, Common Expression Language (CEL), durable workflow orchestration, and secure WebAssembly (Wasm) micro-sandboxes.
4
-
5
- ---
6
-
7
- ## 1. Strategy Pattern & Dynamic Strategy Registry
8
-
9
- Encapsulate diverging tenant algorithms into discrete strategies conforming to a unified domain port:
10
-
11
- ```
12
- ┌────────────────────────────────────────────────────────┐
13
- │ Discount Strategy Port Contract │
14
- ├────────────────────────────────────────────────────────┤
15
- │ calculateDiscount(order): Decimal │
16
- └────────────────────────────────────────────────────────┘
17
- ```
18
-
19
- The application maintains an in-memory Strategy Registry resolving the active strategy based on `tenant.subscriptionTier` or custom tenant config:
20
-
21
- ```
22
- StrategyRegistry.register("standard", StandardDiscountStrategy)
23
- StrategyRegistry.register("enterprise_vip", HighVolumeTierStrategy)
24
-
25
- strategy = StrategyRegistry.resolve(tenant.discountStrategyKey)
26
- discount = strategy.calculateDiscount(order)
27
- ```
28
-
29
- ---
30
-
31
- ## 2. Declarative Rule Evaluation: Common Expression Language (CEL)
32
-
33
- Allow tenants or administrators to configure dynamic conditional logic stored as declarative text or JSON without redeploying binaries. Standardize on **Common Expression Language (CEL)**:
34
-
35
- ```cel
36
- // Example Tenant Rule Expression:
37
- order.total >= 500 && order.shipping_country == "US" && tenant.tier == "ENTERPRISE"
38
- ```
39
-
40
- - **Memory-Safe & Non-Turing Complete**: Prevents infinite loops, recursion crashes, and side-effects.
41
- - **Polyglot Portability**: Native compilers and runtimes available across Go (`cel-go`), Rust (`cel-rust`), Python (`cel-python`), Java (`cel-java`), and TypeScript (`cel-js`).
42
-
43
- ---
44
-
45
- ## 3. Durable Workflows & Orchestration (Temporal / BPMN 2.0)
46
-
47
- For tenants with diverging multi-step approval, fulfillment, or refund lifecycles:
48
- - **Durable Execution Engines**: Standardize on **Temporal.io** or **Camunda 8 / Zeebe (BPMN 2.0)**.
49
- - **Resilience Guarantees**: Workflows automatically persist state across node crashes, manage timeouts, execute automatic retries, and trigger compensation transactions (Saga pattern) across polyglot workers.
50
- - **Tenant Workflow Selection**: The domain routes entity state transitions to tenant-specific workflow IDs configured in database metadata.
51
-
52
- ---
53
-
54
- ## 4. Secure Script Sandboxing: WebAssembly (Wasm / Extism)
55
-
56
- Never execute untrusted tenant strings via host runtime evaluation (`eval()`, dynamic reflection, or unshielded isolates).
57
- - **Universal Sandboxing with Extism / Wasmtime**: Tenants compile custom logic (in Rust, Go, Python, or TypeScript) to portable `.wasm` bytecode.
58
- - **Strict Execution Quotas**: Max 50ms CPU execution budget, max 16MB linear memory boundary.
59
- - **Complete Host Isolation**: Sandboxed instances possess zero access to host filesystem, network sockets, environment variables, or database connections unless explicitly passed via memory interfaces.