(_ctx: TemplateContext, args?: string[])
| 64 | }; |
| 65 | |
| 66 | export function generateRedactTaxonomyTable(_ctx: TemplateContext, args?: string[]): string { |
| 67 | // Compact mode: HIGH-tier rows only (the credentials that BLOCK), one line of |
| 68 | // prose for MEDIUM/LOW. For skills that RUN redaction (e.g. /spec) but aren't |
| 69 | // the security catalog — they need to know what blocks + where the full list |
| 70 | // is, not inline all ~30 patterns. /cso renders the full table. |
| 71 | const compact = args?.[0] === 'compact'; |
| 72 | const out: string[] = []; |
| 73 | |
| 74 | const tiers: Tier[] = compact ? ['HIGH'] : ['HIGH', 'MEDIUM', 'LOW']; |
| 75 | for (const tier of tiers) { |
| 76 | out.push(`**${TIER_BLURB[tier]}**`, ''); |
| 77 | out.push('| ID | Catches | Example |'); |
| 78 | out.push('|----|---------|---------|'); |
| 79 | for (const p of PATTERNS.filter((x) => x.tier === tier)) { |
| 80 | out.push(`| \`${p.id}\` | ${p.description} | ${EXAMPLE[p.id] ?? '—'} |`); |
| 81 | } |
| 82 | out.push(''); |
| 83 | } |
| 84 | |
| 85 | if (compact) { |
| 86 | out.push( |
| 87 | 'MEDIUM (PII / legal / internal + high-FP credential shapes like ' + |
| 88 | '`pk_live_`/`AIza`/JWT/`*_KEY=`) confirms via AskUserQuestion; LOW surfaces ' + |
| 89 | 'as an FYI. Full taxonomy: `lib/redact-patterns.ts` (or `/cso`).', |
| 90 | ); |
| 91 | } else { |
| 92 | out.push( |
| 93 | 'Calibration: a gate that cries wolf gets ignored, so context-variable / ' + |
| 94 | 'high-FP credential shapes (Stripe publishable `pk_live_`, Google `AIza`, ' + |
| 95 | 'JWTs, env-style `*_KEY=`) sit at MEDIUM, not HIGH. The full taxonomy lives ' + |
| 96 | 'in `lib/redact-patterns.ts` and this table is generated from it.', |
| 97 | ); |
| 98 | } |
| 99 | return out.join('\n'); |
| 100 | } |
| 101 | |
| 102 | // ── Invocation block (scan-at-sink) ────────────────────────────────────────── |
| 103 |
no test coverage detected