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.
- package/.agents/hooks.json +42 -42
- package/.agents/hooks.json.example +42 -42
- package/.agents/mcp_config.json.example +29 -29
- package/.agents/scripts/safety_guard.sh +143 -34
- package/.agents/scripts/verify_completion.sh +90 -27
- package/.agents/skills/agentic-architect/SKILL.md +125 -125
- package/.agents/skills/agentic-architect/references/agents_md_template.md +62 -62
- package/.agents/skills/agentic-architect/references/refinement_workflow.md +32 -32
- package/.agents/skills/agentic-architect/references/skill_architecture_inquiry.md +63 -63
- package/.agents/skills/agentic-architect/references/skill_template.md +56 -56
- package/.agents/skills/agentic-architect/scripts/validate_agentic_configs.sh +402 -402
- package/.agents/skills/clean-code-refactor/SKILL.md +91 -91
- package/.agents/skills/clean-code-refactor/references/clean_code_smells.md +27 -27
- package/.agents/skills/clean-code-refactor/references/design_patterns_ts.md +65 -65
- package/.agents/skills/compliance-audit/SKILL.md +120 -120
- package/.agents/skills/compliance-audit/references/owasp_top10_controls.md +16 -16
- package/.agents/skills/compliance-audit/references/soc2_iso_controls.md +28 -28
- package/.agents/skills/lets-build/SKILL.md +173 -173
- package/.agents/skills/lets-build/references/architecture_interview_matrix.md +115 -115
- package/.agents/skills/lets-build/references/hexagonal_bootstrap_scaffolds.md +160 -160
- package/.agents/skills/lets-build/references/project_readme_template.md +79 -79
- package/.agents/skills/lets-build/scripts/bootstrap_workspace.sh +419 -255
- package/.agents/skills/product-analyst/SKILL.md +154 -154
- package/.agents/skills/product-analyst/references/backlog_ordering_techniques.md +107 -107
- package/.agents/skills/product-analyst/references/gherkin_patterns.md +46 -46
- package/.agents/skills/product-analyst/references/invest_checklist.md +38 -38
- package/.agents/skills/product-analyst/references/okr_alignment_guide.md +76 -76
- package/.agents/skills/product-analyst/references/smart_tasks.md +59 -59
- package/.agents/skills/relentless-questioner/SKILL.md +128 -128
- package/.agents/skills/relentless-questioner/references/adaptive_question_trees.md +102 -102
- package/.editorconfig +19 -19
- package/.github/workflows/ci.yml +167 -78
- package/.github/workflows/publish.yml +200 -0
- package/.gitignore +40 -25
- package/AGENTS.md +103 -102
- package/LICENSE +21 -21
- package/README.md +168 -165
- package/bin/azcodr.js +14 -228
- package/docs/knowledge/ubiquitous_language.md +31 -18
- package/docs/rules/agentic_configuration.md +259 -259
- package/docs/rules/api_architecture.md +179 -179
- package/docs/rules/authentication.md +76 -76
- package/docs/rules/authorization.md +75 -75
- package/docs/rules/caching.md +69 -69
- package/docs/rules/clean_code.md +62 -62
- package/docs/rules/cloud_native.md +41 -41
- package/docs/rules/cqrs.md +203 -203
- package/docs/rules/database_design.md +125 -125
- package/docs/rules/database_operations.md +69 -69
- package/docs/rules/design_patterns.md +98 -98
- package/docs/rules/devops_ci_cd.md +76 -76
- package/docs/rules/domain_driven_design.md +122 -122
- package/docs/rules/error_handling.md +54 -52
- package/docs/rules/feature_flags.md +59 -59
- package/docs/rules/frontend_architecture.md +157 -157
- package/docs/rules/multitenancy_architecture.md +98 -98
- package/docs/rules/product_ownership.md +127 -127
- package/docs/rules/project_management.md +49 -49
- package/docs/rules/relentless_questioning.md +52 -52
- package/docs/rules/requirements_engineering.md +98 -98
- package/docs/rules/security_compliance.md +53 -53
- package/docs/rules/server_driven_ui.md +88 -88
- package/docs/rules/test_driven_development.md +185 -185
- package/docs/rules/transactional_email.md +27 -27
- package/docs/rules/type_safety.md +65 -65
- package/docs/rules/ui_ux_architecture.md +150 -150
- package/docs/rules/workflow_state_machines.md +117 -117
- package/lib/cli-parse.js +51 -0
- package/lib/cli-target.js +109 -0
- package/lib/cli.js +180 -0
- package/lib/errors.js +28 -0
- package/lib/git.js +29 -0
- package/lib/guards.js +96 -0
- package/lib/index.d.ts +199 -134
- package/lib/index.js +5 -5
- package/lib/links.js +123 -0
- package/lib/permissions.js +44 -0
- package/lib/repo.js +90 -0
- package/lib/scaffold.js +238 -448
- package/memory.md +119 -36
- package/package.json +65 -62
- package/scripts/test_coverage.js +66 -38
- package/scripts/validate/adr.js +151 -0
- package/scripts/validate/io.js +84 -0
- package/scripts/validate/links.js +167 -0
- package/scripts/validate/parity.js +124 -0
- package/scripts/validate/root.js +184 -0
- package/scripts/validate/rules.js +44 -0
- package/scripts/validate/skills.js +96 -0
- package/scripts/validate/text.js +29 -0
- package/scripts/validate-cli.js +13 -0
- package/scripts/validate.js +140 -258
- package/.github/copilot-instructions.md +0 -1
|
@@ -1,76 +1,76 @@
|
|
|
1
|
-
# DevOps, CI/CD, Container Infrastructure & DevSecOps
|
|
2
|
-
|
|
3
|
-
> **Core Mandate:** Enforce trunk-based continuous integration with shift-left automated gates, minimal distroless OCI container packaging, non-root execution security, software supply chain verification (SBOM & Trivy), and zero-downtime continuous deployment.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 1. Continuous Integration & Trunk-Based Development
|
|
8
|
-
|
|
9
|
-
CI pipelines must execute fast, deterministic, shift-left quality gates on every commit and pull request:
|
|
10
|
-
|
|
11
|
-
```
|
|
12
|
-
[Local Commit] ──► [Pre-Commit Hook] ──► [Pull Request] ──► [Automated CI Gate] ──► [Merge to Main]
|
|
13
|
-
• Secretlint • Build Cache • Lint & Format Check
|
|
14
|
-
• Type Check • 100.00% Test Coverage
|
|
15
|
-
• DevSecOps CVE Scan
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
### Invariants:
|
|
19
|
-
1. **Trunk-Based Development**: Feature branches must be short-lived ($\le 24$ hours) and merged into `main` continuously. Avoid long-lived feature branches that cause painful merge conflicts.
|
|
20
|
-
2. **Shift-Left Automated PR Gates**: Every PR must pass automated CI checks before merge:
|
|
21
|
-
- Zero linter or syntax errors (`npm run lint` / `cargo clippy`).
|
|
22
|
-
- Strict type-checking (`tsc --noEmit` / `mypy`).
|
|
23
|
-
- 100.00% automated test coverage gate.
|
|
24
|
-
3. **Deterministic Build Caching**: Cache dependency directories (`~/.pnpm-store`, `~/.cargo`, `~/.cache/uv`) and Docker layer caches to maintain pipeline execution times under 3 minutes.
|
|
25
|
-
|
|
26
|
-
---
|
|
27
|
-
|
|
28
|
-
## 2. Secure OCI Container Infrastructure
|
|
29
|
-
|
|
30
|
-
All production container images must follow strict security minimization standards:
|
|
31
|
-
|
|
32
|
-
```dockerfile
|
|
33
|
-
# Multi-Stage Build Pattern
|
|
34
|
-
FROM node:22-alpine AS builder
|
|
35
|
-
WORKDIR /app
|
|
36
|
-
COPY package.json pnpm-lock.yaml ./
|
|
37
|
-
RUN corepack enable && pnpm install --frozen-lockfile
|
|
38
|
-
COPY . .
|
|
39
|
-
RUN pnpm build
|
|
40
|
-
|
|
41
|
-
# Minimal Distroless Runtime Stage
|
|
42
|
-
FROM gcr.io/distroless/nodejs22-debian12:nonroot
|
|
43
|
-
WORKDIR /app
|
|
44
|
-
COPY --from=builder --chown=nonroot:nonroot /app/dist ./dist
|
|
45
|
-
COPY --from=builder --chown=nonroot:nonroot /app/node_modules ./node_modules
|
|
46
|
-
USER nonroot
|
|
47
|
-
EXPOSE 3000
|
|
48
|
-
ENTRYPOINT ["node", "dist/index.js"]
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
### Invariants:
|
|
52
|
-
1. **Multi-Stage Builds**: Build tools, package managers, and compilers must never leak into final runtime images.
|
|
53
|
-
2. **Minimal Distroless / Scratch Base**: Use Google Distroless or `scratch` images. Never ship package managers (`apt`, `apk`), shells (`bash`, `sh`), or debugging utilities in production images.
|
|
54
|
-
3. **Non-Root Execution**: Containers must never run as UID 0 (`root`). Always specify an unprivileged user (`USER nonroot:nonroot` or `USER 10001:10001`).
|
|
55
|
-
4. **Read-Only Root Filesystem**: Configure container runtimes with `read_only: true`, mounting ephemeral tmpfs only to designated writable directories (`/tmp`).
|
|
56
|
-
|
|
57
|
-
---
|
|
58
|
-
|
|
59
|
-
## 3. DevSecOps & Supply Chain Security
|
|
60
|
-
|
|
61
|
-
Security checks must be embedded directly into developer workflows and automated pipelines:
|
|
62
|
-
|
|
63
|
-
1. **Pre-Commit Secret Scanning**: Gating tools (e.g. **Secretlint**, **Gitleaks**) must block commits containing private keys, API tokens, passwords, or cloud credentials.
|
|
64
|
-
2. **Software Bill of Materials (SBOM)**: Every release artifact must generate a machine-readable SBOM in **CycloneDX** or **SPDX** format (using `syft` or `cyclonedx-cli`) documenting all direct and transitive dependencies.
|
|
65
|
-
3. **Automated Vulnerability Scanning**: Scan container images and dependencies with **Trivy** or **Grype** in CI. Automatically fail pipelines on unpatched `CRITICAL` or `HIGH` Common Vulnerabilities and Exposures (CVEs).
|
|
66
|
-
|
|
67
|
-
---
|
|
68
|
-
|
|
69
|
-
## 4. Continuous Deployment & Zero-Downtime Rollouts
|
|
70
|
-
|
|
71
|
-
1. **Zero-Downtime Deployment Strategy**: Deployments must utilize rolling updates, canary releases, or blue/green switches. New container instances must pass readiness probes before receiving production traffic.
|
|
72
|
-
2. **Container Health & Lifecycle Probes**:
|
|
73
|
-
- `readinessProbe`: Validates database connectivity and dependency readiness before routing HTTP traffic.
|
|
74
|
-
- `livenessProbe`: Detects deadlocks and restarts unresponsive containers.
|
|
75
|
-
- Graceful Shutdown: Handle `SIGTERM` deterministically by draining in-flight requests within a 30-second termination window.
|
|
76
|
-
3. **Cryptographic Image Signing**: Sign container images with **Cosign** (Sigstore) during CI, and enforce admission controller verification in production clusters.
|
|
1
|
+
# DevOps, CI/CD, Container Infrastructure & DevSecOps
|
|
2
|
+
|
|
3
|
+
> **Core Mandate:** Enforce trunk-based continuous integration with shift-left automated gates, minimal distroless OCI container packaging, non-root execution security, software supply chain verification (SBOM & Trivy), and zero-downtime continuous deployment.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Continuous Integration & Trunk-Based Development
|
|
8
|
+
|
|
9
|
+
CI pipelines must execute fast, deterministic, shift-left quality gates on every commit and pull request:
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
[Local Commit] ──► [Pre-Commit Hook] ──► [Pull Request] ──► [Automated CI Gate] ──► [Merge to Main]
|
|
13
|
+
• Secretlint • Build Cache • Lint & Format Check
|
|
14
|
+
• Type Check • 100.00% Test Coverage
|
|
15
|
+
• DevSecOps CVE Scan
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### Invariants:
|
|
19
|
+
1. **Trunk-Based Development**: Feature branches must be short-lived ($\le 24$ hours) and merged into `main` continuously. Avoid long-lived feature branches that cause painful merge conflicts.
|
|
20
|
+
2. **Shift-Left Automated PR Gates**: Every PR must pass automated CI checks before merge:
|
|
21
|
+
- Zero linter or syntax errors (`npm run lint` / `cargo clippy`).
|
|
22
|
+
- Strict type-checking (`tsc --noEmit` / `mypy`).
|
|
23
|
+
- 100.00% automated test coverage gate.
|
|
24
|
+
3. **Deterministic Build Caching**: Cache dependency directories (`~/.pnpm-store`, `~/.cargo`, `~/.cache/uv`) and Docker layer caches to maintain pipeline execution times under 3 minutes.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 2. Secure OCI Container Infrastructure
|
|
29
|
+
|
|
30
|
+
All production container images must follow strict security minimization standards:
|
|
31
|
+
|
|
32
|
+
```dockerfile
|
|
33
|
+
# Multi-Stage Build Pattern
|
|
34
|
+
FROM node:22-alpine AS builder
|
|
35
|
+
WORKDIR /app
|
|
36
|
+
COPY package.json pnpm-lock.yaml ./
|
|
37
|
+
RUN corepack enable && pnpm install --frozen-lockfile
|
|
38
|
+
COPY . .
|
|
39
|
+
RUN pnpm build
|
|
40
|
+
|
|
41
|
+
# Minimal Distroless Runtime Stage
|
|
42
|
+
FROM gcr.io/distroless/nodejs22-debian12:nonroot
|
|
43
|
+
WORKDIR /app
|
|
44
|
+
COPY --from=builder --chown=nonroot:nonroot /app/dist ./dist
|
|
45
|
+
COPY --from=builder --chown=nonroot:nonroot /app/node_modules ./node_modules
|
|
46
|
+
USER nonroot
|
|
47
|
+
EXPOSE 3000
|
|
48
|
+
ENTRYPOINT ["node", "dist/index.js"]
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Invariants:
|
|
52
|
+
1. **Multi-Stage Builds**: Build tools, package managers, and compilers must never leak into final runtime images.
|
|
53
|
+
2. **Minimal Distroless / Scratch Base**: Use Google Distroless or `scratch` images. Never ship package managers (`apt`, `apk`), shells (`bash`, `sh`), or debugging utilities in production images.
|
|
54
|
+
3. **Non-Root Execution**: Containers must never run as UID 0 (`root`). Always specify an unprivileged user (`USER nonroot:nonroot` or `USER 10001:10001`).
|
|
55
|
+
4. **Read-Only Root Filesystem**: Configure container runtimes with `read_only: true`, mounting ephemeral tmpfs only to designated writable directories (`/tmp`).
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## 3. DevSecOps & Supply Chain Security
|
|
60
|
+
|
|
61
|
+
Security checks must be embedded directly into developer workflows and automated pipelines:
|
|
62
|
+
|
|
63
|
+
1. **Pre-Commit Secret Scanning**: Gating tools (e.g. **Secretlint**, **Gitleaks**) must block commits containing private keys, API tokens, passwords, or cloud credentials.
|
|
64
|
+
2. **Software Bill of Materials (SBOM)**: Every release artifact must generate a machine-readable SBOM in **CycloneDX** or **SPDX** format (using `syft` or `cyclonedx-cli`) documenting all direct and transitive dependencies.
|
|
65
|
+
3. **Automated Vulnerability Scanning**: Scan container images and dependencies with **Trivy** or **Grype** in CI. Automatically fail pipelines on unpatched `CRITICAL` or `HIGH` Common Vulnerabilities and Exposures (CVEs).
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## 4. Continuous Deployment & Zero-Downtime Rollouts
|
|
70
|
+
|
|
71
|
+
1. **Zero-Downtime Deployment Strategy**: Deployments must utilize rolling updates, canary releases, or blue/green switches. New container instances must pass readiness probes before receiving production traffic.
|
|
72
|
+
2. **Container Health & Lifecycle Probes**:
|
|
73
|
+
- `readinessProbe`: Validates database connectivity and dependency readiness before routing HTTP traffic.
|
|
74
|
+
- `livenessProbe`: Detects deadlocks and restarts unresponsive containers.
|
|
75
|
+
- Graceful Shutdown: Handle `SIGTERM` deterministically by draining in-flight requests within a 30-second termination window.
|
|
76
|
+
3. **Cryptographic Image Signing**: Sign container images with **Cosign** (Sigstore) during CI, and enforce admission controller verification in production clusters.
|
|
@@ -1,122 +1,122 @@
|
|
|
1
|
-
# Domain-Driven Design (DDD) & Ubiquitous Language
|
|
2
|
-
|
|
3
|
-
> **Core Mandate:** Separate Problem Space from Solution Space, establish unambiguous Ubiquitous Language definitions, isolate Bounded Contexts, guarantee Domain-Code Language Agreement, and protect Aggregate invariants.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 1. Problem Space vs. Solution Space (Evans & Vernon)
|
|
8
|
-
|
|
9
|
-
Software engineering fails when teams jump directly into the **Solution Space** (choosing languages, frameworks, databases, and microservices) before fully defining the **Problem Space**.
|
|
10
|
-
|
|
11
|
-
```mermaid
|
|
12
|
-
flowchart TD
|
|
13
|
-
subgraph ProblemSpace["The Problem Space (The Essence)"]
|
|
14
|
-
direction TB
|
|
15
|
-
P1["Business Problem ➔ Subdomains (Core / Supporting / Generic) ➔ Invariants"]
|
|
16
|
-
P2["Operational Constraints: Execution target, Latency budget, GC limits"]
|
|
17
|
-
P1 --- P2
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
subgraph SolutionSpace["The Solution Space (The Accidents)"]
|
|
21
|
-
direction TB
|
|
22
|
-
S1["Bounded Contexts ➔ Architectural Style (DOD, Hexagonal, Pipeline)"]
|
|
23
|
-
S2["Emergent Toolchain: Programming Language, Runtime, Persistence"]
|
|
24
|
-
S1 --- S2
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
ProblemSpace -->|Shapes & Dictates| SolutionSpace
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
- **The Problem Space (The Essence - Fred Brooks):** Concerns *what* problem is being solved, the entities, state transitions, and operational constraints (e.g. 16.6ms frame budget for games, zero-install browser sandbox for extensions, or ACID compliance for banking). **Zero technology, stack, or database choices are permitted in the Problem Space.**
|
|
31
|
-
- **The Solution Space (The Accidents):** Concerns *how* the system is realized. Runtimes, programming languages (C, Rust, TS, Go, Java), and storage engines are **emergent outputs** derived strictly from Problem Space constraints.
|
|
32
|
-
- **The Golden Hammer Anti-Pattern:** Selecting tools (e.g., "Let's use Next.js and PostgreSQL") before mapping problem constraints forces the domain to fit the tool, creating massive accidental complexity.
|
|
33
|
-
|
|
34
|
-
### Strategic Subdomain & Capability Mapping
|
|
35
|
-
Structure enterprise business capabilities into three distinct tiers:
|
|
36
|
-
1. **Core Subdomain / Capabilities**: Proprietary value drivers and business differentiators (e.g. specialized workflow engines, dynamic pricing algorithms). Allocate 80% of architectural effort here.
|
|
37
|
-
2. **Supporting Subdomain / Capabilities**: Business functions specific to the domain but not competitive differentiators (e.g. order tracking, invoice rendering).
|
|
38
|
-
3. **Generic Subdomain / Capabilities**: Standard commoditized software (e.g. authentication, audit logging, email transport). Rely exclusively on standard open-source libraries.
|
|
39
|
-
|
|
40
|
-
---
|
|
41
|
-
|
|
42
|
-
## 2. Domain-Code Language Agreement
|
|
43
|
-
|
|
44
|
-
The fundamental premise of Domain-Driven Design (Eric Evans) is that **the code is the model, and the model is the code**. Any divergence between the mental model of domain experts and the source code is called **Linguistic Drift**.
|
|
45
|
-
|
|
46
|
-
### Principles of Linguistic Alignment
|
|
47
|
-
1. **Zero Synonyms (The Single Name Rule)**: Every domain concept has exactly one authoritative term. Synonyms (e.g. `Client` vs `User`, `Account` vs `Organization`, `Contract` vs `Agreement`) are strictly forbidden across code, tests, and user interfaces.
|
|
48
|
-
2. **Eliminate Technical Jargon from Domain Core**: Domain models must not leak technical implementation terms (e.g. `UserRecord`, `TenantRow`, `DataDTO`, `IsActiveFlag`). The domain language must be pure business vocabulary.
|
|
49
|
-
3. **Contextual Isolation**: When a single English word has multiple meanings across business units, split the terms or isolate them within dedicated Bounded Contexts:
|
|
50
|
-
- *Example*: In multi-tenant infrastructure, a system isolation boundary is an **Organization** / **Tenant Workspace**. In application operations, a participant is a **Member**, **User**, or **Customer**. Using "Tenant" for both creates semantic ambiguity and catastrophic bugs.
|
|
51
|
-
|
|
52
|
-
---
|
|
53
|
-
|
|
54
|
-
## 3. Living Ubiquitous Language Glossary
|
|
55
|
-
|
|
56
|
-
Every project must maintain an authoritative, version-controlled **Living Ubiquitous Language Glossary** at [`docs/knowledge/ubiquitous_language.md`](../knowledge/ubiquitous_language.md).
|
|
57
|
-
|
|
58
|
-
### Structure of a Glossary Entry
|
|
59
|
-
Each entry must define:
|
|
60
|
-
- **Canonical Term**: The agreed domain name.
|
|
61
|
-
- **Definition**: The business meaning agreed with stakeholders.
|
|
62
|
-
- **Bounded Context**: The domain subsystem where this definition holds authority.
|
|
63
|
-
- **Forbidden Synonyms**: Banned terms that must never appear in code, schemas, or UI.
|
|
64
|
-
- **Code Representations**: Exact class, type, interface, and database table names.
|
|
65
|
-
|
|
66
|
-
---
|
|
67
|
-
|
|
68
|
-
## 4. Automated Enforcement & Linters
|
|
69
|
-
|
|
70
|
-
To prevent linguistic drift over time, teams must employ mechanical enforcement:
|
|
71
|
-
|
|
72
|
-
### 1. Static Analysis / Linter Rules
|
|
73
|
-
Configure custom linter rules (e.g. ESLint `id-denylist` or custom AST rules) to forbid banned synonyms in identifiers:
|
|
74
|
-
```json
|
|
75
|
-
{
|
|
76
|
-
"rules": {
|
|
77
|
-
"id-denylist": ["error", "client_user", "account_org", "raw_data_dto"]
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
### 2. Branded Nominal Types
|
|
83
|
-
Prevent "Primitive Obsession" where generic strings or IDs are conflated across domain boundaries:
|
|
84
|
-
```typescript
|
|
85
|
-
export type UserId = string & { readonly __brand: unique symbol };
|
|
86
|
-
export type OrganizationId = string & { readonly __brand: unique symbol };
|
|
87
|
-
export type OrderId = string & { readonly __brand: unique symbol };
|
|
88
|
-
|
|
89
|
-
// The compiler prevents accidentally passing an OrganizationId where a UserId is required:
|
|
90
|
-
function assignUserToOrder(orderId: OrderId, userId: UserId): void { ... }
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
### 3. Living Executable Specifications (Gherkin BDD)
|
|
94
|
-
Acceptance criteria must be written strictly in Ubiquitous Language, serving as executable contracts that verify domain terminology in automated test runners.
|
|
95
|
-
|
|
96
|
-
---
|
|
97
|
-
|
|
98
|
-
## 5. Tactical Patterns & Invariants
|
|
99
|
-
|
|
100
|
-
1. **Entities**: Objects defined by identity that persists across state changes (e.g. `User`, `Order`, `Invoice`).
|
|
101
|
-
2. **Value Objects**: Immutable objects defined strictly by their attributes with no identity (e.g. `Money`, `DateRange`, `EmailAddress`).
|
|
102
|
-
3. **Aggregates & Aggregate Roots**: Clusters of domain objects treated as a single transactional consistency boundary. All mutations must pass through explicit methods on the Aggregate Root that assert invariants before committing state:
|
|
103
|
-
- **Zero Anemic Domain Models**: Domain entities must encapsulate state and validation logic. Never expose public setters that allow outside code to corrupt business rules.
|
|
104
|
-
- **Aggregate Root Gatekeeper Pattern**:
|
|
105
|
-
```typescript
|
|
106
|
-
export class OrderAggregate {
|
|
107
|
-
private constructor(private order: OrderState) {}
|
|
108
|
-
|
|
109
|
-
submit(): Result<void, DomainError> {
|
|
110
|
-
if (this.order.items.length === 0) {
|
|
111
|
-
return err(new DomainError('Cannot submit empty order'));
|
|
112
|
-
}
|
|
113
|
-
if (this.order.status !== 'DRAFT') {
|
|
114
|
-
return err(new DomainError('Order already submitted'));
|
|
115
|
-
}
|
|
116
|
-
this.order.status = 'SUBMITTED';
|
|
117
|
-
return ok(undefined);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
```
|
|
121
|
-
4. **Anti-Corruption Layer (ACL)**: When integrating with third-party APIs or legacy systems that use different terminology, translate external payloads into the internal Ubiquitous Language at the boundary adapter before they enter the domain core.
|
|
122
|
-
5. **Cross-Aggregate Coordination in Use Cases**: While an Aggregate Root guards its own internal invariants, business operations frequently span multiple aggregates (e.g. reserving an inventory item for an agreement). Application use cases or orchestrators must coordinate aggregate transitions atomically: asserting resource availability prior to state change, transitioning the constrained entity (e.g. `ALLOCATED`), and restoring state (`AVAILABLE`) upon cancellation, avoiding double-allocation race conditions without coupling aggregates directly.
|
|
1
|
+
# Domain-Driven Design (DDD) & Ubiquitous Language
|
|
2
|
+
|
|
3
|
+
> **Core Mandate:** Separate Problem Space from Solution Space, establish unambiguous Ubiquitous Language definitions, isolate Bounded Contexts, guarantee Domain-Code Language Agreement, and protect Aggregate invariants.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Problem Space vs. Solution Space (Evans & Vernon)
|
|
8
|
+
|
|
9
|
+
Software engineering fails when teams jump directly into the **Solution Space** (choosing languages, frameworks, databases, and microservices) before fully defining the **Problem Space**.
|
|
10
|
+
|
|
11
|
+
```mermaid
|
|
12
|
+
flowchart TD
|
|
13
|
+
subgraph ProblemSpace["The Problem Space (The Essence)"]
|
|
14
|
+
direction TB
|
|
15
|
+
P1["Business Problem ➔ Subdomains (Core / Supporting / Generic) ➔ Invariants"]
|
|
16
|
+
P2["Operational Constraints: Execution target, Latency budget, GC limits"]
|
|
17
|
+
P1 --- P2
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
subgraph SolutionSpace["The Solution Space (The Accidents)"]
|
|
21
|
+
direction TB
|
|
22
|
+
S1["Bounded Contexts ➔ Architectural Style (DOD, Hexagonal, Pipeline)"]
|
|
23
|
+
S2["Emergent Toolchain: Programming Language, Runtime, Persistence"]
|
|
24
|
+
S1 --- S2
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
ProblemSpace -->|Shapes & Dictates| SolutionSpace
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
- **The Problem Space (The Essence - Fred Brooks):** Concerns *what* problem is being solved, the entities, state transitions, and operational constraints (e.g. 16.6ms frame budget for games, zero-install browser sandbox for extensions, or ACID compliance for banking). **Zero technology, stack, or database choices are permitted in the Problem Space.**
|
|
31
|
+
- **The Solution Space (The Accidents):** Concerns *how* the system is realized. Runtimes, programming languages (C, Rust, TS, Go, Java), and storage engines are **emergent outputs** derived strictly from Problem Space constraints.
|
|
32
|
+
- **The Golden Hammer Anti-Pattern:** Selecting tools (e.g., "Let's use Next.js and PostgreSQL") before mapping problem constraints forces the domain to fit the tool, creating massive accidental complexity.
|
|
33
|
+
|
|
34
|
+
### Strategic Subdomain & Capability Mapping
|
|
35
|
+
Structure enterprise business capabilities into three distinct tiers:
|
|
36
|
+
1. **Core Subdomain / Capabilities**: Proprietary value drivers and business differentiators (e.g. specialized workflow engines, dynamic pricing algorithms). Allocate 80% of architectural effort here.
|
|
37
|
+
2. **Supporting Subdomain / Capabilities**: Business functions specific to the domain but not competitive differentiators (e.g. order tracking, invoice rendering).
|
|
38
|
+
3. **Generic Subdomain / Capabilities**: Standard commoditized software (e.g. authentication, audit logging, email transport). Rely exclusively on standard open-source libraries.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 2. Domain-Code Language Agreement
|
|
43
|
+
|
|
44
|
+
The fundamental premise of Domain-Driven Design (Eric Evans) is that **the code is the model, and the model is the code**. Any divergence between the mental model of domain experts and the source code is called **Linguistic Drift**.
|
|
45
|
+
|
|
46
|
+
### Principles of Linguistic Alignment
|
|
47
|
+
1. **Zero Synonyms (The Single Name Rule)**: Every domain concept has exactly one authoritative term. Synonyms (e.g. `Client` vs `User`, `Account` vs `Organization`, `Contract` vs `Agreement`) are strictly forbidden across code, tests, and user interfaces.
|
|
48
|
+
2. **Eliminate Technical Jargon from Domain Core**: Domain models must not leak technical implementation terms (e.g. `UserRecord`, `TenantRow`, `DataDTO`, `IsActiveFlag`). The domain language must be pure business vocabulary.
|
|
49
|
+
3. **Contextual Isolation**: When a single English word has multiple meanings across business units, split the terms or isolate them within dedicated Bounded Contexts:
|
|
50
|
+
- *Example*: In multi-tenant infrastructure, a system isolation boundary is an **Organization** / **Tenant Workspace**. In application operations, a participant is a **Member**, **User**, or **Customer**. Using "Tenant" for both creates semantic ambiguity and catastrophic bugs.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## 3. Living Ubiquitous Language Glossary
|
|
55
|
+
|
|
56
|
+
Every project must maintain an authoritative, version-controlled **Living Ubiquitous Language Glossary** at [`docs/knowledge/ubiquitous_language.md`](../knowledge/ubiquitous_language.md).
|
|
57
|
+
|
|
58
|
+
### Structure of a Glossary Entry
|
|
59
|
+
Each entry must define:
|
|
60
|
+
- **Canonical Term**: The agreed domain name.
|
|
61
|
+
- **Definition**: The business meaning agreed with stakeholders.
|
|
62
|
+
- **Bounded Context**: The domain subsystem where this definition holds authority.
|
|
63
|
+
- **Forbidden Synonyms**: Banned terms that must never appear in code, schemas, or UI.
|
|
64
|
+
- **Code Representations**: Exact class, type, interface, and database table names.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## 4. Automated Enforcement & Linters
|
|
69
|
+
|
|
70
|
+
To prevent linguistic drift over time, teams must employ mechanical enforcement:
|
|
71
|
+
|
|
72
|
+
### 1. Static Analysis / Linter Rules
|
|
73
|
+
Configure custom linter rules (e.g. ESLint `id-denylist` or custom AST rules) to forbid banned synonyms in identifiers:
|
|
74
|
+
```json
|
|
75
|
+
{
|
|
76
|
+
"rules": {
|
|
77
|
+
"id-denylist": ["error", "client_user", "account_org", "raw_data_dto"]
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### 2. Branded Nominal Types
|
|
83
|
+
Prevent "Primitive Obsession" where generic strings or IDs are conflated across domain boundaries:
|
|
84
|
+
```typescript
|
|
85
|
+
export type UserId = string & { readonly __brand: unique symbol };
|
|
86
|
+
export type OrganizationId = string & { readonly __brand: unique symbol };
|
|
87
|
+
export type OrderId = string & { readonly __brand: unique symbol };
|
|
88
|
+
|
|
89
|
+
// The compiler prevents accidentally passing an OrganizationId where a UserId is required:
|
|
90
|
+
function assignUserToOrder(orderId: OrderId, userId: UserId): void { ... }
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### 3. Living Executable Specifications (Gherkin BDD)
|
|
94
|
+
Acceptance criteria must be written strictly in Ubiquitous Language, serving as executable contracts that verify domain terminology in automated test runners.
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## 5. Tactical Patterns & Invariants
|
|
99
|
+
|
|
100
|
+
1. **Entities**: Objects defined by identity that persists across state changes (e.g. `User`, `Order`, `Invoice`).
|
|
101
|
+
2. **Value Objects**: Immutable objects defined strictly by their attributes with no identity (e.g. `Money`, `DateRange`, `EmailAddress`).
|
|
102
|
+
3. **Aggregates & Aggregate Roots**: Clusters of domain objects treated as a single transactional consistency boundary. All mutations must pass through explicit methods on the Aggregate Root that assert invariants before committing state:
|
|
103
|
+
- **Zero Anemic Domain Models**: Domain entities must encapsulate state and validation logic. Never expose public setters that allow outside code to corrupt business rules.
|
|
104
|
+
- **Aggregate Root Gatekeeper Pattern**:
|
|
105
|
+
```typescript
|
|
106
|
+
export class OrderAggregate {
|
|
107
|
+
private constructor(private order: OrderState) {}
|
|
108
|
+
|
|
109
|
+
submit(): Result<void, DomainError> {
|
|
110
|
+
if (this.order.items.length === 0) {
|
|
111
|
+
return err(new DomainError('Cannot submit empty order'));
|
|
112
|
+
}
|
|
113
|
+
if (this.order.status !== 'DRAFT') {
|
|
114
|
+
return err(new DomainError('Order already submitted'));
|
|
115
|
+
}
|
|
116
|
+
this.order.status = 'SUBMITTED';
|
|
117
|
+
return ok(undefined);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
4. **Anti-Corruption Layer (ACL)**: When integrating with third-party APIs or legacy systems that use different terminology, translate external payloads into the internal Ubiquitous Language at the boundary adapter before they enter the domain core.
|
|
122
|
+
5. **Cross-Aggregate Coordination in Use Cases**: While an Aggregate Root guards its own internal invariants, business operations frequently span multiple aggregates (e.g. reserving an inventory item for an agreement). Application use cases or orchestrators must coordinate aggregate transitions atomically: asserting resource availability prior to state change, transitioning the constrained entity (e.g. `ALLOCATED`), and restoring state (`AVAILABLE`) upon cancellation, avoiding double-allocation race conditions without coupling aggregates directly.
|
|
@@ -1,52 +1,54 @@
|
|
|
1
|
-
# Error Handling, Request Tracing & Schema Validation
|
|
2
|
-
|
|
3
|
-
> **Core Mandate:** Enforce fail-fast schema validation at startup, structured OpenTelemetry/JSON request tracing, standardized RFC
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 1. Fail-Fast Configuration & Environment Validation
|
|
8
|
-
|
|
9
|
-
Validate all configuration parameters and environment variables at process bootstrap using strict schema definitions before initializing servers or database connection pools:
|
|
10
|
-
- **Immediate Process Termination**: Halt startup immediately with non-zero exit code if any mandatory variable is missing, malformed, or insecure.
|
|
11
|
-
- **Strict Prohibition of Secret Fallbacks**: Never provide default fallback values for production secrets, database credentials, or private cryptographic keys.
|
|
12
|
-
|
|
13
|
-
---
|
|
14
|
-
|
|
15
|
-
## 2. Structured Tracing & Correlation (OpenTelemetry / W3C)
|
|
16
|
-
|
|
17
|
-
- **Standardized Correlation IDs**: Bind a unique `x-request-id` (UUID v4) and W3C `traceparent` to every inbound request. Forward these identifiers across all downstream RPC calls, database queries, and async broker messages.
|
|
18
|
-
- **Structured JSON Logging**: Format all application logs in structured JSON conforming to OpenTelemetry Resource Schemas or Elastic Common Schema (ECS) (`timestamp`, `severity`, `trace_id`, `span_id`, `request_id`, `tenant_id`, `message`).
|
|
19
|
-
|
|
20
|
-
---
|
|
21
|
-
|
|
22
|
-
## 3. Standardized Error Response Envelope (RFC
|
|
23
|
-
|
|
24
|
-
Enforce a uniform error envelope across all external HTTP/REST endpoints conforming to the **RFC
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
- `
|
|
49
|
-
- `
|
|
50
|
-
- `
|
|
51
|
-
- `
|
|
52
|
-
-
|
|
1
|
+
# Error Handling, Request Tracing & Schema Validation
|
|
2
|
+
|
|
3
|
+
> **Core Mandate:** Enforce fail-fast schema validation at startup, structured OpenTelemetry/JSON request tracing, standardized RFC 9457 problem details, and an explicit canonical DomainError hierarchy.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Fail-Fast Configuration & Environment Validation
|
|
8
|
+
|
|
9
|
+
Validate all configuration parameters and environment variables at process bootstrap using strict schema definitions before initializing servers or database connection pools:
|
|
10
|
+
- **Immediate Process Termination**: Halt startup immediately with non-zero exit code if any mandatory variable is missing, malformed, or insecure.
|
|
11
|
+
- **Strict Prohibition of Secret Fallbacks**: Never provide default fallback values for production secrets, database credentials, or private cryptographic keys.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 2. Structured Tracing & Correlation (OpenTelemetry / W3C)
|
|
16
|
+
|
|
17
|
+
- **Standardized Correlation IDs**: Bind a unique `x-request-id` (UUID v4) and W3C `traceparent` to every inbound request. Forward these identifiers across all downstream RPC calls, database queries, and async broker messages.
|
|
18
|
+
- **Structured JSON Logging**: Format all application logs in structured JSON conforming to OpenTelemetry Resource Schemas or Elastic Common Schema (ECS) (`timestamp`, `severity`, `trace_id`, `span_id`, `request_id`, `tenant_id`, `message`).
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## 3. Standardized Error Response Envelope (RFC 9457)
|
|
23
|
+
|
|
24
|
+
Enforce a uniform error envelope across all external HTTP/REST endpoints conforming to the **RFC 9457 Problem Details** standard.
|
|
25
|
+
|
|
26
|
+
> **Spec currency:** RFC 7807 was **obsoleted by RFC 9457** (July 2023). The wire format is unchanged — `type`/`title`/`status`/`detail`/`instance` plus the `application/problem+json` media type — so this is a citation correction, not a migration. Cite RFC 9457; do not reference RFC 7807 as a current standard.
|
|
27
|
+
|
|
28
|
+
```json
|
|
29
|
+
{
|
|
30
|
+
"type": "https://api.domain.com/errors/RESOURCE_LOCKED",
|
|
31
|
+
"title": "Resource Conflict",
|
|
32
|
+
"status": 409,
|
|
33
|
+
"detail": "The requested order is currently undergoing payment processing.",
|
|
34
|
+
"instance": "/v1/orders/123",
|
|
35
|
+
"code": "ORDER_LOCKED",
|
|
36
|
+
"requestId": "550e8400-e29b-41d4-a716-446655440000",
|
|
37
|
+
"invalidParams": []
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
- **Production Masking Invariant**: Strictly mask internal database error codes, raw SQL queries, file system paths, and stack traces from external client responses in non-local environments.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## 4. Canonical Domain Error Hierarchy & Type-Safe Narrowing
|
|
46
|
+
|
|
47
|
+
- **Canonical DomainError Hierarchy**: Model operational domain failures using an explicit `DomainError` base class with canonical subclasses:
|
|
48
|
+
- `ValidationError` (maps to HTTP 400 / 422)
|
|
49
|
+
- `UnauthorizedError` (maps to HTTP 401)
|
|
50
|
+
- `ForbiddenError` (maps to HTTP 403)
|
|
51
|
+
- `NotFoundError` (maps to HTTP 404)
|
|
52
|
+
- `ConflictError` (maps to HTTP 409)
|
|
53
|
+
- `ExpiredError` (maps to HTTP 410)
|
|
54
|
+
- **Eliminate Untyped Error Monkey-Patching**: Strictly prohibit monkey-patching arbitrary properties onto error objects at catch sites (e.g. `(err as any).statusCode = 404`). Use clean `instanceof` narrowing in HTTP error middleware to map domain errors deterministically to RFC 7807 status codes with full compiler type safety.
|
|
@@ -1,59 +1,59 @@
|
|
|
1
|
-
# Feature Flagging & OpenFeature Standards
|
|
2
|
-
|
|
3
|
-
> **Core Mandate:** Enforce the open-source OpenFeature standard, evaluate flags dynamically via Flipt or Unleash backends, and maintain clean flag lifecycles.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 1. The YAGNI Gate: Environment Variables vs. Dynamic Feature Flags
|
|
8
|
-
|
|
9
|
-
Dynamic feature flag platforms (Flipt, Unleash) introduce network I/O, external infrastructure dependencies, and branching code complexity. **Never deploy a feature flag server when an environment variable or static config satisfies the requirement.**
|
|
10
|
-
|
|
11
|
-
```mermaid
|
|
12
|
-
flowchart TD
|
|
13
|
-
subgraph FlagGate["Feature Flag YAGNI Gate"]
|
|
14
|
-
B1["1. Simple Baseline (Day 1)<br/>• Static environment variable (ENABLE_NEW_CHECKOUT=true)<br/>• Compile-time or build-time feature toggling<br/>• Zero external flag servers (no Flipt, Unleash, LaunchDarkly)"]
|
|
15
|
-
B2["2. Anti-Triggers (Forbidden)<br/>• Flags that only change during scheduled code deployments<br/>• Low-risk internal refactors covered by automated test suites<br/>• Local CLI tools, browser extensions, or single-tenant utilities"]
|
|
16
|
-
B3["3. The Tipping Point (Graduation)<br/>• Percentage-based canary rollouts (5% -> 25% -> 100%)<br/>• Non-engineering product/business teams require runtime toggling without deployment<br/>• Contextual tenant targeting (per subscription tier or tenant ID)<br/>• High-blast-radius integrations requiring instant kill-switches"]
|
|
17
|
-
B1 -->|Forbidden if static or low-risk| B2
|
|
18
|
-
B1 -->|Triggered by canaries or runtime targeting| B3
|
|
19
|
-
end
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
---
|
|
23
|
-
|
|
24
|
-
## 2. OpenFeature Standard Architecture
|
|
25
|
-
|
|
26
|
-
When the tipping point is reached, utilize open-source `@openfeature/server-sdk` with open-source providers (Flipt or Unleash):
|
|
27
|
-
|
|
28
|
-
```typescript
|
|
29
|
-
import { OpenFeature, Client } from '@openfeature/server-sdk';
|
|
30
|
-
import { FliptProvider } from '@openfeature/flipt-provider';
|
|
31
|
-
|
|
32
|
-
OpenFeature.setProvider(new FliptProvider({ url: process.env.FLIPT_URL }));
|
|
33
|
-
export const featureClient: Client = OpenFeature.getClient();
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
---
|
|
37
|
-
|
|
38
|
-
## 3. Contextual Tenant Targeting
|
|
39
|
-
|
|
40
|
-
Pass tenant identity and contextual attributes during evaluation:
|
|
41
|
-
|
|
42
|
-
```typescript
|
|
43
|
-
const isEnabled = await featureClient.getBooleanValue(
|
|
44
|
-
'advanced-analytics',
|
|
45
|
-
false,
|
|
46
|
-
{
|
|
47
|
-
targetingKey: user.id,
|
|
48
|
-
tenantId: user.tenantId,
|
|
49
|
-
tier: tenant.subscriptionTier
|
|
50
|
-
}
|
|
51
|
-
);
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
---
|
|
55
|
-
|
|
56
|
-
## 4. Flag Lifecycle Governance
|
|
57
|
-
|
|
58
|
-
- **Emergency Kill Switches**: Every high-risk feature or third-party integration must be wrapped in a flag that can immediately disable functionality without code redeployment.
|
|
59
|
-
- **Retirement Mandate**: When a feature is 100% rolled out for > 30 days, author a task to purge the flag and its dead code branches.
|
|
1
|
+
# Feature Flagging & OpenFeature Standards
|
|
2
|
+
|
|
3
|
+
> **Core Mandate:** Enforce the open-source OpenFeature standard, evaluate flags dynamically via Flipt or Unleash backends, and maintain clean flag lifecycles.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. The YAGNI Gate: Environment Variables vs. Dynamic Feature Flags
|
|
8
|
+
|
|
9
|
+
Dynamic feature flag platforms (Flipt, Unleash) introduce network I/O, external infrastructure dependencies, and branching code complexity. **Never deploy a feature flag server when an environment variable or static config satisfies the requirement.**
|
|
10
|
+
|
|
11
|
+
```mermaid
|
|
12
|
+
flowchart TD
|
|
13
|
+
subgraph FlagGate["Feature Flag YAGNI Gate"]
|
|
14
|
+
B1["1. Simple Baseline (Day 1)<br/>• Static environment variable (ENABLE_NEW_CHECKOUT=true)<br/>• Compile-time or build-time feature toggling<br/>• Zero external flag servers (no Flipt, Unleash, LaunchDarkly)"]
|
|
15
|
+
B2["2. Anti-Triggers (Forbidden)<br/>• Flags that only change during scheduled code deployments<br/>• Low-risk internal refactors covered by automated test suites<br/>• Local CLI tools, browser extensions, or single-tenant utilities"]
|
|
16
|
+
B3["3. The Tipping Point (Graduation)<br/>• Percentage-based canary rollouts (5% -> 25% -> 100%)<br/>• Non-engineering product/business teams require runtime toggling without deployment<br/>• Contextual tenant targeting (per subscription tier or tenant ID)<br/>• High-blast-radius integrations requiring instant kill-switches"]
|
|
17
|
+
B1 -->|Forbidden if static or low-risk| B2
|
|
18
|
+
B1 -->|Triggered by canaries or runtime targeting| B3
|
|
19
|
+
end
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 2. OpenFeature Standard Architecture
|
|
25
|
+
|
|
26
|
+
When the tipping point is reached, utilize open-source `@openfeature/server-sdk` with open-source providers (Flipt or Unleash):
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import { OpenFeature, Client } from '@openfeature/server-sdk';
|
|
30
|
+
import { FliptProvider } from '@openfeature/flipt-provider';
|
|
31
|
+
|
|
32
|
+
OpenFeature.setProvider(new FliptProvider({ url: process.env.FLIPT_URL }));
|
|
33
|
+
export const featureClient: Client = OpenFeature.getClient();
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## 3. Contextual Tenant Targeting
|
|
39
|
+
|
|
40
|
+
Pass tenant identity and contextual attributes during evaluation:
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
const isEnabled = await featureClient.getBooleanValue(
|
|
44
|
+
'advanced-analytics',
|
|
45
|
+
false,
|
|
46
|
+
{
|
|
47
|
+
targetingKey: user.id,
|
|
48
|
+
tenantId: user.tenantId,
|
|
49
|
+
tier: tenant.subscriptionTier
|
|
50
|
+
}
|
|
51
|
+
);
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## 4. Flag Lifecycle Governance
|
|
57
|
+
|
|
58
|
+
- **Emergency Kill Switches**: Every high-risk feature or third-party integration must be wrapped in a flag that can immediately disable functionality without code redeployment.
|
|
59
|
+
- **Retirement Mandate**: When a feature is 100% rolled out for > 30 days, author a task to purge the flag and its dead code branches.
|