gaia-framework 1.66.0 → 1.83.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.
Files changed (38) hide show
  1. package/.claude/commands/gaia-create-stakeholder.md +20 -0
  2. package/.claude/commands/gaia-test-gap-analysis.md +17 -0
  3. package/CLAUDE.md +87 -1
  4. package/README.md +2 -2
  5. package/_gaia/_config/global.yaml +5 -1
  6. package/_gaia/_config/lifecycle-sequence.yaml +20 -0
  7. package/_gaia/_config/skill-manifest.csv +2 -0
  8. package/_gaia/_config/workflow-manifest.csv +3 -1
  9. package/_gaia/core/engine/workflow.xml +5 -1
  10. package/_gaia/core/workflows/party-mode/steps/step-01-agent-loading.md +60 -9
  11. package/_gaia/creative/workflows/problem-solving/checklist.md +64 -14
  12. package/_gaia/creative/workflows/problem-solving/instructions.xml +367 -22
  13. package/_gaia/creative/workflows/problem-solving/workflow.yaml +31 -1
  14. package/_gaia/dev/agents/_base-dev.md +7 -1
  15. package/_gaia/dev/skills/_skill-index.yaml +9 -0
  16. package/_gaia/dev/skills/figma-integration.md +296 -0
  17. package/_gaia/lifecycle/templates/brownfield-scan-security-prompt.md +228 -0
  18. package/_gaia/lifecycle/templates/gap-entry-schema.md +39 -4
  19. package/_gaia/lifecycle/templates/story-template.md +22 -1
  20. package/_gaia/lifecycle/workflows/2-planning/create-ux-design/instructions.xml +52 -3
  21. package/_gaia/lifecycle/workflows/4-implementation/create-stakeholder/checklist.md +25 -0
  22. package/_gaia/lifecycle/workflows/4-implementation/create-stakeholder/instructions.xml +79 -0
  23. package/_gaia/lifecycle/workflows/4-implementation/create-stakeholder/workflow.yaml +22 -0
  24. package/_gaia/lifecycle/workflows/4-implementation/create-story/instructions.xml +10 -0
  25. package/_gaia/lifecycle/workflows/4-implementation/retrospective/instructions.xml +3 -3
  26. package/_gaia/lifecycle/workflows/4-implementation/validate-story/instructions.xml +11 -0
  27. package/_gaia/lifecycle/workflows/anytime/brownfield-onboarding/instructions.xml +11 -7
  28. package/_gaia/testing/workflows/test-gap-analysis/checklist.md +8 -0
  29. package/_gaia/testing/workflows/test-gap-analysis/instructions.xml +53 -0
  30. package/_gaia/testing/workflows/test-gap-analysis/workflow.yaml +38 -0
  31. package/bin/gaia-framework.js +36 -2
  32. package/bin/helpers/derive-bump-label.js +41 -0
  33. package/bin/helpers/validate-bump-labels.js +38 -0
  34. package/gaia-install.sh +71 -4
  35. package/package.json +1 -1
  36. package/_gaia/_memory/tier2-results/.gitkeep +0 -0
  37. package/_gaia/_memory/tier2-results/checkpoint-resume-2026-03-24.yaml +0 -6
  38. package/_gaia/_memory/tier2-results/engine-scenarios-2026-03-22.yaml +0 -14
@@ -0,0 +1,296 @@
1
+ ---
2
+ name: figma-integration
3
+ version: '1.0'
4
+ requires_mcp: design-tool
5
+ applicable_agents: [typescript-dev, angular-dev, flutter-dev, java-dev, python-dev, mobile-dev]
6
+ test_scenarios:
7
+ - scenario: Figma MCP server available and healthy
8
+ expected: Mode selection (Generate/Import/Skip) presented to user
9
+ - scenario: Figma MCP server not installed
10
+ expected: Silent fallback to markdown-only, no error or warning
11
+ - scenario: Figma MCP server not running
12
+ expected: Silent fallback to markdown-only, no error or warning
13
+ - scenario: Figma API token expired
14
+ expected: Warning displayed, fallback to markdown-only
15
+ - scenario: Rate limited (429)
16
+ expected: Single retry after delay, fallback with warning if retry fails
17
+ - scenario: Timeout exceeding 5 seconds
18
+ expected: Fallback with warning, continue markdown-only
19
+ - scenario: Design tool detection via MCP probe
20
+ expected: Correct adapter selected based on available MCP tool prefix
21
+ - scenario: Token extraction produces W3C DTCG format
22
+ expected: design-tokens.json contains $type/$value structure with semantic aliases
23
+ - scenario: Component spec extraction
24
+ expected: component-specs.yaml contains typed props, abstract layout, and states
25
+ ---
26
+
27
+ **DesignToolProvider Interface** — abstract interface for design tool integrations. Adapters implement these 5 operations:
28
+
29
+ | Operation | Description | Returns |
30
+ |-----------|-------------|---------|
31
+ | `detect()` | Probe MCP tools to identify available design tool | Adapter instance or null |
32
+ | `getTokens()` | Extract design tokens from the design file | W3C DTCG JSON (`design-tokens.json`) |
33
+ | `getComponents()` | Extract component specifications | YAML spec (`component-specs.yaml`) |
34
+ | `getFrames()` | Generate UI kit frames across viewports | Frame metadata for UI kit page |
35
+ | `exportAssets()` | Export images and icons at required densities | Asset files in `assets/` directory |
36
+
37
+ **Adapter Implementations:**
38
+ - **FigmaAdapter** (active) — wraps `figma_*` / `figma/` MCP tools (e.g., `figma/get_file`, `figma/get_styles`, `figma/get_components`). Detected when MCP tools matching prefix `figma` are available.
39
+ - **PenpotAdapter** (planned) — will wrap `penpot_*` MCP tools. Detected via `penpot_` prefix. Not yet implemented.
40
+ - **SketchAdapter** (planned) — will wrap `sketch_*` MCP tools. Detected via `sketch_` prefix. Not yet implemented.
41
+
42
+ **Selection logic:** probe MCP tool list for known prefixes in order: `figma_` / `figma/` → `penpot_` → `sketch_`. Use the first match. If none found, report "No design tool MCP server detected."
43
+
44
+ **MCP constraint (FR-140):** operations are read-heavy/write-light. Most interactions read design data (tokens, components, styles). Write operations are limited to frame generation and are clearly documented per section.
45
+
46
+ <!-- SECTION: detection -->
47
+ ## Detection Probe
48
+
49
+ Detect Figma MCP server availability using a lightweight, read-only probe call.
50
+ This section is consumed by `/gaia-create-ux` at workflow start.
51
+
52
+ > **Security mandate:** NEVER persist Figma API tokens in any GAIA file — checkpoints, sidecars, logs, or artifacts. MCP auth is handled by the MCP server process; GAIA does not touch tokens.
53
+
54
+ > **Detection-only mandate:** GAIA MUST never install, configure, or modify the MCP server. Detection is read-only — probe for availability via `figma/get_user_info` or tool listing, nothing more.
55
+
56
+ ### Probe Call
57
+
58
+ Use `figma/get_user_info` as the detection probe:
59
+ - Read-only, lightweight, validates both connectivity and token validity
60
+ - 5-second hard timeout (NFR-026 compliance)
61
+ - Zero added latency when MCP is not available (silent skip)
62
+
63
+ ### Detection Flow
64
+
65
+ 1. **Attempt probe:** call `figma/get_user_info` with a 5-second hard timeout
66
+ 2. **On success:** set `figma_mcp_available = true`, proceed to mode selection
67
+ 3. **On failure:** classify the failure and handle per the failure mode table below
68
+
69
+ ### Failure Mode Handling
70
+
71
+ | Failure | Detection Signal | Behavior |
72
+ |---------|-----------------|----------|
73
+ | **Not installed** (AC5) | Tool not found / tool not available | Silent fallback to markdown-only mode — no error, no warning, no prompt |
74
+ | **Not running** (AC6) | Connection refused / connection error | Silent fallback to markdown-only mode — no error, no warning, no prompt |
75
+ | **Token expired** (AC7) | 401 or 403 response from `figma/get_user_info` | Warn: "Figma token expired — falling back to markdown" then continue markdown-only |
76
+ | **Rate limited** (AC8) | 429 response | Retry once after `Retry-After` header delay (default: 2 seconds). If retry also fails, warn and fallback to markdown-only |
77
+ | **Timeout** (AC9) | No response within 5-second hard timeout | Warn: "Figma MCP did not respond within 5 seconds — falling back to markdown" then continue markdown-only |
78
+ | **Malformed response** | Unexpected or partial data | Treat as unavailable — silent fallback to markdown-only |
79
+
80
+ ### Mode Selection (on success)
81
+
82
+ When `figma_mcp_available == true`, present the user with:
83
+
84
+ ```
85
+ Figma MCP detected. Select UX design mode:
86
+ [g] Generate — AI-generated UX with Figma export
87
+ [i] Import — Import existing Figma designs into GAIA
88
+ [s] Skip — Proceed with markdown-only (ignore Figma)
89
+ ```
90
+
91
+ ### Minimum API Scopes
92
+
93
+ The Figma API token used by the MCP server requires these minimum scopes:
94
+
95
+ | Scope | Required For | Mode |
96
+ |-------|-------------|------|
97
+ | `files:read` | Reading design files, styles, components | Default (all modes) |
98
+ | `file_content:read` | Reading file content, nodes, images | Default (all modes) |
99
+ | `files:write` | Creating frames, writing to design files | Generate mode only |
100
+
101
+ Scope enforcement is the MCP server's responsibility — GAIA documents scope expectations only and does not validate or request token scopes.
102
+
103
+ ### Error Sanitization Rules
104
+
105
+ All error messages from MCP operations MUST follow this safe error format:
106
+
107
+ ```
108
+ Figma MCP error: {status_code} — {generic_description}. Falling back to markdown-only workflow.
109
+ ```
110
+
111
+ **Disallowed content in error messages:** Figma file URLs, file keys, node IDs, design data, access tokens, or any dynamic content from the Figma API response.
112
+
113
+ | Status Code | Generic Description |
114
+ |-------------|-------------------|
115
+ | 401 | Authentication failed |
116
+ | 403 | Access denied |
117
+ | 404 | Resource not found |
118
+ | 429 | Rate limit exceeded — retry once, then fallback |
119
+ | 500 | Server error |
120
+
121
+ ### Security Boundary
122
+
123
+ - The Figma API token lives exclusively in the MCP server configuration (ADR-024)
124
+ - GAIA files must NEVER contain or log Figma tokens, API keys, or credentials
125
+ - Detection probe interacts through MCP tool abstraction only — no direct HTTP calls
126
+
127
+ ### Traceability
128
+
129
+ - FR-132: Figma MCP detection probe requirement
130
+ - FR-143: Graceful MCP failure handling
131
+ - NFR-026: MCP detection latency < 5 seconds
132
+ - ADR-024: Figma MCP integration via shared skill
133
+
134
+ <!-- SECTION: tokens -->
135
+ ## Design Token Extraction
136
+
137
+ > **Security mandate:** MCP auth is handled by the MCP server — NEVER persist or reference Figma API tokens in extraction outputs, logs, or GAIA files.
138
+
139
+ Extract design tokens from the connected design tool and output in W3C DTCG format.
140
+
141
+ ### Extraction Steps
142
+
143
+ 1. **Fetch styles** — call `figma/get_styles` to retrieve all published styles (colors, typography, effects, grids)
144
+ 2. **Map to W3C DTCG** — transform each style into the W3C Design Tokens Community Group draft format:
145
+ ```json
146
+ {
147
+ "color": {
148
+ "primary": { "$type": "color", "$value": "#3B82F6", "$description": "Brand primary" }
149
+ },
150
+ "spacing": {
151
+ "sm": { "$type": "dimension", "$value": "8px" }
152
+ },
153
+ "typography": {
154
+ "heading-1": {
155
+ "$type": "typography",
156
+ "$value": { "fontFamily": "Inter", "fontSize": "32px", "fontWeight": 700, "lineHeight": 1.2 }
157
+ }
158
+ }
159
+ }
160
+ ```
161
+ 3. **Include semantic aliases** — map raw tokens to semantic names (e.g., `color.surface.primary` → `color.blue.500`)
162
+ 4. **Add composite tokens** — typography composites, shadow composites, border-radius scales
163
+ 5. **Write output** — save to `{planning_artifacts}/design-system/design-tokens.json` with `"schema_version": "1.0"`
164
+
165
+ <!-- SECTION: components -->
166
+ ## Component Spec Extraction
167
+
168
+ > **Security mandate:** MCP auth is handled by the MCP server — NEVER include Figma API tokens in component specs, logs, or any GAIA output files.
169
+
170
+ Extract component specifications into a tech-agnostic intermediate format.
171
+
172
+ ### Extraction Steps
173
+
174
+ 1. **Fetch components** — call `figma/get_components` to list all published components and variants
175
+ 2. **For each component**, extract:
176
+ - **name** — component name (PascalCase)
177
+ - **props** — typed properties: `{ name: string, type: "string"|"number"|"boolean"|"enum", values?: string[] }`
178
+ - **layout** — abstract layout type: `row | column | stack | grid` with spacing via token references (`{spacing.sm}`)
179
+ - **states** — `[default, hover, active, disabled, focus]` with visual diff per state
180
+ - **children** — nested component references with slot definitions
181
+ - **variants** — named variants with their property overrides
182
+ - **responsive** — breakpoint behavior at 375px, 768px, 1280px
183
+ - **a11y** — role, aria-label pattern, description, keyboard interaction
184
+ 3. **Write output** — save to `{planning_artifacts}/design-system/component-specs.yaml` with `schema_version: "1.0"`
185
+
186
+ ### Output Schema
187
+
188
+ ```yaml
189
+ schema_version: "1.0"
190
+ components:
191
+ - name: Button
192
+ props:
193
+ - { name: label, type: string }
194
+ - { name: variant, type: enum, values: [primary, secondary, ghost] }
195
+ - { name: disabled, type: boolean }
196
+ layout: { type: row, gap: "{spacing.sm}" }
197
+ states: [default, hover, active, disabled, focus]
198
+ a11y: { role: button, label: "{props.label}" }
199
+ ```
200
+
201
+ <!-- SECTION: frames -->
202
+ ## Frame Generation
203
+
204
+ > **Security mandate:** MCP auth is handled by the MCP server — NEVER persist Figma API tokens in frame metadata, logs, or any GAIA output files.
205
+
206
+ Create UI kit frames in the design tool across standard viewports.
207
+
208
+ ### Generation Steps
209
+
210
+ 1. **Create UI Kit page** — create a dedicated page named "UI Kit — Generated" in the design file
211
+ 2. **For each screen** defined in the UX design:
212
+ - Create 3 viewport frames: mobile (375px), tablet (768px), desktop (1280px)
213
+ - Apply auto-layout with responsive constraints from component specs
214
+ - Place components using the extracted component specs and token values
215
+ 3. **Add prototype flows** — link frames with interaction flows matching the UX navigation spec
216
+ 4. **Label frames** — use naming convention: `{ScreenName}/{Viewport}` (e.g., `Dashboard/Desktop`)
217
+
218
+ ### Output
219
+
220
+ Frame metadata logged for verification. No file output — frames are created directly in the design tool via MCP calls (`figma/create_frame`, `figma/create_component_instance`).
221
+
222
+ <!-- SECTION: assets -->
223
+ ## Asset Export
224
+
225
+ > **Security mandate:** MCP auth is handled by the MCP server — NEVER include Figma API tokens in asset manifests, export logs, or any GAIA output files.
226
+
227
+ Export raster and vector assets from the design tool at required densities.
228
+
229
+ ### Export Steps
230
+
231
+ 1. **Identify exportable nodes** — scan the design file for nodes marked as exportable (icons, images, illustrations)
232
+ 2. **Export icons** as SVG — call `figma/get_images` with `format: svg` for all icon nodes
233
+ 3. **Export images** as PNG at 3 densities — call `figma/get_images` with `format: png` and `scale: 1`, `scale: 2`, `scale: 3` for image nodes
234
+ 4. **Organize output** into directory structure:
235
+ ```
236
+ {planning_artifacts}/design-system/assets/
237
+ ├── icons/ # SVG icons
238
+ │ ├── icon-name.svg
239
+ ├── images/ # PNG images at 1x/2x/3x
240
+ │ ├── image-name@1x.png
241
+ │ ├── image-name@2x.png
242
+ │ └── image-name@3x.png
243
+ ```
244
+ 5. **Generate asset manifest** — list all exported assets with dimensions and file sizes
245
+
246
+ <!-- SECTION: export -->
247
+ ## Per-Stack Token Resolution
248
+
249
+ > **Security mandate:** MCP auth is handled by the MCP server — NEVER embed Figma API tokens in generated token files, stack outputs, or any GAIA output files.
250
+
251
+ Maps abstract design tokens to framework-specific implementations. Each dev agent uses this table to generate native code from `design-tokens.json`.
252
+
253
+ | Agent | Stack | Token Format | Example |
254
+ |-------|-------|-------------|---------|
255
+ | Cleo | TypeScript/React | CSS custom properties | `--color-primary: #3B82F6;` in `:root {}` |
256
+ | Lena | Angular | SCSS variables + CSS custom properties | `$color-primary: #3B82F6;` in `_tokens.scss` |
257
+ | Freya | Flutter/Dart | ThemeData extensions | `ThemeData(primaryColor: Color(0xFF3B82F6))` |
258
+ | Hugo | Java/Spring | Spring properties + Java constants | `design.color.primary=#3B82F6` in `application.properties` |
259
+ | Ravi | Python | Python dict constants | `TOKENS = {"color": {"primary": "#3B82F6"}}` in `design_tokens.py` |
260
+ | Talia | Mobile (RN/Swift/Compose) | RN StyleSheet / Swift extensions / Compose theme | `StyleSheet.create({primary: '#3B82F6'})` or `extension UIColor { static let primary = UIColor(hex: "3B82F6") }` or `val Primary = Color(0xFF3B82F6)` |
261
+
262
+ ### Resolution Process
263
+
264
+ 1. Read `design-tokens.json` (W3C DTCG format) from `{planning_artifacts}/design-system/`
265
+ 2. Read `component-specs.yaml` from the same directory for component definitions and widget hints
266
+ 3. Identify the active dev agent's stack from the agent persona
267
+ 4. For each token, generate the stack-native representation using the table above
268
+ 5. For each component, use the `widget_hints` field to guide framework-specific widget/component tree generation
269
+ 6. Output token files to the project's design system directory (stack-specific path)
270
+
271
+ ### Token Path Resolution Rules
272
+
273
+ Token paths use `{group.token}` syntax. The resolution pattern per stack:
274
+
275
+ | Stack | Pattern | Example Path | Resolved Output |
276
+ |-------|---------|-------------|-----------------|
277
+ | TypeScript/React | `--{group}-{token}` | `{color.blue-500}` | `var(--color-blue-500)` |
278
+ | Angular | `${group}-{token}` | `{spacing.4}` | `$spacing-4` |
279
+ | Flutter/Dart | `AppTokens.{group}.{token}` | `{typography.body}` | `AppTokens.typography.body` |
280
+ | Java/Spring | `design.{group}.{token}` | `{color.interactive-primary}` | `design.color.interactive-primary` |
281
+ | Python | `TOKENS['{group}']['{token}']` | `{shadow.md}` | `TOKENS['shadow']['md']` |
282
+ | Mobile (RN) | `tokens.{group}.{token}` | `{borderRadius.md}` | `tokens.borderRadius.md` |
283
+ | Mobile (Swift) | `DesignTokens.{group}.{token}` | `{color.blue-500}` | `DesignTokens.color.blue500` |
284
+ | Mobile (Compose) | `AppTheme.{group}.{token}` | `{spacing.2}` | `AppTheme.spacing.s2` |
285
+
286
+ ### Semantic Alias Resolution
287
+
288
+ Semantic tokens reference primitives via `{group.token}` syntax in their `$value` field. When generating stack-specific code, resolve the alias chain to produce the final value. Example:
289
+
290
+ ```
291
+ "interactive-primary": { "$type": "color", "$value": "{color.blue-500}" }
292
+ → resolves to → #3B82F6
293
+ → CSS: --color-interactive-primary: #3B82F6;
294
+ → SCSS: $color-interactive-primary: #3B82F6;
295
+ → Dart: static const interactivePrimary = Color(0xFF3B82F6);
296
+ ```
@@ -3,6 +3,7 @@
3
3
  > Brownfield deep analysis scan subagent. Detects security gaps in API endpoints and infrastructure security configurations.
4
4
  > Reference: Architecture ADR-021, Section 10.15.2, Section 10.15.5, ADR-022 §10.16.5
5
5
  > Infra-awareness: E12-S6 — applies infra-specific patterns when project_type is infrastructure or platform.
6
+ > Non-REST protocols: E11-S17 — GraphQL and gRPC endpoint detection and security gap scanning.
6
7
 
7
8
  ## Objective
8
9
 
@@ -51,6 +52,89 @@ Apply framework-specific patterns based on {tech_stack}:
51
52
 
52
53
  If no API endpoints are detected, output a summary note and zero gap entries for the application phase.
53
54
 
55
+ ## Phase 1b: GraphQL Endpoint Discovery
56
+
57
+ Catalog all GraphQL endpoints. For each endpoint, record: operation type (query/mutation/subscription), resolver function, authentication directives, authorization checks.
58
+
59
+ ### Schema-First Detection Patterns
60
+
61
+ - `.graphql` and `.gql` schema files
62
+ - `type Query { ... }` and `type Mutation { ... }` blocks in schema files
63
+ - `typeDefs` variable definitions in JS/TS files (template literals with SDL)
64
+
65
+ ### Code-First Detection Patterns
66
+
67
+ - `@Resolver()` decorators (NestJS, TypeGraphQL)
68
+ - `@Query()` and `@Mutation()` decorators
69
+ - `resolvers` objects exported from modules
70
+ - Python class-based resolvers (Strawberry `@strawberry.type`, Ariadne `@query_type.field`)
71
+ - Go resolver structs (gqlgen `resolver.go` files)
72
+
73
+ ### GraphQL Framework Variants
74
+
75
+ Apply framework-specific patterns based on detected GraphQL library:
76
+
77
+ | Framework | Language | Detection Pattern |
78
+ |---|---|---|
79
+ | Apollo Server | Node/TS | `ApolloServer`, `@apollo/server`, Apollo plugins |
80
+ | GraphQL Yoga | Node/TS | `createYoga`, `@graphql-yoga/node` |
81
+ | Mercurius | Node/TS (Fastify) | `mercurius`, `app.graphql` |
82
+ | Strawberry | Python | `strawberry.Schema`, `@strawberry.type` |
83
+ | gqlgen | Go | `gqlgen.yml`, `generated.go`, resolver structs |
84
+ | Ariadne | Python | `ariadne`, `make_executable_schema` |
85
+ | NestJS GraphQL | Node/TS | `@nestjs/graphql`, `@Resolver()`, `@Query()`, `@Mutation()` |
86
+
87
+ ### GraphQL Middleware Chain Detection
88
+
89
+ - `graphql-shield` rule trees (`const permissions = shield({ ... })`)
90
+ - `@UseGuards(AuthGuard)` decorators (NestJS)
91
+ - Apollo Server plugins (`ApolloServerPlugin` implementing `requestDidStart`)
92
+ - Yoga plugins (`useAuth`, custom `envelop` plugins)
93
+ - Custom context resolvers setting `context.user` from auth headers
94
+
95
+ ### Graceful Exit — No GraphQL Endpoints
96
+
97
+ If no GraphQL schema files, resolver definitions, or GraphQL framework imports are detected, skip Phase 1b and Phase 2b entirely. Output a summary note and zero gap entries for GraphQL.
98
+
99
+ ## Phase 1c: gRPC Endpoint Discovery
100
+
101
+ Catalog all gRPC endpoints. For each endpoint, record: service name, RPC method name, request/response message types, streaming type (unary/server/client/bidirectional), interceptor chain.
102
+
103
+ ### Proto Service Parsing
104
+
105
+ - `.proto` files with `service` blocks defining `rpc` methods
106
+ - `stream` annotations on request or response types (server streaming, client streaming, bidirectional streaming)
107
+ - `package` declarations for service namespace
108
+
109
+ ### Server Interceptor Detection
110
+
111
+ | Language | Interceptor Pattern |
112
+ |---|---|
113
+ | Java | `ServerInterceptor` interface, `@GrpcService` (Spring gRPC), interceptor registry |
114
+ | Go | `grpc.UnaryInterceptor()`, `grpc.StreamInterceptor()`, `grpc.ChainUnaryInterceptor()` |
115
+ | Python | `grpc.server_interceptor`, `intercept_service()` |
116
+ | Node/TS | `addService()` calls, `@GrpcMethod` decorators (NestJS), `grpc-js` server options |
117
+
118
+ ### gRPC Middleware Chain Detection
119
+
120
+ - Interceptor chains in server setup (ordered middleware)
121
+ - `@GrpcMethod` decorators with guard annotations (NestJS)
122
+ - Metadata extractors for authentication tokens
123
+ - Health check service registration (`grpc.health.v1`)
124
+
125
+ ### Graceful Exit — No gRPC Endpoints
126
+
127
+ If no `.proto` files, gRPC server setup, or gRPC framework imports are detected, skip Phase 1c and Phase 2c entirely. Output a summary note and zero gap entries for gRPC.
128
+
129
+ ## Phase 1d: Mixed-Protocol Detection
130
+
131
+ A single codebase may expose REST + GraphQL + gRPC endpoints simultaneously. When multiple protocols are detected:
132
+
133
+ 1. Scan all three protocols independently
134
+ 2. Identify shared authentication middleware (e.g., a JWT validator used by both Express routes and Apollo context)
135
+ 3. Do not double-count shared middleware as separate gaps — if auth middleware covers both REST and GraphQL, count it once
136
+ 4. Note in findings when multiple protocols share infrastructure
137
+
54
138
  ## Phase 2: Security Gap Detection — Application Rules
55
139
 
56
140
  ### 1. Missing Authentication Middleware (AC3a)
@@ -82,6 +166,99 @@ Sensitive data exposure is `high` severity.
82
166
 
83
167
  Detect POST/PUT/PATCH/DELETE endpoints that accept a request body but have no input validation. Missing input validation is `high` severity.
84
168
 
169
+ ## Phase 2b: GraphQL Security Gap Detection
170
+
171
+ ### 1. Queries/Mutations Missing Auth Directives
172
+
173
+ Detect GraphQL operations missing authentication. Look for:
174
+ - Resolvers without `@auth`, `@authenticated`, `@HasPermission`, or `@UseGuards(AuthGuard)` directives
175
+ - Schema types without `@auth` directive when other types have it (inconsistent protection)
176
+ - Mutation resolvers with no authorization checks are `critical` severity
177
+ - Query resolvers returning non-public data without auth are `high` severity
178
+
179
+ ### 2. Introspection Enabled in Production
180
+
181
+ Detect GraphQL introspection configuration that may leak schema in production:
182
+ - `introspection: true` in Apollo Server config without `NODE_ENV` conditional
183
+ - Missing introspection disable in production configuration
184
+ - Yoga/Mercurius default introspection without explicit disable
185
+
186
+ Introspection in production is `medium` severity.
187
+
188
+ ### 3. Mutations Without Authorization Checks
189
+
190
+ Detect mutation resolvers that lack authorization logic:
191
+ - Mutation handlers with no permission checks, guard decorators, or authorization middleware
192
+ - `graphql-shield` rules that allow mutations without role checks
193
+ - NestJS mutations without `@UseGuards()` when other mutations have guards
194
+
195
+ Missing mutation authorization is `critical` severity.
196
+
197
+ ### 4. Field-Level Authorization Gaps
198
+
199
+ Detect sensitive fields exposed without field-level auth controls:
200
+ - Fields named `email`, `password`, `ssn`, `token`, `secret`, `creditCard` without `@Authorized` or field-level resolvers
201
+ - Resolver types exposing sensitive nested objects without per-field permission checks
202
+ - User types exposing admin-only fields to all authenticated users
203
+
204
+ Field-level authorization gaps are `high` severity.
205
+
206
+ ### 5. GraphQL Federation and Schema Stitching
207
+
208
+ When Apollo Federation or schema stitching is detected:
209
+ - Note gateway-level auth that may mask per-service gaps
210
+ - Flag subgraph services that rely solely on gateway auth without their own validation
211
+ - Detect `@external` fields without authorization in the owning subgraph
212
+
213
+ Federation auth gaps are `medium` severity with a note about gateway-level coverage.
214
+
215
+ ## Phase 2c: gRPC Security Gap Detection
216
+
217
+ ### 1. Services Missing Auth Interceptors
218
+
219
+ Detect gRPC server setup without authentication interceptors:
220
+ - Server initialization without `AuthInterceptor` or equivalent in the interceptor chain
221
+ - Services registered via `addService` with no auth middleware applied
222
+ - Spring gRPC services without `@GrpcService` security configuration
223
+
224
+ Missing auth interceptor is `critical` severity.
225
+
226
+ ### 2. Unary RPCs Without Authorization Metadata
227
+
228
+ Detect unary RPC methods that do not validate authorization metadata:
229
+ - `rpc` method handlers that do not extract or validate `metadata` authorization headers
230
+ - Handler functions that skip token/credential validation from gRPC metadata
231
+ - Methods that do not check caller identity or roles from request context
232
+
233
+ Missing unary authorization is `high` severity.
234
+
235
+ ### 3. Streaming RPCs Without Per-Message Auth
236
+
237
+ Detect bidirectional and server streaming RPCs without per-message authentication:
238
+ - Stream handlers that authenticate only at connection start but not per-message
239
+ - Bidirectional streams without per-message auth validation
240
+ - Server streaming RPCs that do not re-validate authorization on long-lived connections
241
+
242
+ Missing stream auth is `high` severity.
243
+
244
+ ### 4. TLS Configuration Gaps
245
+
246
+ Detect insecure gRPC transport configuration:
247
+ - `grpc.insecure_port` usage in non-development configuration
248
+ - `ServerCredentials.createInsecure()` in production server setup
249
+ - Missing TLS certificate configuration in production gRPC servers
250
+ - Plaintext gRPC channels in production client configuration
251
+
252
+ Insecure TLS is `critical` severity.
253
+
254
+ ### 5. gRPC Reflection Enabled in Production
255
+
256
+ Detect gRPC reflection service that may expose service definitions:
257
+ - `grpc.reflection.v1alpha` or `grpc.reflection.v1` service registered without environment guard
258
+ - Reflection service enabled unconditionally (similar risk to GraphQL introspection)
259
+
260
+ Reflection in production is `medium` severity.
261
+
85
262
  ## Phase 3: False-Positive Mitigation — Inherited Auth
86
263
 
87
264
  Before flagging an endpoint as "missing authentication middleware," trace the middleware chain upward:
@@ -106,6 +283,18 @@ Before flagging an endpoint as "missing authentication middleware," trace the mi
106
283
  - `r.Use(JWTAuth())` — app-level
107
284
  - `group := r.Group("/api"); group.Use(AuthMiddleware())` — group-level
108
285
 
286
+ #### GraphQL Inherited Auth
287
+ - Apollo Server `context` function that validates JWT and sets `context.user` — app-level
288
+ - `graphql-shield` rule tree applied via `applyMiddleware` — schema-level
289
+ - NestJS `@UseGuards(AuthGuard)` on resolver class — class-level
290
+ - Apollo Federation gateway-level auth that validates before routing to subgraphs — gateway-level
291
+
292
+ #### gRPC Inherited Auth
293
+ - Global auth interceptor registered via `grpc.UnaryInterceptor(authInterceptor)` — server-level
294
+ - `ServerInterceptor` added to server builder interceptor chain — server-level
295
+ - Per-service interceptor applied at `addService` — service-level
296
+ - TLS mutual authentication (mTLS) at transport level — transport-level
297
+
109
298
  ## Phase 4: Infrastructure Security Patterns (E12-S6)
110
299
 
111
300
  **Apply ONLY when {project_type} is `infrastructure` or `platform`.**
@@ -180,11 +369,50 @@ gap:
180
369
  evidence:
181
370
  file: "relative/path/to/file"
182
371
  line: 42
372
+ protocol: "rest"
183
373
  recommendation: "Actionable fix — add middleware, validate input, filter response"
184
374
  verified_by: "machine-detected"
185
375
  confidence: "{high|medium|low}"
186
376
  ```
187
377
 
378
+ **Protocol field:** Every gap entry MUST include a `protocol` field in the evidence section indicating which API protocol the finding applies to: `rest`, `graphql`, or `grpc`. This enables downstream consumers to filter and route findings by protocol.
379
+
380
+ #### GraphQL Gap Example
381
+
382
+ ```yaml
383
+ gap:
384
+ id: "GAP-SECURITY-015"
385
+ category: "security-endpoint"
386
+ severity: "critical"
387
+ title: "Mutation resolver missing authorization checks"
388
+ description: "createUser mutation has no @auth directive or guard. Any authenticated user can create accounts."
389
+ evidence:
390
+ file: "src/graphql/resolvers/user.resolver.ts"
391
+ line: 42
392
+ protocol: "graphql"
393
+ recommendation: "Add @UseGuards(AuthGuard, RolesGuard) or @auth directive to the createUser mutation."
394
+ verified_by: "machine-detected"
395
+ confidence: "high"
396
+ ```
397
+
398
+ #### gRPC Gap Example
399
+
400
+ ```yaml
401
+ gap:
402
+ id: "GAP-SECURITY-022"
403
+ category: "security-endpoint"
404
+ severity: "critical"
405
+ title: "gRPC server missing auth interceptor in production config"
406
+ description: "Server setup uses grpc.insecure_port without TLS. No auth interceptor in interceptor chain."
407
+ evidence:
408
+ file: "cmd/server/main.go"
409
+ line: 58
410
+ protocol: "grpc"
411
+ recommendation: "Add TLS credentials and an auth interceptor to the gRPC server configuration."
412
+ verified_by: "machine-detected"
413
+ confidence: "high"
414
+ ```
415
+
188
416
  ### Confidence Classification
189
417
 
190
418
  - **high** — exact pattern match (e.g., no auth decorator/annotation on a `@PostMapping` handler)
@@ -1,7 +1,7 @@
1
1
  # Gap Entry Schema
2
2
 
3
- > **Version:** 1.1.0
4
- > **Story:** E11-S1, E12-S5
3
+ > **Version:** 1.2.0
4
+ > **Story:** E11-S1, E12-S5, E11-S18
5
5
  > **Traces to:** FR-111, FR-123, US-38, ADR-021, ADR-022
6
6
  >
7
7
  > Standardized output schema for brownfield scan subagents (E11).
@@ -22,6 +22,7 @@ description: "<string>"
22
22
  evidence:
23
23
  file: "<relative-path>"
24
24
  line: <number-or-range>
25
+ protocol: "<string>" # Optional
25
26
  recommendation: "<string>"
26
27
  verified_by: "<agent-id>"
27
28
  confidence: "<enum>"
@@ -36,7 +37,7 @@ confidence: "<enum>"
36
37
  | `severity` | enum | yes | Impact level — must be one of the 5 allowed values (see Severity Enum) |
37
38
  | `title` | string | yes | Short summary of the gap (max 80 characters) |
38
39
  | `description` | string | yes | Detailed explanation of the gap, what it means, and why it matters |
39
- | `evidence` | object | yes | Source code evidence (see Evidence Object) |
40
+ | `evidence` | object | yes | Source code evidence with required `file` and `line` sub-fields, plus optional `protocol` sub-field (see Evidence Object) |
40
41
  | `recommendation` | string | yes | Actionable fix or remediation guidance |
41
42
  | `verified_by` | string | yes | ID of the scan agent that produced this finding (e.g., `dead-code-analyzer`, `config-scanner`) |
42
43
  | `confidence` | enum | yes | Agent's confidence in the finding accuracy (see Confidence Enum) |
@@ -95,6 +96,7 @@ The `evidence` field is a composite object grouping source location data:
95
96
  evidence:
96
97
  file: "src/services/auth.ts" # Relative path from project root (non-empty string)
97
98
  line: 42 # Single line number
99
+ protocol: "rest" # Optional. Protocol type
98
100
  ```
99
101
 
100
102
  Or with a line range:
@@ -105,10 +107,19 @@ evidence:
105
107
  line: "15-28" # Line range (start-end)
106
108
  ```
107
109
 
110
+ Or without the optional protocol field (backward compatible):
111
+
112
+ ```yaml
113
+ evidence:
114
+ file: "src/utils/helper.ts"
115
+ line: 10
116
+ ```
117
+
108
118
  | Sub-field | Type | Required | Constraints |
109
119
  |-----------|------|----------|-------------|
110
120
  | `file` | string | yes | Relative path from project root. Must be non-empty. |
111
121
  | `line` | number or string | yes | Single line number (integer) or range as `"start-end"` string |
122
+ | `protocol` | string | no | Optional. One of `rest`, `graphql`, `grpc`, `websocket`, or any custom string. Omit if not applicable. When present, must be a non-empty string. |
112
123
 
113
124
  ## ID Format
114
125
 
@@ -138,10 +149,17 @@ All fields listed in the Field Reference are **required** — a gap entry with a
138
149
  - `evidence.line` must be a positive integer or a range string matching `^\d+-\d+$`
139
150
  - `title` should not exceed 80 characters
140
151
  - `verified_by` must be a non-empty string identifying the scan agent
152
+ - `evidence.protocol` when present, must be a non-empty string
141
153
 
142
154
  ### Required vs Optional
143
155
 
144
- All 9 fields (`id`, `category`, `severity`, `title`, `description`, `evidence`, `recommendation`, `verified_by`, `confidence`) are **required**. There are no optional fields in the base schema.
156
+ All 9 top-level fields (`id`, `category`, `severity`, `title`, `description`, `evidence`, `recommendation`, `verified_by`, `confidence`) are **required**. There are no optional top-level fields in the base schema.
157
+
158
+ The `evidence` object contains one optional sub-field: `protocol`. This is the first optional sub-field in the schema. Existing gap entries that omit `protocol` remain fully valid.
159
+
160
+ ### Optional Field Validation
161
+
162
+ The `protocol` sub-field of the `evidence` object is not enum-validated. It accepts any non-empty string when present. Recommended canonical values are `rest`, `graphql`, `grpc`, and `websocket`, but custom strings (e.g., `mqtt`, `soap`, `amqp`) are also accepted without schema changes. When `protocol` is omitted entirely, the gap entry remains valid (backward compatible). When present, an empty string is invalid.
145
163
 
146
164
  ## Budget Control
147
165
 
@@ -174,6 +192,23 @@ verified_by: "config-scanner"
174
192
  confidence: "high"
175
193
  ```
176
194
 
195
+ ### Application Category Example with Protocol
196
+
197
+ ```yaml
198
+ id: "GAP-security-endpoint-001"
199
+ category: "security-endpoint"
200
+ severity: "high"
201
+ title: "Unprotected admin route exposes user management API"
202
+ description: "The /api/admin/users endpoint has no authentication middleware applied."
203
+ evidence:
204
+ file: "src/routes/admin.ts"
205
+ line: 15
206
+ protocol: "rest"
207
+ recommendation: "Add authentication middleware to all /api/admin/* routes."
208
+ verified_by: "security-scanner"
209
+ confidence: "high"
210
+ ```
211
+
177
212
  ### Infrastructure Category Examples
178
213
 
179
214
  ```yaml