universal-dev-standards 5.8.0 → 5.10.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/bundled/ai/language-packs/README.md +55 -0
- package/bundled/ai/language-packs/language-pack-php-to-csharp.ai.yaml +83 -0
- package/bundled/ai/standards/behavior-snapshot.ai.yaml +122 -18
- package/bundled/ai/standards/deployment-standards.ai.yaml +108 -3
- package/bundled/ai/standards/feature-discovery-standards.ai.yaml +459 -0
- package/bundled/ai/standards/feature-manifest-standard.ai.yaml +23 -20
- package/bundled/ai/standards/mock-boundary.ai.yaml +93 -2
- package/bundled/ai/standards/multi-environment-e2e-testing.ai.yaml +250 -0
- package/bundled/ai/standards/test-completeness-dimensions.ai.yaml +39 -7
- package/bundled/ai/standards/verification-evidence.ai.yaml +30 -4
- package/bundled/locales/zh-CN/CHANGELOG.md +28 -3
- package/bundled/locales/zh-CN/README.md +1 -1
- package/bundled/locales/zh-TW/CHANGELOG.md +28 -3
- package/bundled/locales/zh-TW/README.md +1 -1
- package/package.json +4 -4
- package/src/commands/update.js +4 -1
- package/standards-registry.json +29 -5
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# UDS Language Packs
|
|
2
|
+
|
|
3
|
+
Language packs provide migration risk labels for specific source→target language pairs.
|
|
4
|
+
They extend the core `feature-manifest-standard` without polluting the core standard.
|
|
5
|
+
|
|
6
|
+
## Naming Convention
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
language-pack-<source>-to-<target>.ai.yaml
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Examples:
|
|
13
|
+
- `language-pack-php-to-csharp.ai.yaml`
|
|
14
|
+
- `language-pack-java-to-go.ai.yaml`
|
|
15
|
+
- `language-pack-python-to-rust.ai.yaml`
|
|
16
|
+
|
|
17
|
+
## Available Language Packs
|
|
18
|
+
|
|
19
|
+
| Pack | Source | Target | Labels |
|
|
20
|
+
|------|--------|--------|--------|
|
|
21
|
+
| [language-pack-php-to-csharp.ai.yaml](language-pack-php-to-csharp.ai.yaml) | PHP | C# (ASP.NET Core) | SESSION_HANDLING, ORM_DIFFERENCES, TIMEZONE_HANDLING, FILE_UPLOAD_PATH, REGEX_DIFFERENCES, ARRAY_FUNCTIONS, EXCEPTION_HIERARCHY |
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
Reference language pack risk labels in `feature-manifest.yaml` alongside generic labels:
|
|
26
|
+
|
|
27
|
+
```yaml
|
|
28
|
+
features:
|
|
29
|
+
- id: FM-001
|
|
30
|
+
name: UserLogin
|
|
31
|
+
migration_risks:
|
|
32
|
+
- SESSION_HANDLING # from language-pack-php-to-csharp
|
|
33
|
+
- NULL_SEMANTICS # from generic risks (feature-manifest-standard)
|
|
34
|
+
- ASYNC_MODEL # from generic risks
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Generic vs Language Pack Labels
|
|
38
|
+
|
|
39
|
+
| Type | Source | When to use |
|
|
40
|
+
|------|--------|-------------|
|
|
41
|
+
| Generic | `feature-manifest-standard.migration_risks.generic` | All migration projects |
|
|
42
|
+
| Language Pack | `ai/language-packs/<pack>.ai.yaml` | Specific source→target pairs |
|
|
43
|
+
|
|
44
|
+
## Creating a New Language Pack
|
|
45
|
+
|
|
46
|
+
1. Copy the structure from an existing pack
|
|
47
|
+
2. Replace `source`, `target`, and `migration_risks` with the new pair's specifics
|
|
48
|
+
3. Each risk label should have: `label`, `description`, `details` (optional but recommended)
|
|
49
|
+
4. Submit via pull request to UDS with evidence from real migration projects
|
|
50
|
+
|
|
51
|
+
## Architecture Decision
|
|
52
|
+
|
|
53
|
+
Language packs were separated from the core `feature-manifest-standard` in UDS v1.1.0
|
|
54
|
+
(XSPEC-203) to keep the core standard language-agnostic. See `ai/standards/feature-manifest-standard.ai.yaml`
|
|
55
|
+
`migration_risks.language_packs` for the extension point declaration.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Language Pack: PHP → C# (ASP.NET Core) Migration Risks
|
|
2
|
+
# Migrated from: feature-manifest-standard v1.0.0 core standard
|
|
3
|
+
# Use with: feature-manifest.yaml features[].migration_risks
|
|
4
|
+
|
|
5
|
+
language_pack:
|
|
6
|
+
id: php-to-csharp
|
|
7
|
+
source: php
|
|
8
|
+
target: csharp
|
|
9
|
+
meta:
|
|
10
|
+
version: "1.0.0"
|
|
11
|
+
updated: "2026-05-13"
|
|
12
|
+
description: PHP to C# (ASP.NET Core) migration risk labels
|
|
13
|
+
migrated_from: "feature-manifest-standard v1.0.0 migration_risks.php_to_csharp"
|
|
14
|
+
references:
|
|
15
|
+
- "XSPEC-203: Language Pack Architecture"
|
|
16
|
+
|
|
17
|
+
migration_risks:
|
|
18
|
+
- label: SESSION_HANDLING
|
|
19
|
+
description: PHP session → ASP.NET Core Session/Cookie middleware differences
|
|
20
|
+
details: |
|
|
21
|
+
PHP sessions are file-backed by default and rely on PHPSESSID cookie.
|
|
22
|
+
ASP.NET Core uses IDistributedCache (Redis/SQL) backed sessions.
|
|
23
|
+
Check: session_start(), $_SESSION usage → ISession / IDistributedCache
|
|
24
|
+
|
|
25
|
+
- label: ORM_DIFFERENCES
|
|
26
|
+
description: Eloquent ORM → Entity Framework behavioral differences (lazy loading, conventions)
|
|
27
|
+
details: |
|
|
28
|
+
Eloquent uses ActiveRecord pattern; EF Core uses DataMapper/Unit of Work.
|
|
29
|
+
Lazy loading is opt-in in EF Core (vs default in Eloquent).
|
|
30
|
+
Check: Model relationships, ->with() eager loading, timestamps conventions
|
|
31
|
+
|
|
32
|
+
- label: TIMEZONE_HANDLING
|
|
33
|
+
description: PHP timezone functions → .NET DateTimeOffset handling
|
|
34
|
+
details: |
|
|
35
|
+
PHP date() and strtotime() are timezone-sensitive via date_default_timezone_set().
|
|
36
|
+
.NET uses DateTimeOffset for timezone-aware datetimes; DateTime is ambiguous.
|
|
37
|
+
Check: date(), strtotime(), Carbon usage → DateTimeOffset, TimeZoneInfo
|
|
38
|
+
|
|
39
|
+
- label: FILE_UPLOAD_PATH
|
|
40
|
+
description: PHP $_FILES superglobal → ASP.NET Core IFormFile interface
|
|
41
|
+
details: |
|
|
42
|
+
PHP uses $_FILES superglobal with move_uploaded_file().
|
|
43
|
+
ASP.NET Core uses IFormFile with CopyToAsync() and streaming.
|
|
44
|
+
Check: $_FILES, move_uploaded_file(), file validation logic
|
|
45
|
+
|
|
46
|
+
- label: REGEX_DIFFERENCES
|
|
47
|
+
description: PHP PCRE syntax vs .NET Regex syntax differences
|
|
48
|
+
details: |
|
|
49
|
+
PHP uses PCRE with delimiters (e.g., '/pattern/i'); .NET has no delimiters.
|
|
50
|
+
Named groups: PHP (?P<name>) vs .NET (?<name>).
|
|
51
|
+
Unicode properties and some PCRE extensions differ.
|
|
52
|
+
Check: preg_match(), preg_replace(), preg_split() usage
|
|
53
|
+
|
|
54
|
+
- label: ARRAY_FUNCTIONS
|
|
55
|
+
description: PHP array_* functions → LINQ equivalents
|
|
56
|
+
details: |
|
|
57
|
+
PHP array functions are procedural; .NET uses LINQ extension methods.
|
|
58
|
+
array_map() → .Select(); array_filter() → .Where(); array_reduce() → .Aggregate()
|
|
59
|
+
array_unique() → .Distinct(); usort() → .OrderBy()
|
|
60
|
+
Check: array_map, array_filter, array_reduce, usort, array_column usage
|
|
61
|
+
|
|
62
|
+
- label: EXCEPTION_HIERARCHY
|
|
63
|
+
description: PHP exception hierarchy vs .NET exception hierarchy differences
|
|
64
|
+
details: |
|
|
65
|
+
PHP: Exception → RuntimeException → InvalidArgumentException etc.
|
|
66
|
+
.NET: Exception → SystemException / ApplicationException → specific types
|
|
67
|
+
PHP allows catching multiple types with | (PHP 8+); .NET uses catch blocks.
|
|
68
|
+
Check: try/catch blocks, custom exception classes, exception type mapping
|
|
69
|
+
|
|
70
|
+
usage_example: |
|
|
71
|
+
# In feature-manifest.yaml:
|
|
72
|
+
features:
|
|
73
|
+
- id: FM-001
|
|
74
|
+
name: UserLogin
|
|
75
|
+
migration_risks:
|
|
76
|
+
- SESSION_HANDLING # from this language pack
|
|
77
|
+
- NULL_SEMANTICS # from generic risks (feature-manifest-standard)
|
|
78
|
+
|
|
79
|
+
- id: FM-007
|
|
80
|
+
name: OrderCancellation
|
|
81
|
+
migration_risks:
|
|
82
|
+
- ORM_DIFFERENCES # from this language pack
|
|
83
|
+
- ASYNC_MODEL # from generic risks
|
|
@@ -4,38 +4,32 @@
|
|
|
4
4
|
standard:
|
|
5
5
|
id: behavior-snapshot
|
|
6
6
|
name: Behavior Snapshot Standard
|
|
7
|
-
description:
|
|
7
|
+
description: Multi-modal golden file format for migration parity verification and refactoring characterization; supports HTTP, CLI, File, and Event adapters; defines snapshot schema, parity gate, and Gate 0 protocol
|
|
8
8
|
|
|
9
9
|
meta:
|
|
10
|
-
version: "1.
|
|
11
|
-
updated: "2026-05-
|
|
10
|
+
version: "1.1.0"
|
|
11
|
+
updated: "2026-05-13"
|
|
12
12
|
source: core/behavior-snapshot.md
|
|
13
13
|
references:
|
|
14
14
|
- "XSPEC-201: Refactor/Migration Completeness Protocol"
|
|
15
|
+
- "XSPEC-203: Language Pack Architecture (multi-modal adapter extension)"
|
|
15
16
|
- "Michael Feathers: Working Effectively with Legacy Code (characterization tests)"
|
|
16
17
|
- "Golden Master Testing pattern"
|
|
17
18
|
|
|
18
19
|
snapshot_schema:
|
|
19
20
|
description: Format of a single snapshot JSON file in .snapshots/<feature-id>/<scenario>.json
|
|
20
21
|
required_fields:
|
|
22
|
+
- name: adapter
|
|
23
|
+
type: string
|
|
24
|
+
description: "Snapshot adapter type: http (default) | cli | file | event"
|
|
25
|
+
default: "http"
|
|
26
|
+
backward_compat: "Omitting adapter field is equivalent to adapter: http — existing snapshots remain valid"
|
|
21
27
|
- name: feature_id
|
|
22
28
|
type: string
|
|
23
29
|
description: FM-NNN from feature-manifest.yaml
|
|
24
30
|
- name: scenario
|
|
25
31
|
type: string
|
|
26
32
|
description: "Scenario name (snake_case): happy_path, not_found, invalid_credentials, etc."
|
|
27
|
-
- name: request
|
|
28
|
-
type: object
|
|
29
|
-
fields:
|
|
30
|
-
method: "HTTP method (GET|POST|PUT|PATCH|DELETE)"
|
|
31
|
-
path: "URL path (no base URL)"
|
|
32
|
-
headers: "Optional request headers (omit auth tokens — use placeholder)"
|
|
33
|
-
body: "Optional request body (JSON)"
|
|
34
|
-
- name: response
|
|
35
|
-
type: object
|
|
36
|
-
fields:
|
|
37
|
-
status: "HTTP status code (integer)"
|
|
38
|
-
body: "Response body (JSON object)"
|
|
39
33
|
- name: ignore_fields
|
|
40
34
|
type: list
|
|
41
35
|
description: |
|
|
@@ -43,8 +37,9 @@ standard:
|
|
|
43
37
|
Use for legitimately non-deterministic values: timestamps, tokens, IDs.
|
|
44
38
|
Do NOT use to hide business logic differences.
|
|
45
39
|
|
|
46
|
-
|
|
40
|
+
http_example: |
|
|
47
41
|
{
|
|
42
|
+
"adapter": "http",
|
|
48
43
|
"feature_id": "FM-007",
|
|
49
44
|
"scenario": "happy_path",
|
|
50
45
|
"request": {
|
|
@@ -64,18 +59,108 @@ standard:
|
|
|
64
59
|
"ignore_fields": ["refund_id", "cancelled_at"]
|
|
65
60
|
}
|
|
66
61
|
|
|
62
|
+
adapters:
|
|
63
|
+
description: Adapter schemas for different software interaction types. Choose based on how the feature interacts with the outside world.
|
|
64
|
+
|
|
65
|
+
http:
|
|
66
|
+
description: HTTP request/response adapter — for web services and REST APIs (default)
|
|
67
|
+
fields:
|
|
68
|
+
request:
|
|
69
|
+
method: "HTTP method (GET|POST|PUT|PATCH|DELETE)"
|
|
70
|
+
path: "URL path (no base URL)"
|
|
71
|
+
headers: "Optional request headers (omit auth tokens — use placeholder)"
|
|
72
|
+
body: "Optional request body (JSON)"
|
|
73
|
+
response:
|
|
74
|
+
status: "HTTP status code (integer)"
|
|
75
|
+
body: "Response body (JSON object)"
|
|
76
|
+
when_to_use: "Feature is triggered by HTTP request and returns HTTP response"
|
|
77
|
+
|
|
78
|
+
cli:
|
|
79
|
+
description: CLI tool adapter — for command-line tools, scripts, and batch processors
|
|
80
|
+
fields:
|
|
81
|
+
args: "Command arguments array (excluding the program name itself)"
|
|
82
|
+
stdin: "Standard input string (null if the command reads no stdin)"
|
|
83
|
+
stdout: "Expected standard output string"
|
|
84
|
+
stderr: "Expected standard error string (empty string if none expected)"
|
|
85
|
+
exit_code: "Expected exit code (integer: 0 = success)"
|
|
86
|
+
when_to_use: "Feature is invoked via command-line arguments and produces stdout/stderr output"
|
|
87
|
+
example: |
|
|
88
|
+
{
|
|
89
|
+
"adapter": "cli",
|
|
90
|
+
"feature_id": "FM-012",
|
|
91
|
+
"scenario": "convert_csv_to_json",
|
|
92
|
+
"args": ["convert", "--input", "data.csv", "--format", "json"],
|
|
93
|
+
"stdin": null,
|
|
94
|
+
"stdout": "{\"rows\": 42, \"status\": \"ok\"}",
|
|
95
|
+
"stderr": "",
|
|
96
|
+
"exit_code": 0,
|
|
97
|
+
"ignore_fields": []
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
file:
|
|
101
|
+
description: File I/O adapter — for batch processors, report generators, and data pipelines
|
|
102
|
+
fields:
|
|
103
|
+
input_files: "List of input file descriptors: {path, content_hash}"
|
|
104
|
+
output_files: "List of expected output file descriptors: {path, content_hash}"
|
|
105
|
+
content_hash_format: "sha256:<hex> — use fixtures for deterministic input; capture hash from reference run for expected output"
|
|
106
|
+
when_to_use: "Feature reads input files and produces output files (no HTTP or CLI interaction)"
|
|
107
|
+
example: |
|
|
108
|
+
{
|
|
109
|
+
"adapter": "file",
|
|
110
|
+
"feature_id": "FM-015",
|
|
111
|
+
"scenario": "generate_monthly_report",
|
|
112
|
+
"input_files": [
|
|
113
|
+
{ "path": "fixtures/sales_2026_04.csv", "content_hash": "sha256:abc123" }
|
|
114
|
+
],
|
|
115
|
+
"output_files": [
|
|
116
|
+
{ "path": "output/report_2026_04.pdf", "content_hash": "sha256:def456" }
|
|
117
|
+
],
|
|
118
|
+
"ignore_fields": []
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
event:
|
|
122
|
+
description: Event/message adapter — for event-driven systems, message queues, and daemons
|
|
123
|
+
fields:
|
|
124
|
+
trigger: "The triggering event or message: {type, queue/topic, payload}"
|
|
125
|
+
expected_state_changes: "List of expected database/state changes: {entity, field, from, to}"
|
|
126
|
+
expected_side_effects: "List of expected side effects using standard labels: EMAIL_SENT, QUEUE_MESSAGE_PUBLISHED, FILE_WRITTEN, HTTP_CALL_MADE"
|
|
127
|
+
when_to_use: "Feature is triggered by an event/message and produces state changes or side effects"
|
|
128
|
+
example: |
|
|
129
|
+
{
|
|
130
|
+
"adapter": "event",
|
|
131
|
+
"feature_id": "FM-020",
|
|
132
|
+
"scenario": "order_placed_triggers_inventory_deduction",
|
|
133
|
+
"trigger": {
|
|
134
|
+
"type": "message",
|
|
135
|
+
"queue": "orders.placed",
|
|
136
|
+
"payload": { "order_id": "ORD-001", "product_id": "PROD-007", "quantity": 1 }
|
|
137
|
+
},
|
|
138
|
+
"expected_state_changes": [
|
|
139
|
+
{ "entity": "inventory", "field": "quantity", "from": 10, "to": 9 }
|
|
140
|
+
],
|
|
141
|
+
"expected_side_effects": ["EMAIL_SENT", "QUEUE_MESSAGE_PUBLISHED"],
|
|
142
|
+
"ignore_fields": ["processed_at", "message_id"]
|
|
143
|
+
}
|
|
144
|
+
|
|
67
145
|
directory_structure:
|
|
68
146
|
root: ".snapshots/"
|
|
69
147
|
layout: ".snapshots/<feature-id>/<scenario>.json"
|
|
70
148
|
example: |
|
|
71
149
|
.snapshots/
|
|
72
|
-
FM-001-UserLogin/
|
|
150
|
+
FM-001-UserLogin/ ← http adapter
|
|
73
151
|
happy_path.json
|
|
74
152
|
invalid_credentials.json
|
|
75
|
-
FM-007-OrderCancellation/
|
|
153
|
+
FM-007-OrderCancellation/ ← http adapter
|
|
76
154
|
happy_path.json
|
|
77
155
|
order_not_found.json
|
|
78
156
|
MANUAL-refund_webhook.json
|
|
157
|
+
FM-012-ConvertCsv/ ← cli adapter
|
|
158
|
+
convert_csv_to_json.json
|
|
159
|
+
missing_input_file.json
|
|
160
|
+
FM-015-MonthlyReport/ ← file adapter
|
|
161
|
+
generate_monthly_report.json
|
|
162
|
+
FM-020-InventoryDeduction/ ← event adapter
|
|
163
|
+
order_placed_triggers_inventory_deduction.json
|
|
79
164
|
manual_prefix:
|
|
80
165
|
description: "Files prefixed MANUAL- contain manually authored snapshots (cannot be auto-recorded)"
|
|
81
166
|
examples:
|
|
@@ -161,6 +246,25 @@ standard:
|
|
|
161
246
|
Fix parity failures before promoting — they represent behavioral divergence.
|
|
162
247
|
priority: required
|
|
163
248
|
|
|
249
|
+
- id: adapter-selection
|
|
250
|
+
trigger: creating a behavior snapshot
|
|
251
|
+
instruction: |
|
|
252
|
+
Select the adapter matching the feature's interaction type.
|
|
253
|
+
Use http ONLY for actual HTTP endpoint features.
|
|
254
|
+
Use cli for command-line tool features.
|
|
255
|
+
Use file for batch I/O and report generation features.
|
|
256
|
+
Use event for message-driven and daemon features.
|
|
257
|
+
When in doubt about which adapter to use, refer to the adapters section's when_to_use fields.
|
|
258
|
+
priority: required
|
|
259
|
+
|
|
260
|
+
- id: backward-compatibility
|
|
261
|
+
trigger: reading existing snapshot files without adapter field
|
|
262
|
+
instruction: |
|
|
263
|
+
Treat snapshot files missing the adapter field as adapter=http.
|
|
264
|
+
Do NOT require migration of existing snapshot files to add adapter field.
|
|
265
|
+
New snapshots should always include the adapter field explicitly.
|
|
266
|
+
priority: required
|
|
267
|
+
|
|
164
268
|
related_standards:
|
|
165
269
|
- feature-manifest-standard.ai.yaml
|
|
166
270
|
- acceptance-criteria-traceability.ai.yaml
|
|
@@ -12,10 +12,13 @@ standard:
|
|
|
12
12
|
- "Automate build, test, deploy, and rollback"
|
|
13
13
|
|
|
14
14
|
meta:
|
|
15
|
-
version: "1.
|
|
16
|
-
updated: "2026-
|
|
15
|
+
version: "1.1.0"
|
|
16
|
+
updated: "2026-05-13"
|
|
17
17
|
source: core/deployment-standards.md
|
|
18
|
-
description:
|
|
18
|
+
description: >
|
|
19
|
+
Safe deployment strategies, feature flags, rollback, environment parity, and DORA metrics.
|
|
20
|
+
v1.1.0: Added environment stratification responsibility matrix and stub server CI/CD
|
|
21
|
+
lifecycle rules (XSPEC-204).
|
|
19
22
|
|
|
20
23
|
principles:
|
|
21
24
|
core:
|
|
@@ -125,6 +128,108 @@ checklist:
|
|
|
125
128
|
medium_term_24hr: ["Batch jobs successful", "Data consistency verified", "No memory leaks"]
|
|
126
129
|
long_term_1wk: ["Flag cleanup scheduled", "Retrospective completed", "Docs updated"]
|
|
127
130
|
|
|
131
|
+
# ─────────────────────────────────────────────────────────
|
|
132
|
+
# Environment Stratification Responsibility Matrix (v1.1.0)
|
|
133
|
+
# ─────────────────────────────────────────────────────────
|
|
134
|
+
environment_stratification_matrix:
|
|
135
|
+
rule: >
|
|
136
|
+
Projects with external dependencies MUST build an environment stratification
|
|
137
|
+
responsibility matrix at test-planning time (not at release candidate review).
|
|
138
|
+
This matrix answers: "Which test flows can be fully verified in which environment?"
|
|
139
|
+
when_required: "Any project with external service dependencies (SMS, payment, IdP, messaging, etc.)"
|
|
140
|
+
where: "docs/testing/environment-stratification-matrix.md or in the test plan"
|
|
141
|
+
|
|
142
|
+
template: |
|
|
143
|
+
## Environment Stratification Responsibility Matrix
|
|
144
|
+
|
|
145
|
+
| Flow / Feature | local UAT | Remote UAT | PRD |
|
|
146
|
+
|------------------------|:----------------:|:----------------:|:------------------:|
|
|
147
|
+
| Auth / Login | ✅ stub IdP | ✅ Keycloak/AD | ✅ Enterprise IdP |
|
|
148
|
+
| SMS Sending | ⚠️ L2-stub | ❌ / ⚠️ | ✅ Real + billing |
|
|
149
|
+
| Payment / Purchase | ⚠️ L2-stub | ⚠️ network-dep | ✅ Real + reconcile|
|
|
150
|
+
| User / Dept Management | ✅ | ✅ cross-machine | ✅ |
|
|
151
|
+
| Background Jobs | ✅ in-process | ✅ | ✅ |
|
|
152
|
+
|
|
153
|
+
Legend:
|
|
154
|
+
✅ Full E2E verification possible
|
|
155
|
+
⚠️ Flow passes through stub/mock — real-world dimensions NOT verified
|
|
156
|
+
❌ Cannot test in this environment layer
|
|
157
|
+
|
|
158
|
+
### PRD-only verification items (must plan PRD smoke test coverage)
|
|
159
|
+
- SMS billing correctness
|
|
160
|
+
- Payment real debit + bank reconciliation
|
|
161
|
+
- Enterprise AD group sync behavior
|
|
162
|
+
|
|
163
|
+
mandatory_rule: >
|
|
164
|
+
This matrix MUST be reviewed at test planning stage alongside
|
|
165
|
+
acceptance-criteria-traceability. It is NOT acceptable to discover
|
|
166
|
+
PRD-only verification items for the first time during release candidate review.
|
|
167
|
+
|
|
168
|
+
# ─────────────────────────────────────────────────────────
|
|
169
|
+
# Stub Server CI/CD Lifecycle Rules (v1.1.0)
|
|
170
|
+
# ─────────────────────────────────────────────────────────
|
|
171
|
+
stub_server_cicd_rules:
|
|
172
|
+
rationale: >
|
|
173
|
+
Production CI/CD artifacts commonly exclude stub server directories for valid
|
|
174
|
+
security reasons (e.g., MockSoap/, tests/stub-server/ excluded from build.ps1).
|
|
175
|
+
Without explicit rules, this creates an undocumented "UAT cannot test X" situation
|
|
176
|
+
that is discovered too late in the release cycle.
|
|
177
|
+
|
|
178
|
+
build_time:
|
|
179
|
+
rules:
|
|
180
|
+
- "Production artifact MUST exclude all stub server code directories"
|
|
181
|
+
- "Exclusion rule MUST be documented in docs/uat/STUB-EXCLUSION-RATIONALE.md"
|
|
182
|
+
- "CI build verification step MUST confirm stub directories are absent from artifact"
|
|
183
|
+
example_ps1: |
|
|
184
|
+
# build.ps1 — explicit exclusion with documentation comment
|
|
185
|
+
# Stub server excluded from production artifact (see docs/uat/STUB-EXCLUSION-RATIONALE.md)
|
|
186
|
+
# Consequence: UAT machine cannot run SMS/MMS flow without sidecar deployment (see Option A below)
|
|
187
|
+
$exclude = @("MockSoap", "tests/stub-server", "test-fixtures")
|
|
188
|
+
|
|
189
|
+
uat_deployment:
|
|
190
|
+
rule: "Choose Option A or Option B; document the choice; do NOT leave it undocumented"
|
|
191
|
+
options:
|
|
192
|
+
option_a_sidecar_deploy:
|
|
193
|
+
name: "Sidecar Deployment (Recommended)"
|
|
194
|
+
description: >
|
|
195
|
+
Stub server deployed as separate process to UAT machine;
|
|
196
|
+
application configured via env var to reach the stub endpoint.
|
|
197
|
+
benefit: "Decoupled from app artifact; independently updatable"
|
|
198
|
+
example_github_actions: |
|
|
199
|
+
deploy-stub-server:
|
|
200
|
+
environment: uat
|
|
201
|
+
steps:
|
|
202
|
+
- name: Deploy stub server to UAT
|
|
203
|
+
run: |
|
|
204
|
+
ssh uat-machine "cd /opt/stub-server && pm2 start server.js --name stub-server"
|
|
205
|
+
- name: Configure app to use stub
|
|
206
|
+
run: echo "SMS_ENDPOINT=http://uat-machine:9999/soap" >> $GITHUB_ENV
|
|
207
|
+
example_gitlab_ci: |
|
|
208
|
+
deploy-stub-server:
|
|
209
|
+
stage: deploy
|
|
210
|
+
environment: uat
|
|
211
|
+
script:
|
|
212
|
+
- ssh uat-machine "pm2 start tests/stub-server/server.js --name stub-server"
|
|
213
|
+
only: [uat-branch, tags]
|
|
214
|
+
|
|
215
|
+
option_b_prd_smoke_deferral:
|
|
216
|
+
name: "PRD Smoke Deferral"
|
|
217
|
+
description: >
|
|
218
|
+
Document which flows cannot be tested in UAT; explicitly mark them as
|
|
219
|
+
PRD-smoke-only items. These items must appear in the environment stratification matrix.
|
|
220
|
+
requirement: "Must be reflected as ❌ in environment stratification matrix with PRD smoke plan"
|
|
221
|
+
|
|
222
|
+
prd_prohibitions:
|
|
223
|
+
- "MUST NOT deploy or run stub servers in PRD environment"
|
|
224
|
+
- "MUST NOT include stub server code in PRD artifact"
|
|
225
|
+
- "MUST NOT allow network access to stub server endpoints from PRD"
|
|
226
|
+
|
|
227
|
+
forbidden_state: >
|
|
228
|
+
It is NEVER acceptable to have "no stub server AND no real service AND no documented
|
|
229
|
+
deferral" for a testable flow. Every flow must be either:
|
|
230
|
+
(a) fully testable in UAT via real service or Level 2 stub server, OR
|
|
231
|
+
(b) explicitly documented as PRD-smoke-only with a smoke test plan.
|
|
232
|
+
|
|
128
233
|
physical_spec:
|
|
129
234
|
type: custom_script
|
|
130
235
|
validator:
|