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.
- package/CLAUDE.md +16 -1
- package/README.md +2 -2
- package/_gaia/_config/global.yaml +1 -1
- package/_gaia/core/engine/workflow.xml +6 -0
- package/_gaia/core/protocols/review-gate-check.xml +29 -1
- package/_gaia/lifecycle/knowledge/brownfield/config-contradiction-scan.md +137 -0
- package/_gaia/lifecycle/knowledge/brownfield/dead-code-scan.md +179 -0
- package/_gaia/lifecycle/knowledge/brownfield/test-execution-scan.md +209 -0
- package/_gaia/lifecycle/skills/document-rulesets.md +91 -6
- package/_gaia/lifecycle/templates/brownfield-scan-doc-code-prompt.md +219 -0
- package/_gaia/lifecycle/templates/brownfield-scan-hardcoded-prompt.md +169 -0
- package/_gaia/lifecycle/templates/brownfield-scan-integration-seam-prompt.md +127 -0
- package/_gaia/lifecycle/templates/brownfield-scan-runtime-behavior-prompt.md +141 -0
- package/_gaia/lifecycle/templates/brownfield-scan-security-prompt.md +212 -0
- package/_gaia/lifecycle/templates/gap-entry-schema.md +247 -0
- package/_gaia/lifecycle/templates/infra-prd-template.md +356 -0
- package/_gaia/lifecycle/templates/platform-prd-template.md +431 -0
- package/_gaia/lifecycle/templates/prd-template.md +70 -0
- package/_gaia/lifecycle/workflows/4-implementation/add-feature/checklist.md +1 -1
- package/_gaia/lifecycle/workflows/4-implementation/add-feature/instructions.xml +2 -3
- package/_gaia/lifecycle/workflows/4-implementation/add-stories/checklist.md +5 -0
- package/_gaia/lifecycle/workflows/4-implementation/add-stories/instructions.xml +73 -1
- package/_gaia/lifecycle/workflows/4-implementation/create-story/instructions.xml +1 -1
- package/_gaia/lifecycle/workflows/4-implementation/retrospective/instructions.xml +21 -1
- package/_gaia/lifecycle/workflows/4-implementation/retrospective/workflow.yaml +1 -1
- package/_gaia/lifecycle/workflows/anytime/brownfield-onboarding/checklist.md +12 -0
- package/_gaia/lifecycle/workflows/anytime/brownfield-onboarding/instructions.xml +244 -4
- package/_gaia/lifecycle/workflows/anytime/brownfield-onboarding/workflow.yaml +1 -0
- package/bin/gaia-framework.js +8 -6
- package/gaia-install.sh +28 -20
- 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
|
+
```
|