micro-contracts 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +351 -0
  3. package/dist/cli/templates.d.ts +16 -0
  4. package/dist/cli/templates.d.ts.map +1 -0
  5. package/dist/cli/templates.js +377 -0
  6. package/dist/cli/templates.js.map +1 -0
  7. package/dist/cli.d.ts +9 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +978 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/generator/dependencyGenerator.d.ts +43 -0
  12. package/dist/generator/dependencyGenerator.d.ts.map +1 -0
  13. package/dist/generator/dependencyGenerator.js +159 -0
  14. package/dist/generator/dependencyGenerator.js.map +1 -0
  15. package/dist/generator/domainGenerator.d.ts +16 -0
  16. package/dist/generator/domainGenerator.d.ts.map +1 -0
  17. package/dist/generator/domainGenerator.js +212 -0
  18. package/dist/generator/domainGenerator.js.map +1 -0
  19. package/dist/generator/index.d.ts +37 -0
  20. package/dist/generator/index.d.ts.map +1 -0
  21. package/dist/generator/index.js +747 -0
  22. package/dist/generator/index.js.map +1 -0
  23. package/dist/generator/linter.d.ts +24 -0
  24. package/dist/generator/linter.d.ts.map +1 -0
  25. package/dist/generator/linter.js +202 -0
  26. package/dist/generator/linter.js.map +1 -0
  27. package/dist/generator/overlayProcessor.d.ts +90 -0
  28. package/dist/generator/overlayProcessor.d.ts.map +1 -0
  29. package/dist/generator/overlayProcessor.js +532 -0
  30. package/dist/generator/overlayProcessor.js.map +1 -0
  31. package/dist/generator/schemaGenerator.d.ts +10 -0
  32. package/dist/generator/schemaGenerator.d.ts.map +1 -0
  33. package/dist/generator/schemaGenerator.js +299 -0
  34. package/dist/generator/schemaGenerator.js.map +1 -0
  35. package/dist/generator/templateProcessor.d.ts +178 -0
  36. package/dist/generator/templateProcessor.d.ts.map +1 -0
  37. package/dist/generator/templateProcessor.js +607 -0
  38. package/dist/generator/templateProcessor.js.map +1 -0
  39. package/dist/generator/typeGenerator.d.ts +9 -0
  40. package/dist/generator/typeGenerator.d.ts.map +1 -0
  41. package/dist/generator/typeGenerator.js +395 -0
  42. package/dist/generator/typeGenerator.js.map +1 -0
  43. package/dist/guardrails/allowlist.d.ts +45 -0
  44. package/dist/guardrails/allowlist.d.ts.map +1 -0
  45. package/dist/guardrails/allowlist.js +261 -0
  46. package/dist/guardrails/allowlist.js.map +1 -0
  47. package/dist/guardrails/config.d.ts +40 -0
  48. package/dist/guardrails/config.d.ts.map +1 -0
  49. package/dist/guardrails/config.js +174 -0
  50. package/dist/guardrails/config.js.map +1 -0
  51. package/dist/guardrails/docs.d.ts +24 -0
  52. package/dist/guardrails/docs.d.ts.map +1 -0
  53. package/dist/guardrails/docs.js +138 -0
  54. package/dist/guardrails/docs.js.map +1 -0
  55. package/dist/guardrails/drift.d.ts +23 -0
  56. package/dist/guardrails/drift.d.ts.map +1 -0
  57. package/dist/guardrails/drift.js +127 -0
  58. package/dist/guardrails/drift.js.map +1 -0
  59. package/dist/guardrails/index.d.ts +19 -0
  60. package/dist/guardrails/index.d.ts.map +1 -0
  61. package/dist/guardrails/index.js +25 -0
  62. package/dist/guardrails/index.js.map +1 -0
  63. package/dist/guardrails/lint.d.ts +20 -0
  64. package/dist/guardrails/lint.d.ts.map +1 -0
  65. package/dist/guardrails/lint.js +274 -0
  66. package/dist/guardrails/lint.js.map +1 -0
  67. package/dist/guardrails/manifest.d.ts +43 -0
  68. package/dist/guardrails/manifest.d.ts.map +1 -0
  69. package/dist/guardrails/manifest.js +231 -0
  70. package/dist/guardrails/manifest.js.map +1 -0
  71. package/dist/guardrails/runner.d.ts +31 -0
  72. package/dist/guardrails/runner.d.ts.map +1 -0
  73. package/dist/guardrails/runner.js +268 -0
  74. package/dist/guardrails/runner.js.map +1 -0
  75. package/dist/guardrails/security.d.ts +31 -0
  76. package/dist/guardrails/security.d.ts.map +1 -0
  77. package/dist/guardrails/security.js +181 -0
  78. package/dist/guardrails/security.js.map +1 -0
  79. package/dist/guardrails/typecheck.d.ts +15 -0
  80. package/dist/guardrails/typecheck.d.ts.map +1 -0
  81. package/dist/guardrails/typecheck.js +104 -0
  82. package/dist/guardrails/typecheck.js.map +1 -0
  83. package/dist/guardrails/types.d.ts +196 -0
  84. package/dist/guardrails/types.d.ts.map +1 -0
  85. package/dist/guardrails/types.js +8 -0
  86. package/dist/guardrails/types.js.map +1 -0
  87. package/dist/index.d.ts +7 -0
  88. package/dist/index.d.ts.map +1 -0
  89. package/dist/index.js +7 -0
  90. package/dist/index.js.map +1 -0
  91. package/dist/types.d.ts +489 -0
  92. package/dist/types.d.ts.map +1 -0
  93. package/dist/types.js +297 -0
  94. package/dist/types.js.map +1 -0
  95. package/docs/architecture.svg +226 -0
  96. package/docs/development-guardrails.md +541 -0
  97. package/docs/guardrails-concept.svg +252 -0
  98. package/docs/overlays-deep-dive.md +298 -0
  99. package/package.json +66 -0
@@ -0,0 +1,541 @@
1
+ # Development Guardrails (AI-ready)
2
+
3
+ This document defines **guardrails for AI-assisted and human development**. The guardrails are designed to prevent "diff explosion", keep contracts authoritative, and make changes **machine-verifiable**.
4
+
5
+ The key idea is to separate the system into two layers:
6
+
7
+ - **Tooling (shipped as code / reusable)**: deterministic checks and generators that run locally and in CI and return a clear pass/fail.
8
+ - **Operations (configured in CI / repo policy)**: GitHub configuration (workflows, branch protection, rulesets, approvals) that **enforces** the tooling and protects the guardrails themselves.
9
+
10
+ > The guardrails must not depend on *who* wrote the change (human/AI). They depend only on *what* changed and whether it satisfies the contract.
11
+
12
+ ---
13
+
14
+ ## Table of Contents
15
+
16
+ 1. [Gate Overview](#gate-overview)
17
+ 2. [Available Checks](#available-checks)
18
+ 3. [Configuration](#configuration)
19
+ 4. [Operations (CI / Repo Policy)](#operations-ci--repo-policy)
20
+ 5. [Developer Workflow](#developer-workflow)
21
+ 6. [Appendix: CI Configuration](#appendix-ci-configuration)
22
+
23
+ ---
24
+
25
+ ## Gate Overview
26
+
27
+ The following diagram illustrates the overall architecture of the guardrails system:
28
+
29
+ ![AI-Driven Development Guardrails Concept](./guardrails-concept.svg)
30
+
31
+ ### Gate Summary
32
+
33
+ | Gate | Name | Scope | What it prevents |
34
+ |------|------|-------|------------------|
35
+ | **1** | Change Allowlist | repo-wide | Editing protected/generated areas directly |
36
+ | **2** | OpenAPI Spec Validation | `spec/**` | Invalid specs, bad extensions, breaking changes |
37
+ | **3** | Generated Artifact Integrity | `packages/**`, `*.generated.*` | Hand-editing generated code, drift, tampering |
38
+ | **4** | Code Quality | `server/**`, `frontend/**` | Type errors, lint issues, failing tests |
39
+ | **5** | Doc & Architectural Consistency | `docs/**`, all code | Doc/code mismatch, broken references, architecture drift |
40
+
41
+ ---
42
+
43
+ ## Available Checks
44
+
45
+ Checks are divided into two categories:
46
+
47
+ - **Built-in**: Core checks implemented in `micro-contracts` CLI (allowlist, drift, manifest)
48
+ - **Custom**: User-defined commands in `micro-contracts.guardrails.yaml` (`checks:` section)
49
+
50
+ ### Check Command Options
51
+
52
+ ```bash
53
+ micro-contracts check [options]
54
+
55
+ Options:
56
+ --only <checks> Run only specific checks (comma-separated)
57
+ --skip <checks> Skip specific checks (comma-separated)
58
+ --gate <gates> Run checks for specific gates only (comma-separated, 1-5)
59
+ -v, --verbose Enable verbose output (groups by gate)
60
+ --fix Auto-fix issues where possible
61
+ -g, --guardrails <path> Path to guardrails.yaml
62
+ -d, --generated-dir <path> Path to generated files directory (default: "packages/")
63
+ --changed-files <path> Path to file containing list of changed files (for CI)
64
+ --list List available checks with gate assignments
65
+ --list-gates List available gates
66
+ ```
67
+
68
+ **Examples:**
69
+
70
+ ```bash
71
+ # Run all checks
72
+ micro-contracts check
73
+
74
+ # Run only Gate 1 and 2 checks
75
+ micro-contracts check --gate 1,2
76
+
77
+ # Run Gate 3 checks with verbose output (grouped by gate)
78
+ micro-contracts check --gate 3 -v
79
+
80
+ # Run specific checks by name
81
+ micro-contracts check --only allowlist,drift
82
+
83
+ # List all checks with their gate assignments
84
+ micro-contracts check --list
85
+
86
+ # List available gates
87
+ micro-contracts check --list-gates
88
+ ```
89
+
90
+ ### Gate 1: Change Allowlist
91
+
92
+ Prevents unauthorized edits to protected/generated areas.
93
+
94
+ | Check | Type | Description | Local Command | CI Job |
95
+ |-------|------|-------------|---------------|--------|
96
+ | Allowlist | built-in | Block **direct** edits to `packages/**`, `*.generated.*`; require approval for `.github/**` | `micro-contracts check --only allowlist` | `allowlist` |
97
+
98
+ Files are categorized into three groups:
99
+
100
+ | Category | Examples | Who can edit |
101
+ |----------|----------|--------------|
102
+ | `allowed` | `spec/**/*.yaml`, `server/src/**/domains/**` | Anyone (AI or human) |
103
+ | `protected` | `.github/**`, `spec/spectral.yaml`, `server/src/_shared/overlays/**` | Requires CODEOWNERS approval |
104
+ | `generated` | `packages/**`, `*.generated.*` | Only via `generate` command |
105
+
106
+ Protected files include:
107
+ - CI/workflow definitions (`.github/**`) — guardrail bypass prevention
108
+ - Spectral lint rules (`spec/spectral.yaml`) — security rule tampering
109
+ - Shared overlay implementations (`server/src/_shared/overlays/**`) — security logic
110
+
111
+ ### Gate 2: OpenAPI Spec Validation
112
+
113
+ Validates OpenAPI specs before generation.
114
+
115
+ | Check | Type | Description | Local Command | CI Job |
116
+ |-------|------|-------------|---------------|--------|
117
+ | Spec lint | custom | OpenAPI schema + micro-contracts extensions (Spectral) | `micro-contracts check --only spec-lint` | `spec-lint` |
118
+ | Breaking changes | custom | API compatibility check (oasdiff) | `micro-contracts check --only spec-breaking` | `spec-breaking` |
119
+
120
+ **Spec lint** — Validates via Spectral ruleset:
121
+ - OpenAPI 3.x structure (required fields, JSON Schema, `$ref` resolution)
122
+ - micro-contracts extensions (`x-micro-contracts-domain`, `x-micro-contracts-method`)
123
+ - Security extensions (`x-auth`, `x-authz`) if required
124
+
125
+ **Breaking changes** — Detects backward-incompatible changes:
126
+ - Removed endpoints or parameters
127
+ - Changed response schemas
128
+ - Modified required fields
129
+
130
+ ### Generator
131
+
132
+ Transforms `spec/**` → `packages/**`.
133
+
134
+ | Command | Description |
135
+ |---------|-------------|
136
+ | `micro-contracts generate` | Generate contracts from OpenAPI specs |
137
+
138
+ ### Gate 3: Generated Artifact Integrity
139
+
140
+ Ensures generated code matches spec and hasn't been tampered.
141
+
142
+ > **Why commit generated artifacts?** CI re-runs `generate` and compares against committed files to detect tampering or drift. Without committed artifacts, there's no baseline to verify.
143
+
144
+ | Check | Type | Description | Local Command | CI Job |
145
+ |-------|------|-------------|---------------|--------|
146
+ | Drift | built-in | `git diff packages/` must be clean | `micro-contracts check --only drift` | `drift` |
147
+ | Manifest | built-in | SHA-256 hash verification | `micro-contracts check --only manifest` | `manifest` |
148
+ | Package typecheck | custom | Generated packages compile (`tsc`) | `micro-contracts check --only package-typecheck` | `package-typecheck` |
149
+ | Project rules | custom | Project-specific Spectral rules on **generated** spec | `micro-contracts check --only spec-project` | `spec-project` |
150
+ | Published breaking | custom | Breaking changes vs **published** contract (oasdiff) | `micro-contracts check --only spec-breaking-published` | `spec-breaking-published` |
151
+
152
+ > **Why spec checks in Gate 3?** `spec-project` and `spec-breaking-published` validate the **generated/bundled** spec output, not the source. They run after generation to verify the published contract.
153
+
154
+ **Drift check** — After running `generate`, `packages/**` must match committed state:
155
+ ```bash
156
+ git diff --exit-code packages/
157
+ ```
158
+
159
+ **Manifest verification** — `packages/.generated-manifest.json` stores:
160
+ - SHA-256 hashes of all generated files
161
+ - Generator version used
162
+ - Source spec file references
163
+
164
+ **Package typecheck** — Generated TypeScript must compile without errors.
165
+
166
+ ### Gate 4: Code Quality
167
+
168
+ Validates implementation code quality.
169
+
170
+ | Check | Type | Description | Local Command | CI Job |
171
+ |-------|------|-------------|---------------|--------|
172
+ | TypeScript lint | custom | ESLint rules | `micro-contracts check --only code-lint` | `code-lint` |
173
+ | Type check | custom | TypeScript compilation (`tsc --noEmit`) | `micro-contracts check --only code-typecheck` | `code-typecheck` |
174
+ | Unit tests | custom | Test suite execution | `micro-contracts check --only code-test` | `code-test` |
175
+ | Format check | custom | Prettier formatting | `micro-contracts check --only code-format` | `code-format` |
176
+
177
+ ### Gate 5: Doc & Architectural Consistency
178
+
179
+ Ensures documentation and architecture stay in sync.
180
+
181
+ | Check | Type | Description | Local Command | CI Job |
182
+ |-------|------|-------------|---------------|--------|
183
+ | Markdown sync | custom | Code snippets in docs (embedoc) | `micro-contracts check --only docs-sync` | `docs-sync` |
184
+ | Links validity | custom | Broken link detection | `micro-contracts check --only docs-links` | `docs-links` |
185
+ | Architectural integrity | external | Static analysis (CodeQL) | GitHub CodeQL Action | `codeql` |
186
+
187
+ **Architectural integrity (CodeQL)** — Static analysis verifies:
188
+ - HTTP entry points reach security overlays
189
+ - Transaction boundaries are respected
190
+ - Domain symbols resolve correctly
191
+ - No direct HTTP calls outside generated client
192
+
193
+ ---
194
+
195
+ ## Configuration
196
+
197
+ ### micro-contracts.guardrails.yaml
198
+
199
+ <!--@embedoc:code_snippet file="../examples/micro-contracts.guardrails.yaml" lang="yaml" title="micro-contracts.guardrails.yaml (example)"-->
200
+ **micro-contracts.guardrails.yaml (example)**
201
+
202
+ ```yaml
203
+ # AI-Driven Development Guardrails Configuration
204
+ #
205
+ # This file defines which files can be modified in normal development PRs.
206
+ # Patterns use gitignore-style matching with glob patterns.
207
+ # Prefix with ! to negate (exclude) a pattern.
208
+
209
+ # Files that can be edited in normal development PRs
210
+ allowed:
211
+ # OpenAPI specs (source of truth)
212
+ - spec/**/openapi/*.yaml
213
+ - spec/**/templates/*.hbs
214
+
215
+ # Domain implementations (human-written)
216
+ - server/src/**/domains/**/*.ts
217
+ - server/src/**/container.ts
218
+ - server/src/server.ts
219
+
220
+ # Module-specific overlays (NOT _shared)
221
+ - server/src/*/overlays/**/*.ts
222
+ - "!server/src/_shared/overlays/**"
223
+
224
+ # Configuration
225
+ - micro-contracts.config.yaml
226
+ - package.json
227
+ - tsconfig.json
228
+
229
+ # Documentation
230
+ - docs/**/*.md
231
+ - README.md
232
+
233
+ # Files that require special approval
234
+ protected:
235
+ # Spectral lint rules
236
+ - spec/spectral.yaml
237
+ - spec/_shared/spectral.yaml
238
+
239
+ # Shared overlay definitions
240
+ - spec/_shared/overlays/**
241
+
242
+ # Shared security overlay implementations
243
+ - server/src/_shared/overlays/**
244
+
245
+ # This guardrails configuration
246
+ - micro-contracts.guardrails.yaml
247
+
248
+ # CI/workflow definitions
249
+ - .github/**
250
+
251
+ # Generated artifacts (committed, but only modified via generate)
252
+ generated:
253
+ # Contract packages
254
+ - packages/**
255
+
256
+ # Generated files
257
+ - "**/*.generated.ts"
258
+ - "**/*.generated.yaml"
259
+ - "**/*.generated.yml"
260
+
261
+ # Check command configurations
262
+ # Define custom commands for each guardrail check
263
+ #
264
+ # Based on guardrails-concept.svg:
265
+ #
266
+ # Gate 1: Change Allowlist
267
+ # - allowlist (built-in): packages/** edit blocked, *.generated.* edit blocked
268
+ #
269
+ # Gate 2: OpenAPI Contract Validation (Spectral)
270
+ # - spec-lint: Schema Validity, x-security Required, x-auth Declaration
271
+ # - spec-breaking: Breaking Changes detection (oasdiff)
272
+ #
273
+ # Gate 3: Generated Artifact Integrity
274
+ # - drift (built-in): git diff packages/**
275
+ # - manifest (built-in): SHA-256 verification
276
+ # - package-typecheck: Generated package type check
277
+ #
278
+ # Gate 4: Code Quality
279
+ # - code-lint: TypeScript Lint (ESLint)
280
+ # - code-typecheck: Type Check (tsc)
281
+ # - code-test: Unit Tests
282
+ #
283
+ # Gate 5: Doc Consistency & Static Analysis
284
+ # - docs-sync: Markdown Sync (embedoc)
285
+ # - docs-links: Links Valid
286
+ # - security (built-in): CodeQL static analysis
287
+ #
288
+ # Placeholders:
289
+ # {files} - space-separated list of target files (auto-detected)
290
+ # {cwd} - current working directory
291
+
292
+ checks:
293
+ # ==========================================
294
+ # Gate 2: OpenAPI Contract Validation
295
+ # ==========================================
296
+ # Schema Validity, x-security Required, x-auth Declaration, Description Check
297
+ spec-lint:
298
+ command: "npx @stoplight/spectral-cli lint {files} --ruleset spec/spectral.yaml"
299
+ gate: 2
300
+
301
+ # Breaking Changes detection (oasdiff)
302
+ # Compare current spec against main branch
303
+ # Uses bundled spec to resolve $refs properly
304
+ #
305
+ # NOTE: Replace the base path with your actual generated spec location:
306
+ # Recommended: main:packages/contract/<module>/docs/openapi.generated.yaml
307
+ # Example below uses: main:examples/packages/... (for this repo's structure)
308
+ spec-breaking:
309
+ command: "bash -c 'npx @redocly/cli bundle spec/core/openapi/core.yaml -o /tmp/current.yaml && git show main:examples/packages/contract/core/docs/openapi.generated.yaml > /tmp/base.yaml 2>/dev/null && oasdiff breaking /tmp/base.yaml /tmp/current.yaml --fail-on ERR || echo \"No base spec found (new file)\"'"
310
+ gate: 2
311
+
312
+ # ==========================================
313
+ # Gate 3: Generated Artifact Integrity
314
+ # ==========================================
315
+ # drift, manifest are built-in checks (gate: 3)
316
+
317
+ # Generated package type check
318
+ package-typecheck:
319
+ command: "cd packages/contract && npx tsc --noEmit"
320
+ gate: 3
321
+
322
+ # ==========================================
323
+ # Gate 4: Code Quality
324
+ # ==========================================
325
+ # TypeScript Lint (ESLint)
326
+ code-lint:
327
+ command: "cd server && npx eslint src/ --ext .ts && cd ../frontend && npx eslint src/ --ext .ts,.tsx"
328
+ gate: 4
329
+
330
+ # Type Check (tsc)
331
+ code-typecheck:
332
+ command: "cd server && npx tsc --noEmit && cd ../frontend && npx tsc --noEmit"
333
+ gate: 4
334
+
335
+ # Unit Tests
336
+ code-test:
337
+ command: "cd server && npm test && cd ../frontend && npm test"
338
+ gate: 4
339
+ enabled: false # Enable when tests are set up
340
+
341
+ # ==========================================
342
+ # Gate 5: Doc Consistency & Static Analysis
343
+ # ==========================================
344
+ # Markdown Sync (embedoc) - regenerate and check for drift
345
+ docs-sync:
346
+ command: "npx embedoc build && git diff --exit-code docs/"
347
+ gate: 5
348
+ enabled: false # Enable when docs/ directory exists
349
+
350
+ # Links Valid - verify documentation references
351
+ docs-links:
352
+ command: "node scripts/verify-doc-consistency.mjs"
353
+ gate: 5
354
+ enabled: false # Enable when scripts/verify-doc-consistency.mjs exists
355
+
356
+ ```
357
+
358
+ 📄 Source: [`micro-contracts.guardrails.yaml`](../examples/micro-contracts.guardrails.yaml) (lines full)
359
+ <!--@embedoc:end-->
360
+
361
+ ### Manifest Format
362
+
363
+ The `micro-contracts generate` command creates `packages/.generated-manifest.json`:
364
+
365
+ ```json
366
+ {
367
+ "version": "1.0.0",
368
+ "generatedAt": "2024-01-15T10:30:00Z",
369
+ "generatorVersion": "1.2.3",
370
+ "files": {
371
+ "contract/core/schemas/types.ts": {
372
+ "sha256": "a1b2c3d4e5f6...",
373
+ "source": "spec/core/openapi/core.yaml"
374
+ }
375
+ }
376
+ }
377
+ ```
378
+
379
+ ---
380
+
381
+ ## Operations (CI / Repo Policy)
382
+
383
+ ### Pinned Generator (Supply Chain Boundary)
384
+
385
+ CI must run the generator via **pinned `npx`** to prevent local tampering:
386
+
387
+ ```bash
388
+ npx --yes -p micro-contracts@${MICRO_CONTRACTS_VERSION} micro-contracts generate
389
+ npx --yes -p micro-contracts@${MICRO_CONTRACTS_VERSION} micro-contracts check
390
+ ```
391
+
392
+ ### Protecting `.github/**`
393
+
394
+ - Feature branches MUST NOT modify `.github/**`
395
+ - Changes require dedicated "infra PR" with CODEOWNERS approval
396
+ - **Rationale**: CI definition is part of the guardrail
397
+
398
+ ### Required Status Checks
399
+
400
+ `main` branch protection must require these **2 job names**:
401
+
402
+ | Job | Gates covered | What it runs |
403
+ |-----|---------------|--------------|
404
+ | `guardrails` | 1–5 | allowlist → spec-lint → spec-breaking → generate → drift → manifest → code checks → docs checks |
405
+ | `codeql` | 5 | Static analysis (CodeQL) |
406
+
407
+ > **Tip**: If you need finer control, split into per-gate jobs (`gate-1`, `gate-2`, etc.) and require each.
408
+
409
+ ### CODEOWNERS
410
+
411
+ | Path | Owner | Reason |
412
+ |------|-------|--------|
413
+ | `spec/spectral.yaml` | security/platform | Lint rules |
414
+ | `server/src/_shared/overlays/**` | security/platform | Security logic |
415
+ | `micro-contracts.guardrails.yaml` | security/platform | Guardrail config |
416
+ | `.github/**` | infra/maintainer | CI definitions |
417
+
418
+ ---
419
+
420
+ ## Developer Workflow
421
+
422
+ ### Normal feature PR
423
+
424
+ 1. Edit only `allowed` paths
425
+ 2. If you change `spec/**`, run `generate`
426
+ 3. Run `check` locally
427
+ 4. Open PR → CI must pass
428
+
429
+ ### Spec change
430
+
431
+ 1. Update `spec/**/openapi/*.yaml`
432
+ 2. Run `generate` (updates `packages/**`)
433
+ 3. Run `check`
434
+ 4. If oasdiff reports breaking changes, require explicit review
435
+
436
+ ### What the guardrails prevent
437
+
438
+ | Scenario | Gate | Result |
439
+ |----------|------|--------|
440
+ | Edit `spec/**/*.yaml` → regenerate → commit | — | ✅ Allowed |
441
+ | Edit `server/src/**/domains/**` | — | ✅ Allowed |
442
+ | Edit `packages/**/*.ts` directly | 1 | ❌ Blocked |
443
+ | Edit `*.generated.ts` directly | 1 | ❌ Blocked |
444
+ | Edit spec but forget to regenerate | 3 | ❌ Fails drift |
445
+ | Create endpoint without `x-auth` | 2 | ❌ Fails spec-lint |
446
+
447
+ ---
448
+
449
+ ## Appendix: CI Configuration
450
+
451
+ ### CI workflow
452
+
453
+ ```yaml
454
+ # .github/workflows/ai-guardrails.yml
455
+ name: ai-guardrails
456
+ on: [pull_request]
457
+
458
+ env:
459
+ MC: npx --yes -p micro-contracts@${{ vars.MICRO_CONTRACTS_VERSION }} micro-contracts
460
+
461
+ jobs:
462
+ guardrails:
463
+ runs-on: ubuntu-latest
464
+ steps:
465
+ - uses: actions/checkout@v4
466
+ with: { fetch-depth: 0 }
467
+
468
+ # Gate 1-2 (pinned)
469
+ - run: ${{ env.MC }} check --gate 1,2
470
+
471
+ # Generator (pinned)
472
+ - run: ${{ env.MC }} generate
473
+
474
+ # Gate 3-5 (pinned)
475
+ - run: ${{ env.MC }} check --gate 3,4,5
476
+
477
+ codeql:
478
+ runs-on: ubuntu-latest
479
+ permissions: { security-events: write }
480
+ steps:
481
+ - uses: actions/checkout@v4
482
+ - uses: github/codeql-action/init@v3
483
+ with: { languages: javascript }
484
+ - run: npm ci && npm run build
485
+ - uses: github/codeql-action/analyze@v3
486
+ ```
487
+
488
+ ### npm scripts
489
+
490
+ <!--@embedoc:code_snippet file="../examples/package.json" lang="json" start="7" end="46" title="package.json scripts (example)"-->
491
+ **package.json scripts (example)**
492
+
493
+ ```json
494
+ "scripts": {
495
+ "generate": "node ../dist/cli.js generate",
496
+
497
+ "check": "node ../dist/cli.js check",
498
+ "check:all": "node ../dist/cli.js check",
499
+
500
+ "check:gate1": "node ../dist/cli.js check --gate 1",
501
+ "check:gate2": "node ../dist/cli.js check --gate 2",
502
+ "check:gate3": "node ../dist/cli.js check --gate 3",
503
+ "check:gate4": "node ../dist/cli.js check --gate 4",
504
+ "check:gate5": "node ../dist/cli.js check --gate 5",
505
+ "check:gate1-2": "node ../dist/cli.js check --gate 1,2",
506
+ "check:gate3-5": "node ../dist/cli.js check --gate 3,4,5",
507
+
508
+ "check:allowlist": "node ../dist/cli.js check --only allowlist",
509
+ "check:spec-lint": "node ../dist/cli.js check --only spec-lint",
510
+ "check:spec-breaking": "node ../dist/cli.js check --only spec-breaking",
511
+ "check:drift": "node ../dist/cli.js check --only drift",
512
+ "check:manifest": "node ../dist/cli.js check --only manifest",
513
+ "check:package-typecheck": "node ../dist/cli.js check --only package-typecheck",
514
+ "check:code-lint": "node ../dist/cli.js check --only code-lint",
515
+ "check:code-typecheck": "node ../dist/cli.js check --only code-typecheck",
516
+ "check:docs-sync": "node ../dist/cli.js check --only docs-sync",
517
+ "check:docs-links": "node ../dist/cli.js check --only docs-links",
518
+
519
+ "lint:openapi": "spectral lint spec/core/openapi/core.yaml spec/billing/openapi/billing.yaml --ruleset spec/spectral.yaml",
520
+ "lint:openapi:generated": "spectral lint packages/contract/core/docs/openapi.generated.yaml packages/contract/billing/docs/openapi.generated.yaml --ruleset spec/spectral.yaml",
521
+ "lint:ts": "eslint server/src frontend/src --ext .ts,.tsx",
522
+ "lint": "npm run lint:openapi && npm run lint:ts",
523
+
524
+ "build": "npm run build:contract && npm run build:server && npm run build:frontend",
525
+ "build:contract": "tsc --noEmit -p packages/contract",
526
+ "build:server": "cd server && npm run build",
527
+ "build:frontend": "cd frontend && npm run build",
528
+
529
+ "dev": "concurrently -n server,frontend -c blue,green \"npm run server:dev\" \"npm run frontend:dev\"",
530
+ "server:install": "cd server && npm install",
531
+ "frontend:install": "cd frontend && npm install",
532
+ "server:dev": "cd server && PORT=3001 npm run dev",
533
+ "frontend:dev": "cd frontend && VITE_API_BASE_URL=http://localhost:3001 npm run dev -- --port 5173",
534
+ ```
535
+
536
+ 📄 Source: [`package.json`](../examples/package.json) (lines 7-46)
537
+ <!--@embedoc:end-->
538
+
539
+ ---
540
+
541
+ *Last updated: 2026-01-06*