gaia-framework 1.65.1 → 1.66.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 (31) hide show
  1. package/CLAUDE.md +16 -1
  2. package/README.md +2 -2
  3. package/_gaia/_config/global.yaml +1 -1
  4. package/_gaia/core/engine/workflow.xml +6 -0
  5. package/_gaia/core/protocols/review-gate-check.xml +29 -1
  6. package/_gaia/lifecycle/knowledge/brownfield/config-contradiction-scan.md +137 -0
  7. package/_gaia/lifecycle/knowledge/brownfield/dead-code-scan.md +179 -0
  8. package/_gaia/lifecycle/knowledge/brownfield/test-execution-scan.md +209 -0
  9. package/_gaia/lifecycle/skills/document-rulesets.md +91 -6
  10. package/_gaia/lifecycle/templates/brownfield-scan-doc-code-prompt.md +219 -0
  11. package/_gaia/lifecycle/templates/brownfield-scan-hardcoded-prompt.md +169 -0
  12. package/_gaia/lifecycle/templates/brownfield-scan-integration-seam-prompt.md +127 -0
  13. package/_gaia/lifecycle/templates/brownfield-scan-runtime-behavior-prompt.md +141 -0
  14. package/_gaia/lifecycle/templates/brownfield-scan-security-prompt.md +212 -0
  15. package/_gaia/lifecycle/templates/gap-entry-schema.md +247 -0
  16. package/_gaia/lifecycle/templates/infra-prd-template.md +356 -0
  17. package/_gaia/lifecycle/templates/platform-prd-template.md +431 -0
  18. package/_gaia/lifecycle/templates/prd-template.md +70 -0
  19. package/_gaia/lifecycle/workflows/4-implementation/add-feature/checklist.md +1 -1
  20. package/_gaia/lifecycle/workflows/4-implementation/add-feature/instructions.xml +2 -3
  21. package/_gaia/lifecycle/workflows/4-implementation/add-stories/checklist.md +5 -0
  22. package/_gaia/lifecycle/workflows/4-implementation/add-stories/instructions.xml +73 -1
  23. package/_gaia/lifecycle/workflows/4-implementation/create-story/instructions.xml +1 -1
  24. package/_gaia/lifecycle/workflows/4-implementation/retrospective/instructions.xml +21 -1
  25. package/_gaia/lifecycle/workflows/4-implementation/retrospective/workflow.yaml +1 -1
  26. package/_gaia/lifecycle/workflows/anytime/brownfield-onboarding/checklist.md +12 -0
  27. package/_gaia/lifecycle/workflows/anytime/brownfield-onboarding/instructions.xml +244 -4
  28. package/_gaia/lifecycle/workflows/anytime/brownfield-onboarding/workflow.yaml +1 -0
  29. package/bin/gaia-framework.js +8 -6
  30. package/gaia-install.sh +28 -20
  31. package/package.json +1 -1
@@ -0,0 +1,141 @@
1
+ # Runtime Behavior Inventory Scanner — Subagent Prompt
2
+
3
+ > Brownfield deep analysis scan subagent. Catalogs runtime behaviors that only manifest during execution.
4
+ > Reference: Architecture ADR-021, Section 10.15.2, Section 10.15.5, ADR-022 §10.16.5
5
+ > Infra-awareness: E12-S6 — applies infra-specific patterns when project_type is infrastructure or platform.
6
+
7
+ ## Objective
8
+
9
+ Scan the codebase at `{project-path}` to catalog runtime behaviors — scheduled tasks, background processes, startup hooks, shutdown handlers, and behaviors that are not visible from static code structure alone.
10
+
11
+ **Input variables:**
12
+ - `{tech_stack}` — Detected technology stack from Step 1 discovery
13
+ - `{project-path}` — Absolute path to the project source code directory
14
+ - `{project_type}` — Project type: `application`, `infrastructure`, or `platform`
15
+
16
+ **Output format:** Follow the gap entry schema at `{project-root}/_gaia/lifecycle/templates/gap-entry-schema.md` exactly.
17
+
18
+ ## Detection Categories — Application Patterns
19
+
20
+ ### 1. Scheduled Tasks and Cron Jobs
21
+
22
+ Detect application-level scheduled tasks:
23
+ - **Java/Spring:** `@Scheduled`, `@EnableScheduling`, Quartz `@DisallowConcurrentExecution`
24
+ - **Node/Express:** `node-cron`, `agenda`, `bull` queue scheduled jobs, `setInterval` for polling
25
+ - **Python/Django:** Celery `@periodic_task`, `celery.conf.beat_schedule`, `django-crontab`
26
+ - **Go:** `robfig/cron`, `time.Ticker`, goroutine polling loops
27
+
28
+ ### 2. Startup and Shutdown Hooks
29
+
30
+ Detect application lifecycle hooks:
31
+ - **Java/Spring:** `@PostConstruct`, `@PreDestroy`, `ApplicationListener`, `CommandLineRunner`
32
+ - **Node/Express:** `process.on('SIGTERM')`, `process.on('SIGINT')`, `beforeExit`
33
+ - **Python/Django:** `AppConfig.ready()`, `atexit.register`, signal handlers
34
+ - **Go:** `os.Signal` handling, `defer` patterns in main(), `sync.Once`
35
+
36
+ ### 3. Background Workers and Async Processors
37
+
38
+ Detect background processing patterns:
39
+ - Message queue consumers (Bull, SQS, Kafka, RabbitMQ consumers)
40
+ - Worker threads, child processes, goroutines for long-running tasks
41
+ - WebSocket connection handlers
42
+ - File watchers and directory monitors
43
+
44
+ ### 4. Race Conditions and Concurrency Risks
45
+
46
+ Detect patterns prone to race conditions:
47
+ - Shared mutable state without synchronization
48
+ - Non-atomic read-modify-write sequences
49
+ - Missing database transaction boundaries on multi-step operations
50
+
51
+ ## Detection Categories — Infrastructure Patterns (E12-S6)
52
+
53
+ **Apply ONLY when {project_type} is `infrastructure` or `platform`.**
54
+
55
+ ### 5. CronJob Detection
56
+
57
+ Detect Kubernetes CronJob resources and their scheduling patterns.
58
+
59
+ **Scan for:**
60
+ - `kind: CronJob` in Kubernetes manifests
61
+ - `spec.schedule` field — extract the cron expression
62
+ - `spec.concurrencyPolicy` — flag if missing (defaults to `Allow`, may cause overlapping runs)
63
+ - `spec.startingDeadlineSeconds` — flag if missing (no deadline for missed schedules)
64
+ - `spec.successfulJobsHistoryLimit` / `spec.failedJobsHistoryLimit` — flag if set to 0 (no history retained)
65
+ - `spec.suspend` — note if suspended (informational)
66
+
67
+ **Flag these as gaps:**
68
+ - CronJobs without `concurrencyPolicy: Forbid` or `Replace` (risk of overlapping runs)
69
+ - CronJobs without `startingDeadlineSeconds` (missed jobs may accumulate)
70
+ - CronJobs without resource limits on their pod template
71
+ - CronJobs with `restartPolicy: Always` (CronJob pods should use `OnFailure` or `Never`)
72
+
73
+ **Severity:** `medium` for missing policies, `high` for incorrect restart policies
74
+
75
+ ### 6. DaemonSet Detection
76
+
77
+ Detect Kubernetes DaemonSet resources and their node scheduling.
78
+
79
+ **Scan for:**
80
+ - `kind: DaemonSet` in Kubernetes manifests
81
+ - `spec.updateStrategy` — flag if missing or set to `OnDelete` (prefer `RollingUpdate`)
82
+ - `spec.template.spec.tolerations` — catalog which node taints are tolerated
83
+ - `spec.template.spec.nodeSelector` — catalog node selection criteria
84
+ - `spec.template.spec.priorityClassName` — note if using system priority classes
85
+
86
+ **Flag these as gaps:**
87
+ - DaemonSets without `updateStrategy` (defaults to `OnDelete`, requires manual pod deletion)
88
+ - DaemonSets without resource requests/limits (can starve node resources)
89
+ - DaemonSets with `hostNetwork: true` without documented justification
90
+ - DaemonSets without `terminationGracePeriodSeconds` set appropriately
91
+
92
+ **Severity:** `medium` for missing update strategy, `high` for unbounded resource usage
93
+
94
+ ### 7. Init Container and Sidecar Pattern Detection
95
+
96
+ Detect init containers and sidecar container patterns in Kubernetes Pods.
97
+
98
+ **Scan for:**
99
+ - `spec.initContainers` in Pod specs — catalog each init container's purpose
100
+ - Multi-container pods where one container serves as a sidecar (log collector, proxy, metrics agent)
101
+ - Istio/Envoy sidecar injection annotations: `sidecar.istio.io/inject: "true"`
102
+ - Init containers that run database migrations, config loading, or secret fetching
103
+ - Sidecar containers for: logging (fluentd, filebeat), monitoring (prometheus exporter), proxying (envoy, nginx)
104
+
105
+ **Flag these as gaps:**
106
+ - Init containers without resource limits (can block pod startup indefinitely)
107
+ - Init containers without timeout or failure handling
108
+ - Sidecar containers without health checks (liveness/readiness probes)
109
+ - Multi-container pods without clear documentation of container roles
110
+
111
+ **Severity:** `medium` for missing resource limits, `low` for missing documentation
112
+
113
+ ### 8. Health Probe Detection (Liveness, Readiness, Startup)
114
+
115
+ Detect the presence and configuration of Kubernetes health probes.
116
+
117
+ **Scan for:**
118
+ - `livenessProbe` — checks if the container is running; restarts on failure
119
+ - `readinessProbe` — checks if the container can serve traffic; removes from service on failure
120
+ - `startupProbe` — checks if the application has started; disables liveness/readiness until success
121
+
122
+ **Flag these as gaps:**
123
+ - Containers without `livenessProbe` (no automatic restart on hang)
124
+ - Containers without `readinessProbe` (may receive traffic before ready)
125
+ - Long-starting containers without `startupProbe` (liveness probe may kill them during startup)
126
+ - Probes with `initialDelaySeconds: 0` and no `startupProbe` (may restart healthy containers during startup)
127
+ - Probes using `exec` commands that could be expensive (e.g., database queries as health checks)
128
+ - Liveness and readiness probes pointing to the same endpoint (if the endpoint is slow, both fail simultaneously)
129
+ - Missing `periodSeconds`, `timeoutSeconds`, `failureThreshold` customization (relying on defaults may not suit the workload)
130
+
131
+ **Severity:** `high` for missing liveness/readiness probes, `medium` for suboptimal probe configuration
132
+
133
+ ## Output Format
134
+
135
+ Gap entry structure uses `category: "runtime-behavior"` with `id: "GAP-RUNTIME-{seq}"`.
136
+ For infra-specific findings, include "[INFRA]" prefix in the title for clarity.
137
+ Budget: max 70 entries, truncate low-severity if exceeded.
138
+
139
+ ## Output File
140
+
141
+ Write all findings to: `{planning_artifacts}/brownfield-scan-runtime-behavior.md`
@@ -0,0 +1,212 @@
1
+ # Security Endpoint Audit Scanner — Subagent Prompt
2
+
3
+ > Brownfield deep analysis scan subagent. Detects security gaps in API endpoints and infrastructure security configurations.
4
+ > Reference: Architecture ADR-021, Section 10.15.2, Section 10.15.5, ADR-022 §10.16.5
5
+ > Infra-awareness: E12-S6 — applies infra-specific patterns when project_type is infrastructure or platform.
6
+
7
+ ## Objective
8
+
9
+ Scan the codebase at `{project-path}` to catalog all API endpoints and infrastructure security configurations, and identify security gaps.
10
+
11
+ **Input variables:**
12
+ - `{tech_stack}` — Detected technology stack from Step 1 discovery
13
+ - `{project-path}` — Absolute path to the project source code directory
14
+ - `{project_type}` — Project type: `application`, `infrastructure`, or `platform`
15
+
16
+ **Output format:** Follow the gap entry schema at `{project-root}/_gaia/lifecycle/templates/gap-entry-schema.md` exactly.
17
+
18
+ ## Phase 1: Endpoint Discovery (Application Patterns)
19
+
20
+ Catalog all API endpoints. For each endpoint, record: route path, HTTP method, authentication, authorization, handler function.
21
+
22
+ ### Stack-Aware Endpoint Discovery Patterns
23
+
24
+ Apply framework-specific patterns based on {tech_stack}:
25
+
26
+ #### Java/Spring
27
+ - `@GetMapping`, `@PostMapping`, `@PutMapping`, `@DeleteMapping`, `@PatchMapping`
28
+ - `@RequestMapping(method = RequestMethod.GET)`
29
+ - `RouterFunction<ServerResponse>` (Spring WebFlux)
30
+ - `@RestController` class-level `@RequestMapping`
31
+
32
+ #### Node/Express
33
+ - `app.get()`, `app.post()`, `app.put()`, `app.delete()`, `app.patch()`
34
+ - `router.get()`, `router.post()`, `router.put()`, `router.delete()`
35
+ - `app.route().get().post()`
36
+ - `app.all()`
37
+
38
+ #### Python/Django
39
+ - `path()`, `re_path()` in `urls.py`
40
+ - `@api_view(['GET', 'POST'])`
41
+ - `class XxxViewSet(viewsets.ModelViewSet)`
42
+ - `class XxxView(APIView)`
43
+
44
+ #### Go/Gin
45
+ - `r.GET()`, `r.POST()`, `r.PUT()`, `r.DELETE()`, `r.PATCH()`
46
+ - `group.GET()`, `group.POST()`
47
+ - `http.HandleFunc()`, `http.Handle()`
48
+ - `mux.HandleFunc()`, `mux.Handle()`
49
+
50
+ ### Graceful Exit — No API Endpoints
51
+
52
+ If no API endpoints are detected, output a summary note and zero gap entries for the application phase.
53
+
54
+ ## Phase 2: Security Gap Detection — Application Rules
55
+
56
+ ### 1. Missing Authentication Middleware (AC3a)
57
+
58
+ Detect endpoints with no authentication middleware. Mutating endpoints (POST, PUT, PATCH, DELETE) missing auth are `critical`. Read endpoints (GET) missing auth that return non-public data are `high`.
59
+
60
+ ### 2. IDOR Vulnerability Detection (AC3b)
61
+
62
+ Detect endpoints where path parameters reference resources without ownership validation. IDOR vulnerabilities are `critical` severity.
63
+
64
+ ### 3. Rate Limiting Gap Detection (AC3c)
65
+
66
+ Detect endpoints without rate limiting at the application level. Missing rate limiting is `high` severity.
67
+
68
+ **Note:** Reverse proxy or API gateway rate limiting is not visible to static code analysis. Verify infrastructure-level rate limiting separately.
69
+
70
+ ### 4. Sensitive Data Exposure Detection (AC3d)
71
+
72
+ Detect endpoints whose response objects contain fields that should be filtered:
73
+ - `password`, `password_hash`, `hashed_password`
74
+ - `token`, `access_token`, `refresh_token`, `api_key`, `secret`
75
+ - `ssn`, `social_security`, `national_id`
76
+ - `credit_card`, `card_number`, `cvv`, `expiry`
77
+ - Any field matching patterns: `*_secret`, `*_key`, `*_token`
78
+
79
+ Sensitive data exposure is `high` severity.
80
+
81
+ ### 5. Missing Input Validation on Mutating Endpoints (AC3e)
82
+
83
+ Detect POST/PUT/PATCH/DELETE endpoints that accept a request body but have no input validation. Missing input validation is `high` severity.
84
+
85
+ ## Phase 3: False-Positive Mitigation — Inherited Auth
86
+
87
+ Before flagging an endpoint as "missing authentication middleware," trace the middleware chain upward:
88
+
89
+ #### Java/Spring Security
90
+ - `HttpSecurity.authorizeRequests().anyRequest().authenticated()` — app-level
91
+ - `@PreAuthorize` on controller class — class-level
92
+ - `SecurityFilterChain` bean — app-level
93
+ - `.antMatchers("/api/**").authenticated()` — path-level
94
+
95
+ #### Node/Express Middleware
96
+ - `app.use(authMiddleware)` — app-level
97
+ - `router.use(passport.authenticate('jwt'))` — router-level
98
+ - `app.use('/api', authMiddleware, apiRouter)` — path-level
99
+
100
+ #### Django Permissions
101
+ - `REST_FRAMEWORK.DEFAULT_PERMISSION_CLASSES: [IsAuthenticated]` — app-level
102
+ - `LoginRequiredMixin` — class-level
103
+ - `@login_required` — function-level
104
+
105
+ #### Go/Gin Middleware
106
+ - `r.Use(JWTAuth())` — app-level
107
+ - `group := r.Group("/api"); group.Use(AuthMiddleware())` — group-level
108
+
109
+ ## Phase 4: Infrastructure Security Patterns (E12-S6)
110
+
111
+ **Apply ONLY when {project_type} is `infrastructure` or `platform`.**
112
+
113
+ ### 4a. Exposed Ports in Kubernetes Manifests
114
+
115
+ Detect Kubernetes Services and Pods that expose ports unnecessarily or without documentation.
116
+
117
+ **Flag these:**
118
+ - `NodePort` services exposing ports to external traffic without documented justification
119
+ - `hostPort` usage in Pod specs (exposes container port on the node's IP)
120
+ - Services with `type: LoadBalancer` without IP whitelisting or security group restrictions
121
+ - Pods with `hostNetwork: true` (shares the node's network namespace)
122
+ - Containers listening on privileged ports (< 1024) without documented need
123
+
124
+ **Severity:** `high` for NodePort/LoadBalancer exposure, `critical` for hostNetwork/hostPort
125
+
126
+ ### 4b. Permissive Ingress Rules
127
+
128
+ Detect overly permissive network ingress rules in Kubernetes Ingress resources, cloud security groups, and firewall rules.
129
+
130
+ **Flag these:**
131
+ - Kubernetes Ingress resources without TLS configuration
132
+ - Ingress rules with wildcard hosts: `host: "*"` or missing host field
133
+ - AWS Security Groups with `0.0.0.0/0` ingress on non-standard ports
134
+ - Terraform `aws_security_group_rule` with `cidr_blocks = ["0.0.0.0/0"]` on ports other than 80/443
135
+ - GCP firewall rules with `source_ranges = ["0.0.0.0/0"]` without service account filtering
136
+ - Azure NSG rules with `source_address_prefix = "*"` on sensitive ports
137
+
138
+ **Severity:** `critical` for `0.0.0.0/0` on sensitive ports (SSH/22, DB/3306/5432, admin ports), `high` for permissive ingress on standard ports
139
+
140
+ ### 4c. Overly Broad RBAC Bindings
141
+
142
+ Detect Kubernetes RBAC configurations that grant excessive permissions.
143
+
144
+ **Flag these:**
145
+ - `ClusterRoleBinding` bound to `cluster-admin` for non-system service accounts
146
+ - `RoleBinding` or `ClusterRoleBinding` with `resources: ["*"]` and `verbs: ["*"]`
147
+ - Service accounts with `automountServiceAccountToken: true` when not needed
148
+ - `ClusterRole` with `apiGroups: ["*"]` granting access to all API groups
149
+ - Roles that grant `create`, `delete`, or `patch` on `secrets` without namespace scoping
150
+ - Default service account with non-default permissions
151
+
152
+ **Severity:** `critical` for cluster-admin bindings and wildcard permissions, `high` for broad secret access
153
+
154
+ ### 4d. Missing NetworkPolicy
155
+
156
+ Detect Kubernetes namespaces and workloads without NetworkPolicy enforcement.
157
+
158
+ **Flag these:**
159
+ - Namespaces with no NetworkPolicy resources defined (all traffic allowed by default)
160
+ - Pods in namespaces where NetworkPolicy exists but does not select them (via label selectors)
161
+ - NetworkPolicy with empty `ingress` or `egress` rules (allows all traffic of that type)
162
+ - Workloads in production namespaces without both ingress AND egress NetworkPolicy
163
+ - Multi-tenant clusters without namespace-level network isolation
164
+
165
+ **Severity:** `high` for missing NetworkPolicy in production, `medium` for missing in non-production
166
+
167
+ ## Output Format
168
+
169
+ ### Gap Entry Structure
170
+
171
+ Each finding MUST use the standardized gap schema from `gap-entry-schema.md`:
172
+
173
+ ```yaml
174
+ gap:
175
+ id: "GAP-SECURITY-{seq}"
176
+ category: "security-endpoint"
177
+ severity: "{critical|high}"
178
+ title: "Short description (max 80 chars)"
179
+ description: "What was found, why it matters, what security implication it has"
180
+ evidence:
181
+ file: "relative/path/to/file"
182
+ line: 42
183
+ recommendation: "Actionable fix — add middleware, validate input, filter response"
184
+ verified_by: "machine-detected"
185
+ confidence: "{high|medium|low}"
186
+ ```
187
+
188
+ ### Confidence Classification
189
+
190
+ - **high** — exact pattern match (e.g., no auth decorator/annotation on a `@PostMapping` handler)
191
+ - **medium** — heuristic match (e.g., handler accesses path parameter without obvious ownership check)
192
+ - **low** — ambiguous case (e.g., custom auth mechanism not recognized by pattern table)
193
+
194
+ ### Budget Enforcement
195
+
196
+ Each gap entry should average approximately 100 tokens in structured YAML format.
197
+ Maximum output: 70 gap entries per scan.
198
+
199
+ If more than 70 gaps are detected:
200
+ 1. Sort all findings by severity (critical > high)
201
+ 2. Within same severity, sort by confidence (high > medium > low)
202
+ 3. Keep the top 70 entries
203
+ 4. Append a budget summary section:
204
+
205
+ ```markdown
206
+ ## Budget Summary
207
+ Total gaps detected: {N}. Showing top 70 by severity. Omitted: {N-70} entries.
208
+ ```
209
+
210
+ ## Output File
211
+
212
+ Write all findings to: `{planning_artifacts}/brownfield-scan-security.md`
@@ -0,0 +1,247 @@
1
+ # Gap Entry Schema
2
+
3
+ > **Version:** 1.1.0
4
+ > **Story:** E11-S1, E12-S5
5
+ > **Traces to:** FR-111, FR-123, US-38, ADR-021, ADR-022
6
+ >
7
+ > Standardized output schema for brownfield scan subagents (E11).
8
+ > All scan agents MUST format gap entries using this schema.
9
+ > Infra-specific categories added for infrastructure/platform project support (E12-S5).
10
+ > Location: `_gaia/lifecycle/templates/gap-entry-schema.md`
11
+
12
+ ## Schema Definition
13
+
14
+ Each gap entry is a YAML object with the following fields:
15
+
16
+ ```yaml
17
+ id: "GAP-{scan_type}-{seq}"
18
+ category: "<enum>"
19
+ severity: "<enum>"
20
+ title: "<string>"
21
+ description: "<string>"
22
+ evidence:
23
+ file: "<relative-path>"
24
+ line: <number-or-range>
25
+ recommendation: "<string>"
26
+ verified_by: "<agent-id>"
27
+ confidence: "<enum>"
28
+ ```
29
+
30
+ ## Field Reference
31
+
32
+ | Field | Type | Required | Description |
33
+ |-------|------|----------|-------------|
34
+ | `id` | string | yes | Unique identifier. Format: `GAP-{scan_type}-{seq}` where `scan_type` maps to the category and `seq` is a zero-padded 3-digit sequence (e.g., `GAP-dead-code-001`) |
35
+ | `category` | enum | yes | Gap classification — must be one of the 12 allowed values (see Category Enum) |
36
+ | `severity` | enum | yes | Impact level — must be one of the 5 allowed values (see Severity Enum) |
37
+ | `title` | string | yes | Short summary of the gap (max 80 characters) |
38
+ | `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
+ | `recommendation` | string | yes | Actionable fix or remediation guidance |
41
+ | `verified_by` | string | yes | ID of the scan agent that produced this finding (e.g., `dead-code-analyzer`, `config-scanner`) |
42
+ | `confidence` | enum | yes | Agent's confidence in the finding accuracy (see Confidence Enum) |
43
+
44
+ ## Enums
45
+
46
+ ### Severity Enum
47
+
48
+ | Value | Description |
49
+ |-------|-------------|
50
+ | `critical` | Blocks deployment or causes data loss |
51
+ | `high` | Significant risk requiring prompt attention |
52
+ | `medium` | Moderate risk, should be addressed in current sprint |
53
+ | `low` | Minor issue, can be deferred |
54
+ | `info` | Informational finding, no immediate action needed |
55
+
56
+ ### Category Enum
57
+
58
+ 12 categories total — 7 application categories (E11-S1) plus 5 infrastructure categories (E12-S5):
59
+
60
+ #### Application Categories (7)
61
+
62
+ | Value | Scan Agent | Description |
63
+ |-------|------------|-------------|
64
+ | `config-contradiction` | E11-S2 | Configuration files contradict each other or runtime behavior |
65
+ | `dead-code` | E11-S3 | Unreachable code, unused exports, orphaned files |
66
+ | `hard-coded-logic` | E11-S4 | Magic numbers, embedded URLs, environment-specific constants |
67
+ | `security-endpoint` | E11-S5 | Unprotected routes, missing auth, exposed secrets |
68
+ | `runtime-behavior` | E11-S6 | Behavior that only manifests at runtime (race conditions, memory leaks) |
69
+ | `doc-code-drift` | E11-S7 | Documentation does not match actual code behavior |
70
+ | `integration-seam` | E11-S8 | Fragile integration points, tight coupling, missing contracts |
71
+
72
+ #### Infrastructure Categories (5) — ADR-022 §10.16.5
73
+
74
+ | Value | Infra PRD Section | Description |
75
+ |-------|-------------------|-------------|
76
+ | `resource-drift` | Resource Specifications | Declared infrastructure state differs from actual deployed state (e.g., Terraform state mismatch, orphaned cloud resources) |
77
+ | `config-sprawl` | Environment Strategy & DX | Configuration values duplicated across multiple files without a single source of truth (e.g., same port in Dockerfile, Helm values, and Terraform variables) |
78
+ | `secret-exposure` | Security Posture | Secrets, credentials, or sensitive values present in source files, environment configs, or IaC definitions without proper secrets management |
79
+ | `missing-policy` | Verification Strategy | Infrastructure lacks policy-as-code enforcement (e.g., no OPA/Rego, no Checkov rules, no tfsec scans for security/compliance) |
80
+ | `environment-skew` | Environment Strategy & DX | Environment definitions (dev/staging/prod) have inconsistent resource specifications, missing parity, or undocumented differences |
81
+
82
+ ### Confidence Enum
83
+
84
+ | Value | Description |
85
+ |-------|-------------|
86
+ | `high` | Strong evidence, verified through multiple signals |
87
+ | `medium` | Reasonable evidence, single signal source |
88
+ | `low` | Weak evidence, needs human verification |
89
+
90
+ ## Evidence Object
91
+
92
+ The `evidence` field is a composite object grouping source location data:
93
+
94
+ ```yaml
95
+ evidence:
96
+ file: "src/services/auth.ts" # Relative path from project root (non-empty string)
97
+ line: 42 # Single line number
98
+ ```
99
+
100
+ Or with a line range:
101
+
102
+ ```yaml
103
+ evidence:
104
+ file: "config/database.yml"
105
+ line: "15-28" # Line range (start-end)
106
+ ```
107
+
108
+ | Sub-field | Type | Required | Constraints |
109
+ |-----------|------|----------|-------------|
110
+ | `file` | string | yes | Relative path from project root. Must be non-empty. |
111
+ | `line` | number or string | yes | Single line number (integer) or range as `"start-end"` string |
112
+
113
+ ## ID Format
114
+
115
+ Pattern: `GAP-{scan_type}-{seq}`
116
+
117
+ - `scan_type` is the category value (e.g., `dead-code`, `config-contradiction`)
118
+ - `seq` is a zero-padded 3-digit sequence number starting at 001
119
+ - Regex: `^GAP-(config-contradiction|dead-code|hard-coded-logic|security-endpoint|runtime-behavior|doc-code-drift|integration-seam|resource-drift|config-sprawl|secret-exposure|missing-policy|environment-skew)-\d{3}$`
120
+
121
+ The `scan_type` component in the ID maps directly to the `category` value. See the Category Enum tables (Application + Infrastructure) for the full list of valid scan types.
122
+
123
+ ## Validation Rules
124
+
125
+ All fields listed in the Field Reference are **required** — a gap entry with any missing field is invalid.
126
+
127
+ ### Enum Validation
128
+
129
+ - `severity` must be exactly one of: `critical`, `high`, `medium`, `low`, `info`
130
+ - `category` must be exactly one of: `config-contradiction`, `dead-code`, `hard-coded-logic`, `security-endpoint`, `runtime-behavior`, `doc-code-drift`, `integration-seam`, `resource-drift`, `config-sprawl`, `secret-exposure`, `missing-policy`, `environment-skew`
131
+ - `confidence` must be exactly one of: `high`, `medium`, `low`
132
+ - Any value not in the enum set must be rejected
133
+
134
+ ### Format Validation
135
+
136
+ - `id` must match the regex `^GAP-(config-contradiction|dead-code|hard-coded-logic|security-endpoint|runtime-behavior|doc-code-drift|integration-seam|resource-drift|config-sprawl|secret-exposure|missing-policy|environment-skew)-\d{3}$`
137
+ - `evidence.file` must be a non-empty string containing a relative path (no leading `/`)
138
+ - `evidence.line` must be a positive integer or a range string matching `^\d+-\d+$`
139
+ - `title` should not exceed 80 characters
140
+ - `verified_by` must be a non-empty string identifying the scan agent
141
+
142
+ ### Required vs Optional
143
+
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.
145
+
146
+ ## Budget Control
147
+
148
+ Each gap entry should average approximately **100 tokens** in structured YAML format (per NFR-024).
149
+
150
+ Guidelines:
151
+ - Use structured YAML, not prose paragraphs
152
+ - Keep `title` under 80 characters
153
+ - Keep `description` to 1-2 sentences
154
+ - Keep `recommendation` to 1-2 sentences
155
+ - Avoid embedding full code snippets in descriptions — reference via `evidence` instead
156
+
157
+ With 12 categories across application and infrastructure scans, total token usage varies by project type. After consolidation and deduplication (E11-S10), the single `consolidated-gaps.md` must stay within the 40K framework context budget.
158
+
159
+ ## Examples
160
+
161
+ ### Application Category Example
162
+
163
+ ```yaml
164
+ id: "GAP-config-contradiction-001"
165
+ category: "config-contradiction"
166
+ severity: "high"
167
+ title: "Database timeout mismatch between config files"
168
+ description: "production.yaml sets db.timeout to 30s while docker-compose.yml sets POSTGRES_TIMEOUT to 10s."
169
+ evidence:
170
+ file: "config/production.yaml"
171
+ line: 18
172
+ recommendation: "Align timeout values. Set both to 30s or extract to a shared environment variable."
173
+ verified_by: "config-scanner"
174
+ confidence: "high"
175
+ ```
176
+
177
+ ### Infrastructure Category Examples
178
+
179
+ ```yaml
180
+ id: "GAP-resource-drift-001"
181
+ category: "resource-drift"
182
+ severity: "high"
183
+ title: "Terraform state shows orphaned S3 bucket"
184
+ description: "S3 bucket 'app-logs-legacy' exists in AWS but is not declared in any Terraform configuration."
185
+ evidence:
186
+ file: "infra/terraform/storage.tf"
187
+ line: "1-45"
188
+ recommendation: "Import the bucket into Terraform state or delete it if no longer needed."
189
+ verified_by: "infra-drift-scanner"
190
+ confidence: "high"
191
+ ```
192
+
193
+ ```yaml
194
+ id: "GAP-config-sprawl-001"
195
+ category: "config-sprawl"
196
+ severity: "medium"
197
+ title: "Database port duplicated across 4 config files"
198
+ description: "Port 5432 is hardcoded in Dockerfile, docker-compose.yml, Helm values.yaml, and Terraform variables.tf."
199
+ evidence:
200
+ file: "docker-compose.yml"
201
+ line: 14
202
+ recommendation: "Extract database port to a single environment variable, reference it from all 4 files."
203
+ verified_by: "config-sprawl-scanner"
204
+ confidence: "high"
205
+ ```
206
+
207
+ ```yaml
208
+ id: "GAP-secret-exposure-001"
209
+ category: "secret-exposure"
210
+ severity: "critical"
211
+ title: "AWS access key embedded in Terraform variables"
212
+ description: "AWS_ACCESS_KEY_ID is set as a default value in variables.tf instead of using a secrets manager."
213
+ evidence:
214
+ file: "infra/terraform/variables.tf"
215
+ line: 23
216
+ recommendation: "Remove the default value, use AWS SSM Parameter Store or HashiCorp Vault."
217
+ verified_by: "secret-scanner"
218
+ confidence: "high"
219
+ ```
220
+
221
+ ```yaml
222
+ id: "GAP-missing-policy-001"
223
+ category: "missing-policy"
224
+ severity: "medium"
225
+ title: "No policy-as-code enforcement for Kubernetes manifests"
226
+ description: "Kubernetes deployments lack OPA/Gatekeeper or Kyverno policies for security constraints."
227
+ evidence:
228
+ file: "k8s/deployments/api-server.yaml"
229
+ line: "1-30"
230
+ recommendation: "Add OPA Gatekeeper constraints or Kyverno policies to enforce pod security standards."
231
+ verified_by: "policy-scanner"
232
+ confidence: "medium"
233
+ ```
234
+
235
+ ```yaml
236
+ id: "GAP-environment-skew-001"
237
+ category: "environment-skew"
238
+ severity: "high"
239
+ title: "Staging uses 2 replicas while production uses 5"
240
+ description: "Replica counts differ between staging and production with no documented justification."
241
+ evidence:
242
+ file: "k8s/overlays/staging/deployment-patch.yaml"
243
+ line: 8
244
+ recommendation: "Document the replica difference rationale or align staging proportionally."
245
+ verified_by: "env-skew-scanner"
246
+ confidence: "high"
247
+ ```