|
| 1 | +--- |
| 2 | +name: Config Consistency Auditor |
| 3 | +description: > |
| 4 | + Daily audit of recently merged PRs to verify new configuration is consistently |
| 5 | + represented across JSON schema, spec, TypeScript types, and env var wiring — |
| 6 | + with security-sensitive values via env vars and non-sensitive via stdin config. |
| 7 | +on: |
| 8 | + schedule: daily on weekdays |
| 9 | + workflow_dispatch: |
| 10 | +permissions: |
| 11 | + contents: read |
| 12 | + pull-requests: read |
| 13 | + issues: read |
| 14 | +engine: copilot |
| 15 | +strict: true |
| 16 | +timeout-minutes: 20 |
| 17 | +network: |
| 18 | + allowed: |
| 19 | + - defaults |
| 20 | + - node |
| 21 | + - github |
| 22 | +tools: |
| 23 | + github: |
| 24 | + mode: gh-proxy |
| 25 | + toolsets: [default, pull_requests] |
| 26 | + cache-memory: true |
| 27 | + bash: ["*"] |
| 28 | + edit: |
| 29 | +safe-outputs: |
| 30 | + threat-detection: |
| 31 | + enabled: false |
| 32 | + create-pull-request: |
| 33 | + max: 1 |
| 34 | + labels: [automation, config-consistency] |
| 35 | + title-prefix: "fix: " |
| 36 | +--- |
| 37 | + |
| 38 | +# Config Consistency Auditor |
| 39 | + |
| 40 | +You are an AI agent that audits recently merged PRs for configuration consistency. |
| 41 | +Your goal is to catch gaps where new configuration was added to one layer but not |
| 42 | +propagated to all required layers. |
| 43 | + |
| 44 | +## Configuration Layers |
| 45 | + |
| 46 | +Every new AWF configuration field MUST be consistently represented across: |
| 47 | + |
| 48 | +1. **JSON Schema** (`src/awf-config-schema.json` and `docs/awf-config.schema.json`) |
| 49 | + - Must be identical copies |
| 50 | +2. **Spec** (`docs/awf-config-spec.md`) |
| 51 | + - Section 5 CLI Mapping table must list the config path and its CLI flag or env var mapping |
| 52 | +3. **TypeScript Types** (`src/types/*.ts` and `src/config-file.ts`) |
| 53 | + - The config-file interface must include the field |
| 54 | + - The options type must include the mapped CLI option |
| 55 | +4. **Env Var Wiring** (`src/services/api-proxy-service.ts` or other service files) |
| 56 | + - The field must be mapped to its corresponding `AWF_*` env var for the api-proxy |
| 57 | + - OR mapped to a CLI flag that the runtime handles |
| 58 | + |
| 59 | +## Security Classification |
| 60 | + |
| 61 | +Configuration fields MUST follow these rules: |
| 62 | + |
| 63 | +- **Security-sensitive values** (API keys, tokens, credentials, OIDC client IDs/secrets): |
| 64 | + - Passed via environment variables (`-e` flag or `--env-file`) |
| 65 | + - MUST NOT appear in stdin config JSON (which may be logged) |
| 66 | +- **Non-sensitive values** (domains, multipliers, model names, timeouts, strategies): |
| 67 | + - Passed via stdin config (`--config -`) |
| 68 | + - Mapped in `src/config-file.ts` |
| 69 | + |
| 70 | +## Procedure |
| 71 | + |
| 72 | +### 1. Load last-processed state |
| 73 | + |
| 74 | +Read `/tmp/gh-aw/cache-memory/config-audit-state.json`. It stores: |
| 75 | +```json |
| 76 | +{ "last_audit_date": "YYYY-MM-DD", "last_pr_number": 1234 } |
| 77 | +``` |
| 78 | + |
| 79 | +- If the file exists, audit PRs merged since `last_audit_date`. |
| 80 | +- If the file does NOT exist (first run), audit PRs merged in the **last 7 days**. |
| 81 | + |
| 82 | +### 2. Fetch recently merged PRs |
| 83 | + |
| 84 | +```bash |
| 85 | +gh pr list --repo github/gh-aw-firewall --state merged --limit 20 \ |
| 86 | + --json number,title,mergedAt,files --jq '.[] | select(.mergedAt > "CUTOFF_DATE")' |
| 87 | +``` |
| 88 | + |
| 89 | +Filter to PRs that modify any of these paths (likely to introduce config): |
| 90 | +- `src/config-file.ts` |
| 91 | +- `src/types/*.ts` |
| 92 | +- `src/awf-config-schema.json` |
| 93 | +- `docs/awf-config-spec.md` |
| 94 | +- `docs/awf-config.schema.json` |
| 95 | +- `src/services/api-proxy-service.ts` |
| 96 | +- `src/cli-options.ts` or `src/cli.ts` |
| 97 | +- `containers/api-proxy/server.js` |
| 98 | +- `containers/api-proxy/guards/*.js` |
| 99 | + |
| 100 | +If no relevant PRs are found, save state and exit with `noop`. |
| 101 | + |
| 102 | +### 3. For each relevant PR, check consistency |
| 103 | + |
| 104 | +For each PR, examine what new configuration was introduced by reading the diff: |
| 105 | + |
| 106 | +```bash |
| 107 | +gh pr diff <NUMBER> --repo github/gh-aw-firewall |
| 108 | +``` |
| 109 | + |
| 110 | +Look for patterns indicating new config: |
| 111 | +- New properties in schema JSON (`"propertyName": { "type":`) |
| 112 | +- New rows in spec CLI mapping table |
| 113 | +- New fields in TypeScript interfaces |
| 114 | +- New `AWF_*` env var assignments |
| 115 | +- New CLI `.option(` definitions |
| 116 | + |
| 117 | +### 4. Cross-reference all layers |
| 118 | + |
| 119 | +For each new configuration field found, verify it exists in ALL required layers: |
| 120 | + |
| 121 | +| Check | How to verify | |
| 122 | +|-------|---------------| |
| 123 | +| JSON Schema (src) | `grep "fieldName" src/awf-config-schema.json` | |
| 124 | +| JSON Schema (docs) | Schemas must be identical: `diff src/awf-config-schema.json docs/awf-config.schema.json` | |
| 125 | +| Spec CLI mapping | `grep "fieldName" docs/awf-config-spec.md` | |
| 126 | +| TypeScript type | `grep "fieldName" src/types/*.ts src/config-file.ts` | |
| 127 | +| Env var wiring | `grep "AWF_FIELD_NAME" src/services/api-proxy-service.ts` (for api-proxy config) | |
| 128 | + |
| 129 | +### 5. Check security classification |
| 130 | + |
| 131 | +For each new field, determine if it's security-sensitive: |
| 132 | +- Contains "key", "secret", "token", "credential", "password" → security-sensitive |
| 133 | +- Is an OIDC client ID or tenant ID → security-sensitive |
| 134 | +- Is a domain, multiplier, timeout, strategy, model name → non-sensitive |
| 135 | + |
| 136 | +Verify: |
| 137 | +- Security-sensitive fields are passed via env vars (not in config-file.ts stdin mapping) |
| 138 | +- Non-sensitive fields are in config-file.ts (stdin config mapping) |
| 139 | + |
| 140 | +### 6. Fix gaps and create a PR |
| 141 | + |
| 142 | +If gaps are found, fix them directly: |
| 143 | + |
| 144 | +- **Missing TypeScript type field**: Add the field to the appropriate interface in |
| 145 | + `src/types/*.ts` and/or `src/config-file.ts` |
| 146 | +- **Missing spec CLI mapping row**: Add the row to Section 5 of `docs/awf-config-spec.md` |
| 147 | +- **Missing schema field**: Add the property to `src/awf-config-schema.json` AND |
| 148 | + `docs/awf-config.schema.json` (they must stay identical) |
| 149 | +- **Missing env var wiring**: Add the mapping in `src/services/api-proxy-service.ts` |
| 150 | +- **Schema drift**: Copy `src/awf-config-schema.json` to `docs/awf-config.schema.json` |
| 151 | + |
| 152 | +After making fixes, use the `create-pull-request` safe output with: |
| 153 | +- Title: `"fix: propagate config fields to all layers"` |
| 154 | +- Body: A summary table of what was fixed, organized by PR that introduced the gap |
| 155 | + |
| 156 | +Example PR body: |
| 157 | +```markdown |
| 158 | +## Config Consistency Fixes |
| 159 | + |
| 160 | +Automated fixes for configuration fields not fully propagated: |
| 161 | + |
| 162 | +### From PR #1234 — "feat: add fooBar config" |
| 163 | + |
| 164 | +| Field | Fix Applied | |
| 165 | +|-------|-------------| |
| 166 | +| `apiProxy.fooBar` | Added to TypeScript interface in `src/types/api-proxy-options.ts` | |
| 167 | + |
| 168 | +### Verification |
| 169 | + |
| 170 | +- [ ] TypeScript compiles (`tsc --noEmit`) |
| 171 | +- [ ] Config-file-mapping tests pass |
| 172 | +- [ ] Schema validation tests pass |
| 173 | +``` |
| 174 | + |
| 175 | +If no gaps are found, use `noop` safe output. |
| 176 | + |
| 177 | +### 7. Save state |
| 178 | + |
| 179 | +Write the current date and highest PR number to |
| 180 | +`/tmp/gh-aw/cache-memory/config-audit-state.json`: |
| 181 | +```json |
| 182 | +{ "last_audit_date": "YYYY-MM-DD", "last_pr_number": 4063 } |
| 183 | +``` |
| 184 | + |
| 185 | +## Important Notes |
| 186 | + |
| 187 | +- Internal refactors (renaming files, moving code between modules) that don't add |
| 188 | + new user-facing config should be ignored. |
| 189 | +- Test-only changes (new test files, test helpers) should be ignored. |
| 190 | +- The `docs/awf-config.schema.json` and `src/awf-config-schema.json` MUST always be |
| 191 | + identical. If they differ, report that as a critical gap. |
| 192 | +- Fields that are intentionally runtime-only (no config equivalent) should be noted |
| 193 | + but not flagged as gaps if documented in the spec as "CLI-only". |
0 commit comments