azcodr 1.5.0 → 1.5.2
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 -0
- package/.agents/hooks.json.example +42 -42
- package/.agents/mcp_config.json.example +29 -24
- package/.agents/scripts/safety_guard.sh +34 -16
- package/.agents/scripts/verify_completion.sh +27 -13
- 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 -362
- 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 -172
- 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 +255 -253
- 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/copilot-instructions.md +1 -0
- package/.github/workflows/ci.yml +78 -0
- package/.gitignore +25 -25
- package/AGENTS.md +102 -102
- package/LICENSE +21 -21
- package/README.md +165 -154
- package/bin/azcodr.js +228 -228
- package/data/.gitkeep +0 -0
- package/docs/knowledge/ubiquitous_language.md +18 -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 +52 -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/index.d.ts +134 -123
- package/lib/index.js +5 -5
- package/lib/scaffold.js +448 -351
- package/memory.md +36 -36
- package/package.json +62 -59
- package/scripts/test_coverage.js +38 -0
- package/scripts/validate.js +258 -0
|
@@ -1,179 +1,179 @@
|
|
|
1
|
-
# API Architecture, Protocols & Communication Standards
|
|
2
|
-
|
|
3
|
-
> **Core Mandate:** Enforce standard HTTP semantics, synchronous vs. asynchronous processing (`202 Accepted`), capability metadata (`_actions`), safe mutations via idempotency keys, keyset cursor pagination, optimistic concurrency control (OCC), and RFC 8594 lifecycle versioning.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 1. Standard HTTP Semantics & Status Codes
|
|
8
|
-
|
|
9
|
-
APIs must adhere strictly to standard HTTP semantics. Never return `200 OK` for error envelopes:
|
|
10
|
-
|
|
11
|
-
| Status Code | Semantic Purpose | When to Return |
|
|
12
|
-
|---|---|---|
|
|
13
|
-
| **`200 OK`** | Successful read or synchronous update | Standard `GET`, `PATCH`, `PUT` queries that return payloads. |
|
|
14
|
-
| **`201 Created`** | Successful resource creation | Synchronous `POST` with `Location: /api/v1/resources/:id` header. |
|
|
15
|
-
| **`202 Accepted`** | Asynchronous task accepted | Tasks exceeding latency budgets (> 1.5s) delegated to background queues. |
|
|
16
|
-
| **`204 No Content`** | Successful action with zero payload | Standard `DELETE` or empty mutation responses. |
|
|
17
|
-
| **`400 Bad Request`** | Malformed syntax or protocol violation | Unparseable JSON, invalid query parameters. |
|
|
18
|
-
| **`401 Unauthorized`** | Missing or invalid authentication | Missing, expired, or tampered JWT / API token. |
|
|
19
|
-
| **`403 Forbidden`** | Authenticated but insufficient permission | Role, tenant boundary, or policy guard denial. |
|
|
20
|
-
| **`404 Not Found`** | Resource does not exist | Unknown entity identifier (or masked tenant resource). |
|
|
21
|
-
| **`409 Conflict`** | State conflict or race condition | Concurrency mismatch (`If-Match`), unique constraint, or in-flight idempotency. |
|
|
22
|
-
| **`422 Unprocessable`** | Semantic validation failure | Schema constraint violation (RFC 7807 problem details). |
|
|
23
|
-
| **`500 Internal Error`** | Unhandled server exception | Unexpected server failure; never leak internal stack traces. |
|
|
24
|
-
|
|
25
|
-
### Subresource URL Conventions
|
|
26
|
-
- Express relational hierarchy cleanly: `/api/v1/organizations/:orgId/projects/:projectId/members`.
|
|
27
|
-
- Limit URL nesting to a maximum of 2 subresource levels; for deeper resources, access directly via canonical ID (`/api/v1/tasks/:taskId`).
|
|
28
|
-
|
|
29
|
-
### Enumeration Masking
|
|
30
|
-
- Authentication and recovery endpoints must never reveal user existence (e.g. return `"If an account exists, a recovery link has been sent"` with identical timing).
|
|
31
|
-
|
|
32
|
-
---
|
|
33
|
-
|
|
34
|
-
## 2. Synchronous vs. Asynchronous Processing (`202 Accepted`)
|
|
35
|
-
|
|
36
|
-
Operations with unpredictable or long execution durations (> 1.5 seconds, such as video rendering, large PDF exports, batch imports, or complex report generation) must never block synchronous HTTP request threads:
|
|
37
|
-
|
|
38
|
-
```mermaid
|
|
39
|
-
sequenceDiagram
|
|
40
|
-
autonumber
|
|
41
|
-
actor Client
|
|
42
|
-
participant Gateway as API Gateway
|
|
43
|
-
participant Queue as Task Queue / Worker
|
|
44
|
-
|
|
45
|
-
Client->>Gateway: POST /reports/export (Long-running > 1.5s)
|
|
46
|
-
Gateway->>Queue: Dispatch background job
|
|
47
|
-
Gateway-->>Client: 202 Accepted (Location: /api/v1/tasks/tsk_123)
|
|
48
|
-
Note over Client,Gateway: Client polls GET /api/v1/tasks/tsk_123 until complete
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
### Protocol Standards:
|
|
52
|
-
1. Dispatch the payload to a persistent worker queue (e.g., BullMQ, Temporal, Celery).
|
|
53
|
-
2. Respond immediately with **`202 Accepted`** containing:
|
|
54
|
-
- Header: `Location: /api/v1/tasks/:taskId`
|
|
55
|
-
- Envelope:
|
|
56
|
-
```json
|
|
57
|
-
{
|
|
58
|
-
"taskId": "tsk_123",
|
|
59
|
-
"status": "QUEUED",
|
|
60
|
-
"pollIntervalMs": 2000,
|
|
61
|
-
"_links": {
|
|
62
|
-
"status": { "href": "/api/v1/tasks/tsk_123", "method": "GET" },
|
|
63
|
-
"cancel": { "href": "/api/v1/tasks/tsk_123", "method": "DELETE" }
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
```
|
|
67
|
-
3. Polling endpoint (`GET /api/v1/tasks/:taskId`) returns:
|
|
68
|
-
- In-progress: `200 OK` with status `PROCESSING` and progress percentage.
|
|
69
|
-
- Finished: `303 See Other` with `Location: /api/v1/reports/rep_789` or `200 OK` with `status: "COMPLETED"` and the final artifact URI.
|
|
70
|
-
|
|
71
|
-
---
|
|
72
|
-
|
|
73
|
-
## 3. Allowed Actions & Capability Metadata (`_actions` Envelope)
|
|
74
|
-
|
|
75
|
-
Clients must not duplicate complex server-side business and authorization rules to decide whether UI actions (edit, delete, approve, cancel, refund) are permitted. **The server is the authoritative source of truth.**
|
|
76
|
-
|
|
77
|
-
### Pattern: `_actions` and `_links` Envelope
|
|
78
|
-
Every resource response must embed an `_actions` boolean map and optional `_links` hypermedia block indicating what the requesting caller is permitted to do based on their role, tenant boundaries, and the entity's current lifecycle state:
|
|
79
|
-
|
|
80
|
-
```json
|
|
81
|
-
{
|
|
82
|
-
"id": "ord_9876",
|
|
83
|
-
"status": "SHIPPED",
|
|
84
|
-
"totalAmount": 149.99,
|
|
85
|
-
"currency": "USD",
|
|
86
|
-
"_actions": {
|
|
87
|
-
"canEdit": false,
|
|
88
|
-
"canCancel": false,
|
|
89
|
-
"canTrack": true,
|
|
90
|
-
"canRequestRefund": true
|
|
91
|
-
},
|
|
92
|
-
"_links": {
|
|
93
|
-
"self": { "href": "/api/v1/orders/ord_9876", "method": "GET" },
|
|
94
|
-
"track": { "href": "/api/v1/orders/ord_9876/tracking", "method": "GET" },
|
|
95
|
-
"refund": { "href": "/api/v1/orders/ord_9876/refunds", "method": "POST" }
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
### Frontend Binding:
|
|
101
|
-
- UI action buttons directly bind visibility or disabled state to `resource._actions.canCancel`.
|
|
102
|
-
- When business logic evolves (e.g. orders over $1,000 require manager approval), only backend policy changes—zero frontend redeployment required.
|
|
103
|
-
|
|
104
|
-
---
|
|
105
|
-
|
|
106
|
-
## 4. Safe Mutations via Idempotency Keys (IETF Draft)
|
|
107
|
-
|
|
108
|
-
To prevent duplicate execution (double charging, duplicate orders) caused by network retries or transient connection drops:
|
|
109
|
-
|
|
110
|
-
### Protocol Standards:
|
|
111
|
-
- Clients generating mutating requests (`POST`, `PATCH`) must supply a unique `Idempotency-Key: <uuid-v4>` header.
|
|
112
|
-
- **Server Execution Lifecycle**:
|
|
113
|
-
1. Check distributed idempotency cache for key `idemp:<tenantId>:<idempotencyKey>`.
|
|
114
|
-
2. If found with status `IN_FLIGHT`: return **`409 Conflict`** (`IDEMPOTENT_OPERATION_IN_PROGRESS`).
|
|
115
|
-
3. If found with status `COMPLETED`: return the cached HTTP status code, headers, and response payload without re-executing.
|
|
116
|
-
4. If not found: Acquire distributed lock, execute mutation within an atomic database transaction, cache the response envelope with a 24-hour TTL, and release the lock.
|
|
117
|
-
|
|
118
|
-
---
|
|
119
|
-
|
|
120
|
-
## 5. High-Scale Keyset / Cursor-Based Pagination
|
|
121
|
-
|
|
122
|
-
Never use offset pagination (`OFFSET 10000 LIMIT 20`) on large tables. Offsets degrade linearly ($O(N)$) and suffer from page-drift anomalies as rows are inserted or deleted.
|
|
123
|
-
|
|
124
|
-
### Specification & Envelope:
|
|
125
|
-
- Query Parameters: `?cursor=<opaque_base64>&limit=20` (default limit 20, max 100).
|
|
126
|
-
- Response Envelope:
|
|
127
|
-
```json
|
|
128
|
-
{
|
|
129
|
-
"data": [...],
|
|
130
|
-
"pagination": {
|
|
131
|
-
"nextCursor": "ZXlKaWRI...==",
|
|
132
|
-
"hasMore": true,
|
|
133
|
-
"limit": 20
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
```
|
|
137
|
-
- **Agnostic Keyset Query Pattern**:
|
|
138
|
-
```sql
|
|
139
|
-
SELECT * FROM orders
|
|
140
|
-
WHERE tenant_id = :tenantId
|
|
141
|
-
AND (created_at, id) < (:cursorCreatedAt, :cursorId)
|
|
142
|
-
ORDER BY created_at DESC, id DESC
|
|
143
|
-
LIMIT :limit + 1;
|
|
144
|
-
```
|
|
145
|
-
If `results.length > limit`, slice the extra item and encode its composite values (`created_at`, `id`) into the base64 `nextCursor`.
|
|
146
|
-
|
|
147
|
-
---
|
|
148
|
-
|
|
149
|
-
## 6. Optimistic Concurrency Control (OCC)
|
|
150
|
-
|
|
151
|
-
Prevent lost-update anomalies during concurrent edits without pessimistic database row locking:
|
|
152
|
-
|
|
153
|
-
### Protocol Standards:
|
|
154
|
-
- Every mutable entity contains an incrementing integer `version` column.
|
|
155
|
-
- The server returns the current entity version in the `ETag` response header: `ETag: W/"v4"`.
|
|
156
|
-
- Clients submitting updates (`PUT`, `PATCH`) must include `If-Match: W/"v4"`.
|
|
157
|
-
- **Atomic Concurrency Handling**:
|
|
158
|
-
```sql
|
|
159
|
-
UPDATE orders
|
|
160
|
-
SET status = :status, version = version + 1
|
|
161
|
-
WHERE id = :id AND version = :expectedVersion;
|
|
162
|
-
```
|
|
163
|
-
- If `rows_affected == 0`: Return **`409 Conflict`** with error code `CONCURRENCY_CONFLICT` and the latest entity representation.
|
|
164
|
-
|
|
165
|
-
---
|
|
166
|
-
|
|
167
|
-
## 7. API Versioning & RFC 8594 Lifecycle Deprecation
|
|
168
|
-
|
|
169
|
-
### URI Versioning Standard
|
|
170
|
-
- Standardize on explicit path versioning: `/v1/`, `/v2/`.
|
|
171
|
-
- Never introduce breaking changes within an active major version:
|
|
172
|
-
- *Non-Breaking (Permitted in `/v1/`):* Adding optional fields, adding new endpoints, adding new enum variants.
|
|
173
|
-
- *Breaking (Demands `/v2/`):* Renaming/removing fields, changing validation constraints, altering status codes.
|
|
174
|
-
|
|
175
|
-
### RFC 8594 Sunset & Deprecation Headers
|
|
176
|
-
When deprecating an endpoint, provide clients with a minimum 90-day grace period:
|
|
177
|
-
- `Deprecation: @<unix-timestamp>`: Date when the endpoint was deprecated.
|
|
178
|
-
- `Sunset: <HTTP-date>`: Absolute date when the endpoint will return `410 Gone`.
|
|
179
|
-
- `Link: </api/v2/docs>; rel="sunset"`: Link to migration documentation.
|
|
1
|
+
# API Architecture, Protocols & Communication Standards
|
|
2
|
+
|
|
3
|
+
> **Core Mandate:** Enforce standard HTTP semantics, synchronous vs. asynchronous processing (`202 Accepted`), capability metadata (`_actions`), safe mutations via idempotency keys, keyset cursor pagination, optimistic concurrency control (OCC), and RFC 8594 lifecycle versioning.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Standard HTTP Semantics & Status Codes
|
|
8
|
+
|
|
9
|
+
APIs must adhere strictly to standard HTTP semantics. Never return `200 OK` for error envelopes:
|
|
10
|
+
|
|
11
|
+
| Status Code | Semantic Purpose | When to Return |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| **`200 OK`** | Successful read or synchronous update | Standard `GET`, `PATCH`, `PUT` queries that return payloads. |
|
|
14
|
+
| **`201 Created`** | Successful resource creation | Synchronous `POST` with `Location: /api/v1/resources/:id` header. |
|
|
15
|
+
| **`202 Accepted`** | Asynchronous task accepted | Tasks exceeding latency budgets (> 1.5s) delegated to background queues. |
|
|
16
|
+
| **`204 No Content`** | Successful action with zero payload | Standard `DELETE` or empty mutation responses. |
|
|
17
|
+
| **`400 Bad Request`** | Malformed syntax or protocol violation | Unparseable JSON, invalid query parameters. |
|
|
18
|
+
| **`401 Unauthorized`** | Missing or invalid authentication | Missing, expired, or tampered JWT / API token. |
|
|
19
|
+
| **`403 Forbidden`** | Authenticated but insufficient permission | Role, tenant boundary, or policy guard denial. |
|
|
20
|
+
| **`404 Not Found`** | Resource does not exist | Unknown entity identifier (or masked tenant resource). |
|
|
21
|
+
| **`409 Conflict`** | State conflict or race condition | Concurrency mismatch (`If-Match`), unique constraint, or in-flight idempotency. |
|
|
22
|
+
| **`422 Unprocessable`** | Semantic validation failure | Schema constraint violation (RFC 7807 problem details). |
|
|
23
|
+
| **`500 Internal Error`** | Unhandled server exception | Unexpected server failure; never leak internal stack traces. |
|
|
24
|
+
|
|
25
|
+
### Subresource URL Conventions
|
|
26
|
+
- Express relational hierarchy cleanly: `/api/v1/organizations/:orgId/projects/:projectId/members`.
|
|
27
|
+
- Limit URL nesting to a maximum of 2 subresource levels; for deeper resources, access directly via canonical ID (`/api/v1/tasks/:taskId`).
|
|
28
|
+
|
|
29
|
+
### Enumeration Masking
|
|
30
|
+
- Authentication and recovery endpoints must never reveal user existence (e.g. return `"If an account exists, a recovery link has been sent"` with identical timing).
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## 2. Synchronous vs. Asynchronous Processing (`202 Accepted`)
|
|
35
|
+
|
|
36
|
+
Operations with unpredictable or long execution durations (> 1.5 seconds, such as video rendering, large PDF exports, batch imports, or complex report generation) must never block synchronous HTTP request threads:
|
|
37
|
+
|
|
38
|
+
```mermaid
|
|
39
|
+
sequenceDiagram
|
|
40
|
+
autonumber
|
|
41
|
+
actor Client
|
|
42
|
+
participant Gateway as API Gateway
|
|
43
|
+
participant Queue as Task Queue / Worker
|
|
44
|
+
|
|
45
|
+
Client->>Gateway: POST /reports/export (Long-running > 1.5s)
|
|
46
|
+
Gateway->>Queue: Dispatch background job
|
|
47
|
+
Gateway-->>Client: 202 Accepted (Location: /api/v1/tasks/tsk_123)
|
|
48
|
+
Note over Client,Gateway: Client polls GET /api/v1/tasks/tsk_123 until complete
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Protocol Standards:
|
|
52
|
+
1. Dispatch the payload to a persistent worker queue (e.g., BullMQ, Temporal, Celery).
|
|
53
|
+
2. Respond immediately with **`202 Accepted`** containing:
|
|
54
|
+
- Header: `Location: /api/v1/tasks/:taskId`
|
|
55
|
+
- Envelope:
|
|
56
|
+
```json
|
|
57
|
+
{
|
|
58
|
+
"taskId": "tsk_123",
|
|
59
|
+
"status": "QUEUED",
|
|
60
|
+
"pollIntervalMs": 2000,
|
|
61
|
+
"_links": {
|
|
62
|
+
"status": { "href": "/api/v1/tasks/tsk_123", "method": "GET" },
|
|
63
|
+
"cancel": { "href": "/api/v1/tasks/tsk_123", "method": "DELETE" }
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
3. Polling endpoint (`GET /api/v1/tasks/:taskId`) returns:
|
|
68
|
+
- In-progress: `200 OK` with status `PROCESSING` and progress percentage.
|
|
69
|
+
- Finished: `303 See Other` with `Location: /api/v1/reports/rep_789` or `200 OK` with `status: "COMPLETED"` and the final artifact URI.
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## 3. Allowed Actions & Capability Metadata (`_actions` Envelope)
|
|
74
|
+
|
|
75
|
+
Clients must not duplicate complex server-side business and authorization rules to decide whether UI actions (edit, delete, approve, cancel, refund) are permitted. **The server is the authoritative source of truth.**
|
|
76
|
+
|
|
77
|
+
### Pattern: `_actions` and `_links` Envelope
|
|
78
|
+
Every resource response must embed an `_actions` boolean map and optional `_links` hypermedia block indicating what the requesting caller is permitted to do based on their role, tenant boundaries, and the entity's current lifecycle state:
|
|
79
|
+
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"id": "ord_9876",
|
|
83
|
+
"status": "SHIPPED",
|
|
84
|
+
"totalAmount": 149.99,
|
|
85
|
+
"currency": "USD",
|
|
86
|
+
"_actions": {
|
|
87
|
+
"canEdit": false,
|
|
88
|
+
"canCancel": false,
|
|
89
|
+
"canTrack": true,
|
|
90
|
+
"canRequestRefund": true
|
|
91
|
+
},
|
|
92
|
+
"_links": {
|
|
93
|
+
"self": { "href": "/api/v1/orders/ord_9876", "method": "GET" },
|
|
94
|
+
"track": { "href": "/api/v1/orders/ord_9876/tracking", "method": "GET" },
|
|
95
|
+
"refund": { "href": "/api/v1/orders/ord_9876/refunds", "method": "POST" }
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Frontend Binding:
|
|
101
|
+
- UI action buttons directly bind visibility or disabled state to `resource._actions.canCancel`.
|
|
102
|
+
- When business logic evolves (e.g. orders over $1,000 require manager approval), only backend policy changes—zero frontend redeployment required.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## 4. Safe Mutations via Idempotency Keys (IETF Draft)
|
|
107
|
+
|
|
108
|
+
To prevent duplicate execution (double charging, duplicate orders) caused by network retries or transient connection drops:
|
|
109
|
+
|
|
110
|
+
### Protocol Standards:
|
|
111
|
+
- Clients generating mutating requests (`POST`, `PATCH`) must supply a unique `Idempotency-Key: <uuid-v4>` header.
|
|
112
|
+
- **Server Execution Lifecycle**:
|
|
113
|
+
1. Check distributed idempotency cache for key `idemp:<tenantId>:<idempotencyKey>`.
|
|
114
|
+
2. If found with status `IN_FLIGHT`: return **`409 Conflict`** (`IDEMPOTENT_OPERATION_IN_PROGRESS`).
|
|
115
|
+
3. If found with status `COMPLETED`: return the cached HTTP status code, headers, and response payload without re-executing.
|
|
116
|
+
4. If not found: Acquire distributed lock, execute mutation within an atomic database transaction, cache the response envelope with a 24-hour TTL, and release the lock.
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## 5. High-Scale Keyset / Cursor-Based Pagination
|
|
121
|
+
|
|
122
|
+
Never use offset pagination (`OFFSET 10000 LIMIT 20`) on large tables. Offsets degrade linearly ($O(N)$) and suffer from page-drift anomalies as rows are inserted or deleted.
|
|
123
|
+
|
|
124
|
+
### Specification & Envelope:
|
|
125
|
+
- Query Parameters: `?cursor=<opaque_base64>&limit=20` (default limit 20, max 100).
|
|
126
|
+
- Response Envelope:
|
|
127
|
+
```json
|
|
128
|
+
{
|
|
129
|
+
"data": [...],
|
|
130
|
+
"pagination": {
|
|
131
|
+
"nextCursor": "ZXlKaWRI...==",
|
|
132
|
+
"hasMore": true,
|
|
133
|
+
"limit": 20
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
- **Agnostic Keyset Query Pattern**:
|
|
138
|
+
```sql
|
|
139
|
+
SELECT * FROM orders
|
|
140
|
+
WHERE tenant_id = :tenantId
|
|
141
|
+
AND (created_at, id) < (:cursorCreatedAt, :cursorId)
|
|
142
|
+
ORDER BY created_at DESC, id DESC
|
|
143
|
+
LIMIT :limit + 1;
|
|
144
|
+
```
|
|
145
|
+
If `results.length > limit`, slice the extra item and encode its composite values (`created_at`, `id`) into the base64 `nextCursor`.
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## 6. Optimistic Concurrency Control (OCC)
|
|
150
|
+
|
|
151
|
+
Prevent lost-update anomalies during concurrent edits without pessimistic database row locking:
|
|
152
|
+
|
|
153
|
+
### Protocol Standards:
|
|
154
|
+
- Every mutable entity contains an incrementing integer `version` column.
|
|
155
|
+
- The server returns the current entity version in the `ETag` response header: `ETag: W/"v4"`.
|
|
156
|
+
- Clients submitting updates (`PUT`, `PATCH`) must include `If-Match: W/"v4"`.
|
|
157
|
+
- **Atomic Concurrency Handling**:
|
|
158
|
+
```sql
|
|
159
|
+
UPDATE orders
|
|
160
|
+
SET status = :status, version = version + 1
|
|
161
|
+
WHERE id = :id AND version = :expectedVersion;
|
|
162
|
+
```
|
|
163
|
+
- If `rows_affected == 0`: Return **`409 Conflict`** with error code `CONCURRENCY_CONFLICT` and the latest entity representation.
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## 7. API Versioning & RFC 8594 Lifecycle Deprecation
|
|
168
|
+
|
|
169
|
+
### URI Versioning Standard
|
|
170
|
+
- Standardize on explicit path versioning: `/v1/`, `/v2/`.
|
|
171
|
+
- Never introduce breaking changes within an active major version:
|
|
172
|
+
- *Non-Breaking (Permitted in `/v1/`):* Adding optional fields, adding new endpoints, adding new enum variants.
|
|
173
|
+
- *Breaking (Demands `/v2/`):* Renaming/removing fields, changing validation constraints, altering status codes.
|
|
174
|
+
|
|
175
|
+
### RFC 8594 Sunset & Deprecation Headers
|
|
176
|
+
When deprecating an endpoint, provide clients with a minimum 90-day grace period:
|
|
177
|
+
- `Deprecation: @<unix-timestamp>`: Date when the endpoint was deprecated.
|
|
178
|
+
- `Sunset: <HTTP-date>`: Absolute date when the endpoint will return `410 Gone`.
|
|
179
|
+
- `Link: </api/v2/docs>; rel="sunset"`: Link to migration documentation.
|
|
@@ -1,76 +1,76 @@
|
|
|
1
|
-
# Enterprise Authentication, Token Rotation & WebAuthn
|
|
2
|
-
|
|
3
|
-
> **Core Mandate:** Enforce in-memory short-lived access tokens, cryptographic Refresh Token Rotation (RTR) with family revocation on replay detection, FIDO2/WebAuthn passkeys, and OIDC federation.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 1. Token Lifecycles & Cryptographic Refresh Token Rotation (RTR)
|
|
8
|
-
|
|
9
|
-
- **Access Tokens**: Short-lived (max 15 minutes), held strictly in volatile application memory or client memory (never persisted in unencrypted browser storage). Standardize on **PASETO** (Platform-Agnostic Security Tokens) or **RFC 7519 JWT** with asymmetric RSA/EdDSA keys published via `/.well-known/jwks.json`.
|
|
10
|
-
- **Refresh Tokens**: Stored strictly in `HttpOnly`, `Secure`, `SameSite=Strict` cookies or encrypted OS keyrings.
|
|
11
|
-
- **Cryptographic Rotation & Replay Detection Protocol**:
|
|
12
|
-
- Persist only cryptographically salted hashes (e.g. SHA-256 / Argon2id) of refresh tokens in storage.
|
|
13
|
-
- Group tokens by `family_id` across rotation cycles.
|
|
14
|
-
- If an expired or already-consumed token in a family is presented (replay attack), **immediately invalidate the entire token family**, terminate active sessions, and emit a high-priority security alert.
|
|
15
|
-
|
|
16
|
-
---
|
|
17
|
-
|
|
18
|
-
## 2. FIDO2 / WebAuthn Passkeys & Multi-Factor Authentication
|
|
19
|
-
|
|
20
|
-
- **FIDO2 / WebAuthn Standard**: Support hardware security keys (YubiKey, Apple Touch ID/Face ID, Windows Hello) conforming to the W3C WebAuthn Level 3 specification.
|
|
21
|
-
- **Server Cryptographic Verification**: Validate hardware-signed cryptographic challenges against stored credential public keys using language-native WebAuthn verifier ports.
|
|
22
|
-
- **Time-Based One-Time Passwords (TOTP)**: Implement RFC 6238 compliant TOTP verification as an alternative MFA factor.
|
|
23
|
-
|
|
24
|
-
---
|
|
25
|
-
|
|
26
|
-
## 3. Enterprise Identity Federation & Workload Identity
|
|
27
|
-
|
|
28
|
-
- **OIDC & OAuth 2.1**: Standardize on OpenID Connect 1.0 Authorization Code Flow with PKCE for enterprise single sign-on (SSO) with Okta, Azure AD, Keycloak, or Google Workspace.
|
|
29
|
-
- **SCIM 2.0 Provisioning**: Implement RFC 7644 SCIM endpoints for automated tenant user synchronization and lifecycle de-provisioning.
|
|
30
|
-
- **Service-to-Service Workload Identity**: Utilize **SPIFFE / SPIRE** for zero-trust mutual TLS (mTLS) cryptographic attestation between polyglot microservices.
|
|
31
|
-
|
|
32
|
-
---
|
|
33
|
-
|
|
34
|
-
## 4. Frontend Authentication Architecture & Production UX
|
|
35
|
-
|
|
36
|
-
- **Dedicated Auth Experience**:
|
|
37
|
-
- Provide a clean, focused, professional sign-in interface (dedicated `/login` route or unpolluted modal) with zero clutter.
|
|
38
|
-
- Require formal Zod schema validation on submit and blur using React Hook Form.
|
|
39
|
-
- Enforce accessible error messaging using ARIA live regions (`role="alert"` / `aria-live="assertive"`).
|
|
40
|
-
- Include "Remember me" session persistence and "Forgot password?" recovery options.
|
|
41
|
-
- Provide a separate, dedicated registration flow (`/register`) with tenant organization initialization.
|
|
42
|
-
- **Post-Login Role-Based Redirection Matrix**:
|
|
43
|
-
- Authentication must evaluate the user's primary active role and immediately redirect to their tailored domain experience:
|
|
44
|
-
- `ADMIN`, `OPERATOR`, `MANAGER` ➔ `/` (Operator Executive Dashboard).
|
|
45
|
-
- `MEMBER`, `CONSUMER` ➔ `/portal` (Self-Service Consumer Portal).
|
|
46
|
-
- `PROSPECT`, `GUEST` ➔ `/catalog` or `/onboarding`.
|
|
47
|
-
- **Session State & Token Management**:
|
|
48
|
-
- Store short-lived access tokens strictly in memory within the frontend application context.
|
|
49
|
-
- Automatically refresh tokens in the background via `POST /api/v1/auth/refresh` using HttpOnly refresh cookies.
|
|
50
|
-
- On application mount, restore session state and memberships gracefully without flashing unauthenticated screens or crashing.
|
|
51
|
-
- **Declarative Route & Role Guards**:
|
|
52
|
-
- Wrap protected views in `<ProtectedRoute requiredRoles={[...]} fallbackUrl="...">`.
|
|
53
|
-
- Unauthenticated access redirects to `/login?returnTo=<current_url>`.
|
|
54
|
-
- Unauthorized access renders an accessible 403 Forbidden view with a "Return to My Dashboard" CTA.
|
|
55
|
-
|
|
56
|
-
---
|
|
57
|
-
|
|
58
|
-
## 5. Strict Decoupling of Developer Demo Personas from Production Authentication
|
|
59
|
-
|
|
60
|
-
- **The Toy Prototype Anti-Pattern**: Embedding test personas ("Admin Alice", "Operator Bob", "Member Charlie") directly inside user-facing login forms or modals severely compromises application credibility and confuses real users.
|
|
61
|
-
- **Mandatory Isolation**:
|
|
62
|
-
- Developer demo personas must be **100% decoupled** from production authentication.
|
|
63
|
-
- Demo personas must exist exclusively in a dedicated **Development Test Harness** (`<DevPersonaSwitcher />` or floating dev toolbar) rendered conditionally:
|
|
64
|
-
```tsx
|
|
65
|
-
// Rendered ONLY in local development or preview environments
|
|
66
|
-
if (import.meta.env.DEV) {
|
|
67
|
-
return <DevPersonaToolbar />;
|
|
68
|
-
}
|
|
69
|
-
```
|
|
70
|
-
- The Dev Toolbar must be explicitly badge-labeled: `[DEV / TEST HARNESS: Switch Role]`.
|
|
71
|
-
- When switching personas, the harness must:
|
|
72
|
-
1. Clear stale TanStack Query caches to prevent data cross-contamination.
|
|
73
|
-
2. Authenticate the selected demo persona and update auth context.
|
|
74
|
-
3. Trigger role-appropriate navigation (e.g. switching to Member navigates to `/portal`; switching to Operator navigates to `/`).
|
|
75
|
-
- **Zero Production Leaks**: In production builds (`import.meta.env.PROD`), the developer persona switcher must be tree-shaken and completely stripped from the bundle.
|
|
76
|
-
|
|
1
|
+
# Enterprise Authentication, Token Rotation & WebAuthn
|
|
2
|
+
|
|
3
|
+
> **Core Mandate:** Enforce in-memory short-lived access tokens, cryptographic Refresh Token Rotation (RTR) with family revocation on replay detection, FIDO2/WebAuthn passkeys, and OIDC federation.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Token Lifecycles & Cryptographic Refresh Token Rotation (RTR)
|
|
8
|
+
|
|
9
|
+
- **Access Tokens**: Short-lived (max 15 minutes), held strictly in volatile application memory or client memory (never persisted in unencrypted browser storage). Standardize on **PASETO** (Platform-Agnostic Security Tokens) or **RFC 7519 JWT** with asymmetric RSA/EdDSA keys published via `/.well-known/jwks.json`.
|
|
10
|
+
- **Refresh Tokens**: Stored strictly in `HttpOnly`, `Secure`, `SameSite=Strict` cookies or encrypted OS keyrings.
|
|
11
|
+
- **Cryptographic Rotation & Replay Detection Protocol**:
|
|
12
|
+
- Persist only cryptographically salted hashes (e.g. SHA-256 / Argon2id) of refresh tokens in storage.
|
|
13
|
+
- Group tokens by `family_id` across rotation cycles.
|
|
14
|
+
- If an expired or already-consumed token in a family is presented (replay attack), **immediately invalidate the entire token family**, terminate active sessions, and emit a high-priority security alert.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 2. FIDO2 / WebAuthn Passkeys & Multi-Factor Authentication
|
|
19
|
+
|
|
20
|
+
- **FIDO2 / WebAuthn Standard**: Support hardware security keys (YubiKey, Apple Touch ID/Face ID, Windows Hello) conforming to the W3C WebAuthn Level 3 specification.
|
|
21
|
+
- **Server Cryptographic Verification**: Validate hardware-signed cryptographic challenges against stored credential public keys using language-native WebAuthn verifier ports.
|
|
22
|
+
- **Time-Based One-Time Passwords (TOTP)**: Implement RFC 6238 compliant TOTP verification as an alternative MFA factor.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## 3. Enterprise Identity Federation & Workload Identity
|
|
27
|
+
|
|
28
|
+
- **OIDC & OAuth 2.1**: Standardize on OpenID Connect 1.0 Authorization Code Flow with PKCE for enterprise single sign-on (SSO) with Okta, Azure AD, Keycloak, or Google Workspace.
|
|
29
|
+
- **SCIM 2.0 Provisioning**: Implement RFC 7644 SCIM endpoints for automated tenant user synchronization and lifecycle de-provisioning.
|
|
30
|
+
- **Service-to-Service Workload Identity**: Utilize **SPIFFE / SPIRE** for zero-trust mutual TLS (mTLS) cryptographic attestation between polyglot microservices.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## 4. Frontend Authentication Architecture & Production UX
|
|
35
|
+
|
|
36
|
+
- **Dedicated Auth Experience**:
|
|
37
|
+
- Provide a clean, focused, professional sign-in interface (dedicated `/login` route or unpolluted modal) with zero clutter.
|
|
38
|
+
- Require formal Zod schema validation on submit and blur using React Hook Form.
|
|
39
|
+
- Enforce accessible error messaging using ARIA live regions (`role="alert"` / `aria-live="assertive"`).
|
|
40
|
+
- Include "Remember me" session persistence and "Forgot password?" recovery options.
|
|
41
|
+
- Provide a separate, dedicated registration flow (`/register`) with tenant organization initialization.
|
|
42
|
+
- **Post-Login Role-Based Redirection Matrix**:
|
|
43
|
+
- Authentication must evaluate the user's primary active role and immediately redirect to their tailored domain experience:
|
|
44
|
+
- `ADMIN`, `OPERATOR`, `MANAGER` ➔ `/` (Operator Executive Dashboard).
|
|
45
|
+
- `MEMBER`, `CONSUMER` ➔ `/portal` (Self-Service Consumer Portal).
|
|
46
|
+
- `PROSPECT`, `GUEST` ➔ `/catalog` or `/onboarding`.
|
|
47
|
+
- **Session State & Token Management**:
|
|
48
|
+
- Store short-lived access tokens strictly in memory within the frontend application context.
|
|
49
|
+
- Automatically refresh tokens in the background via `POST /api/v1/auth/refresh` using HttpOnly refresh cookies.
|
|
50
|
+
- On application mount, restore session state and memberships gracefully without flashing unauthenticated screens or crashing.
|
|
51
|
+
- **Declarative Route & Role Guards**:
|
|
52
|
+
- Wrap protected views in `<ProtectedRoute requiredRoles={[...]} fallbackUrl="...">`.
|
|
53
|
+
- Unauthenticated access redirects to `/login?returnTo=<current_url>`.
|
|
54
|
+
- Unauthorized access renders an accessible 403 Forbidden view with a "Return to My Dashboard" CTA.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## 5. Strict Decoupling of Developer Demo Personas from Production Authentication
|
|
59
|
+
|
|
60
|
+
- **The Toy Prototype Anti-Pattern**: Embedding test personas ("Admin Alice", "Operator Bob", "Member Charlie") directly inside user-facing login forms or modals severely compromises application credibility and confuses real users.
|
|
61
|
+
- **Mandatory Isolation**:
|
|
62
|
+
- Developer demo personas must be **100% decoupled** from production authentication.
|
|
63
|
+
- Demo personas must exist exclusively in a dedicated **Development Test Harness** (`<DevPersonaSwitcher />` or floating dev toolbar) rendered conditionally:
|
|
64
|
+
```tsx
|
|
65
|
+
// Rendered ONLY in local development or preview environments
|
|
66
|
+
if (import.meta.env.DEV) {
|
|
67
|
+
return <DevPersonaToolbar />;
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
- The Dev Toolbar must be explicitly badge-labeled: `[DEV / TEST HARNESS: Switch Role]`.
|
|
71
|
+
- When switching personas, the harness must:
|
|
72
|
+
1. Clear stale TanStack Query caches to prevent data cross-contamination.
|
|
73
|
+
2. Authenticate the selected demo persona and update auth context.
|
|
74
|
+
3. Trigger role-appropriate navigation (e.g. switching to Member navigates to `/portal`; switching to Operator navigates to `/`).
|
|
75
|
+
- **Zero Production Leaks**: In production builds (`import.meta.env.PROD`), the developer persona switcher must be tree-shaken and completely stripped from the bundle.
|
|
76
|
+
|