@event4u/agent-config 8.7.0 → 8.8.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 (83) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +52 -0
  3. package/CONTRIBUTING.md +25 -0
  4. package/README.md +7 -4
  5. package/dist/agent-src/contexts/execution/auto-orchestration-activation.md +1 -1
  6. package/dist/agent-src/contexts/execution/orchestration-benchmark-gate.md +28 -16
  7. package/dist/agent-src/contexts/execution/orchestration-telemetry.md +15 -0
  8. package/dist/agent-src/rules/active-remediation.md +92 -0
  9. package/dist/agent-src/rules/broken-access-control.md +106 -0
  10. package/dist/agent-src/rules/communication-through-line.md +42 -0
  11. package/dist/agent-src/rules/decision-revisit-gate.md +8 -0
  12. package/dist/agent-src/rules/minimal-safe-diff.md +18 -1
  13. package/dist/agent-src/rules/prefer-enums-over-literals.md +65 -0
  14. package/dist/agent-src/rules/senior-engineering-discipline.md +82 -0
  15. package/dist/agent-src/skills/ai-code-blindspots/SKILL.md +105 -0
  16. package/dist/agent-src/skills/ai-code-blindspots/evals/triggers.json +52 -0
  17. package/dist/agent-src/skills/authz-review/SKILL.md +21 -4
  18. package/dist/agent-src/skills/dependency-upgrade/SKILL.md +20 -0
  19. package/dist/agent-src/skills/frontend-render-security/SKILL.md +104 -0
  20. package/dist/agent-src/skills/frontend-render-security/evals/triggers.json +52 -0
  21. package/dist/agent-src/skills/roadmap-writing/SKILL.md +7 -0
  22. package/dist/agent-src/skills/supply-chain-intake/SKILL.md +100 -0
  23. package/dist/agent-src/skills/supply-chain-intake/evals/triggers.json +52 -0
  24. package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +43 -2
  25. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  26. package/dist/agent-src/templates/roadmaps.md +24 -0
  27. package/dist/discovery/deprecation-report.md +1 -1
  28. package/dist/discovery/discovery-manifest.json +195 -15
  29. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  30. package/dist/discovery/discovery-manifest.summary.md +3 -3
  31. package/dist/discovery/orphan-report.md +1 -1
  32. package/dist/discovery/packs.json +13 -5
  33. package/dist/discovery/trust-report.md +11 -11
  34. package/dist/discovery/workspaces.json +12 -4
  35. package/dist/install/install.mjs +5 -2
  36. package/dist/mcp/awesome-mcp-servers.row.md +1 -1
  37. package/dist/mcp/mcp-cloudflare-catalogue.json +1 -1
  38. package/dist/mcp/registry-manifest.json +4 -4
  39. package/dist/router.json +1 -1
  40. package/dist/server/schemas/settings.js +2 -1
  41. package/dist/server/schemas/settings.js.map +1 -1
  42. package/docs/CLAIMS.md +30 -2
  43. package/docs/architecture.md +2 -2
  44. package/docs/catalog.md +14 -0
  45. package/docs/contracts/mcp-tool-inventory.md +31 -30
  46. package/docs/decisions/ADR-105-automatic-subagent-orchestration.md +6 -0
  47. package/docs/decisions/ADR-116-memory-tripwire-activation-path.md +2 -2
  48. package/docs/decisions/ADR-117-subagents-auto-default-on.md +88 -0
  49. package/docs/decisions/INDEX.md +1 -0
  50. package/docs/experiences/content_creator.md +2 -0
  51. package/docs/experiences/finance.md +2 -0
  52. package/docs/experiences/founder.md +2 -0
  53. package/docs/experiences/ops.md +2 -0
  54. package/docs/featured-skills.md +2 -2
  55. package/docs/getting-started-by-role.md +1 -1
  56. package/docs/getting-started.md +1 -1
  57. package/docs/governance-advantage.md +1 -1
  58. package/docs/guidelines/agent-infra/memory-access.md +12 -0
  59. package/docs/proof.md +45 -3
  60. package/docs/release-runbook.md +138 -0
  61. package/docs/second-brain-scope.md +73 -0
  62. package/docs/succession.md +80 -0
  63. package/package.json +2 -2
  64. package/src/config/agent-settings.template.yml +25 -6
  65. package/src/scripts/_lib/orchestration_gate.ts +12 -8
  66. package/src/scripts/_lib/orchestration_savings.ts +127 -0
  67. package/src/scripts/build_proof.ts +38 -0
  68. package/src/scripts/chat_history.ts +79 -7
  69. package/src/scripts/domain_soundness_status.ts +236 -0
  70. package/src/scripts/generate_index.ts +14 -0
  71. package/src/scripts/hot_context_hook.ts +47 -2
  72. package/src/scripts/lint_behavioural_eval_freshness.ts +140 -0
  73. package/src/scripts/mcp_server/consumer_tool_catalog.json +22 -3
  74. package/src/scripts/mcp_server/tools.ts +159 -1
  75. package/src/scripts/memory_lookup.ts +184 -6
  76. package/src/scripts/memory_replay.ts +285 -0
  77. package/src/scripts/orchestration_savings_report.ts +100 -0
  78. package/src/scripts/schemas/domain-truth.schema.json +94 -0
  79. package/src/scripts/schemas/evals.schema.json +113 -0
  80. package/src/scripts/second_brain_score.ts +186 -0
  81. package/src/scripts/session_memory_index.ts +94 -0
  82. package/src/scripts/skill_eval_coverage.ts +318 -0
  83. package/src/server/schemas/settings.ts +5 -2
@@ -0,0 +1,82 @@
1
+ ---
2
+ type: "auto"
3
+ tier: "2b"
4
+ alwaysApply: false
5
+ description: "Writing/generating code — generalize (no overfit or tautological tests), supply the invisible cross-cutting controls the prompt didn't name, never invent an API/field/package"
6
+ triggers:
7
+ - intent: "writing or generating code"
8
+ - intent: "implementing a feature"
9
+ - keyword: "implement"
10
+ - keyword: "endpoint"
11
+ - keyword: "query"
12
+ - keyword: "migration"
13
+ - keyword: "component"
14
+ - keyword: "seeder"
15
+ - keyword: "dependency"
16
+ - keyword: "refactor"
17
+ routes_to:
18
+ - "skill:ai-code-blindspots"
19
+ - "skill:frontend-render-security"
20
+ - "skill:supply-chain-intake"
21
+ - "skill:testing-anti-patterns"
22
+ workspaces: [engineering]
23
+ packs: [engineering-base]
24
+ ---
25
+
26
+ # Senior Engineering Discipline
27
+
28
+ Dominant failure mode of AI-written code isn't ignorance — **omission**. Model writes happy-path code satisfying the literal task + passing shallow tests, silently drops the invisible cross-cutting controls a senior supplies from unstated context. Baseline (2025 studies): a large share of AI-generated code ships a known vulnerability even at high syntax-correctness, and automation bias makes devs trust it *more* while it's *less* safe. Write like a senior: general not overfit; invisible controls present; verified against real sources, not memory. Act like a senior **owner**, not a passive typist — work in the interest of the product, the user, and the company, especially on security and quality; see a problem → react (fix it if small and task-aligned, else ask — per [`active-remediation`](active-remediation.md)) — never look away.
29
+
30
+ ## The Iron Law
31
+
32
+ ```
33
+ CODE AND TESTS EXPRESS THE GENERAL RULE — NEVER OVERFIT TO A FIXED CASE.
34
+ SUPPLY THE INVISIBLE CROSS-CUTTING CONTROLS THE PROMPT DID NOT NAME.
35
+ NEVER INVENT AN API, FIELD, OR PACKAGE — VERIFY IT AGAINST A REAL SOURCE.
36
+ THE HAPPY PATH THAT PASSES ONE TEST IS NOT A FINISHED CHANGE.
37
+ ```
38
+
39
+ ## Three obligations, every time you write code
40
+
41
+ ### 1. Generalize — never overfit
42
+
43
+ - Implementation expresses the general rule, not a special case that happens to satisfy the example. Don't hardcode a derivable value; don't branch on one literal where a rule covers all inputs; don't paste a near-duplicate where an existing abstraction fits.
44
+ - Tests assert **general behavior**, never a fixed value or narrow regex passing only for one crafted input. Derive expected from inputs + seeded/random data — never hardcode what the code emits. Cover happy **and** boundary (empty / null / max / Unicode) **and** error **and**, on security paths, an abuse case. Lone happy-path assertion = tautology. → `skill:testing-anti-patterns`.
45
+
46
+ ### 2. Cover the invisible controls for what you touched
47
+
48
+ Before done, assert the unmentioned cross-cutting control is present, matched to surface:
49
+
50
+ - **endpoint / route** → authorization + tenant scope + input validation + rate limit; state-changing → CSRF + audit. (`security-sensitive-stop` gates the sensitive ones.)
51
+ - **database query / migration** → parameterized (never string-built), tenant-scoped, transaction around multi-step writes, reversible migration (expand-contract, never bare `DROP`), index on filtered / FK columns.
52
+ - **user-controlled render** → output-encode; never `dangerouslySetInnerHTML` / `v-html` / `innerHTML` / `eval` on non-constant input; no secret / token in client code. → `skill:frontend-render-security`.
53
+ - **file / outbound fetch** → path-confinement + SSRF allow-list; validate server-side, never client-only.
54
+ - **infra / IaC** → least-privilege (no `Action:*` / `Resource:*`), encryption at rest, no `0.0.0.0/0` to mgmt / DB ports, no hardcoded creds; real scanner (Checkov / Trivy) is the backstop — `plan` succeeding isn't.
55
+ - **new dependency** → verify it exists on the real registry before install (hallucinated / "slopsquatted" packages ~1 in 5 AI suggestions); pin + lockfile; CVE scan. → `skill:supply-chain-intake`.
56
+
57
+ Full surface→controls table + backstop greps: → `skill:ai-code-blindspots`.
58
+
59
+ ### 3. Verify — never assert from memory
60
+
61
+ No completion claim without exercising the real path (running endpoint / UI / test — not "the code looks right"). "Defined but not wired" (middleware written, never connected to the route) = **not done**. → `verify-before-complete`, `source-discovery-gate`.
62
+
63
+ ## When it fires
64
+
65
+ Any turn that writes, generates, or modifies code — feature, endpoint, query, migration, component, test, seeder, dependency, infra resource.
66
+
67
+ ## When NOT to fire
68
+
69
+ - Prose / docs / config-only edits, no code behavior.
70
+ - One-line rename / typo / formatting.
71
+ - User fenced the scope ("just this one line", "skip the checks").
72
+
73
+ ## Relationship to existing rules
74
+
75
+ Cross-cutting **anchor**; depth lives elsewhere and this routes to it. Doesn't replace `security-sensitive-stop` (threat-model before editing auth / billing / tenant / secret paths), `minimal-safe-diff` (smallest change), `think-before-action` (analyze first), `downstream-changes` (update all callers), `output-discipline` (no placeholder / TODO code). When one fires it wins on its subject; this adds the "generalized + invisible controls?" gate on top.
76
+
77
+ ## See also
78
+
79
+ - [`ai-code-blindspots`](../skills/ai-code-blindspots/SKILL.md) — surface→controls checklist + backstop greps.
80
+ - [`frontend-render-security`](../skills/frontend-render-security/SKILL.md), [`supply-chain-intake`](../skills/supply-chain-intake/SKILL.md) — the two precision gaps.
81
+ - [`testing-anti-patterns`](../skills/testing-anti-patterns/SKILL.md) — overfit / tautological assertions + test-data realism.
82
+ - [`security-sensitive-stop`](security-sensitive-stop.md), [`engineering-safety-floor`](engineering-safety-floor.md), [`verify-before-complete`](verify-before-complete.md), [`source-discovery-gate`](source-discovery-gate.md).
@@ -0,0 +1,105 @@
1
+ ---
2
+ model_tier: medium
3
+ name: ai-code-blindspots
4
+ description: "Before finishing any code (endpoint, query, migration, render, file, infra, dependency, test) — the senior pre-ship checklist of invisible cross-cutting controls AI omits, with backstop greps"
5
+ domain: quality
6
+ workspaces:
7
+ - engineering
8
+ packs:
9
+ - engineering-base
10
+ ---
11
+
12
+ # ai-code-blindspots
13
+
14
+ AI writes the code the prompt literally asked for and stops. The controls a senior adds from unstated context — authorization, tenant scope, validation, transactions, encryption, rate limiting, output encoding, error handling, edge cases, package existence — are *invisible* to a single-file prompt, so they're the first thing dropped. They're also the classes pattern-linters miss. This skill is the pre-ship checklist: for the surface you wrote, assert the matching control is present, run the backstop grep, route to the deep skill when it needs more than a check.
15
+
16
+ A **routing + verification** layer — doesn't re-teach what the deep skills own. The "did I supply the invisible controls?" gate `senior-engineering-discipline` points at.
17
+
18
+ ## When to use
19
+
20
+ - You wrote (or are finishing) an endpoint, query, migration, UI render, file/network op, infra resource, dependency change, or test — before calling it done.
21
+ - Reviewing an AI-authored diff, asking "what did it silently omit?".
22
+ - The `senior-engineering-discipline` rule fired and routed here.
23
+
24
+ Do NOT use when: change is prose/docs/config-only, or a one-line rename — no code surface to check.
25
+
26
+ ## The Iron Law
27
+
28
+ ```
29
+ FOR EVERY SURFACE YOU TOUCHED, NAME THE INVISIBLE CONTROL AND CONFIRM IT IS PRESENT.
30
+ "NOT MENTIONED IN THE PROMPT" IS EXACTLY WHY IT IS MISSING — CHECK IT ANYWAY.
31
+ A CONTROL DEFINED BUT NOT WIRED IS ABSENT. A grep IS CHEAPER THAN A BREACH.
32
+ ```
33
+
34
+ ## Procedure
35
+
36
+ 1. List the surfaces this change touched (endpoint, query, migration, render, file/fetch, infra, dependency, test).
37
+ 2. For each surface, take its row below: assert every listed invisible control is present (with file:line), and run the matching backstop grep.
38
+ 3. For anything a grep flags or a check can't confirm, open the routed deep skill.
39
+ 4. Emit the per-surface confirmation (Output format); surface any unresolved gap to the user — never silently omit.
40
+
41
+ ## Surface → invisible controls → backstop
42
+
43
+ Run the row(s) for what you touched. The grep is a fast authoring-time backstop (not a substitute for reading the code); zero results = pass, a hit = look.
44
+
45
+ | Surface you wrote | Invisible controls to assert | Deep skill |
46
+ |---|---|---|
47
+ | **HTTP endpoint / route** | authorization (this principal may act on this resource — not just authenticated); tenant scope; **the three negative tests** (unauth→401, non-owner→403/404, cross-tenant→403/404); boundary input validation; rate limit actually wired; state-changing → CSRF + audit | `broken-access-control`, `authz-review`, `threat-modeling` |
48
+ | **DB query / ORM** | parameterized, never string-built; tenant predicate present; no `SELECT *` across a serialization boundary; N+1 avoided (eager load) | `source-discovery`, `security` |
49
+ | **Migration** | reversible (`down`); expand-contract for drop/rename (never a bare `DROP COLUMN` before code stops reading it); transaction; index on new FK/filter column | `engineering-safety-floor`, `migration-architect` |
50
+ | **User-controlled render (FE)** | output-encoded; no `dangerouslySetInnerHTML`/`v-html`/`innerHTML`/`eval` on non-constant input; no secret/token in client code; token not in `localStorage` | `frontend-render-security` |
51
+ | **File / outbound fetch** | path confined to an allowed base; SSRF allow-list + private-IP block on user-supplied URLs; size limit; server-side validation (never client-only) | `security`, `defense-in-depth` |
52
+ | **Infra / IaC** | least-privilege (no `Action:*`/`Resource:*`); encryption at rest; no `0.0.0.0/0` to mgmt/DB ports; no hardcoded creds; scanner-verified, not `plan`-verified | `engineering-safety-floor`, `terraform`, `secrets-management` |
53
+ | **New dependency** | exists on the real registry (not hallucinated); not typo-adjacent to a popular one; pinned + lockfile committed; CVE-scanned | `supply-chain-intake`, `dependency-upgrade` |
54
+ | **Secrets/credentials** | never a literal in source; env / secret-manager reference; password columns use bcrypt/argon2, never MD5/SHA | `secrets-management`, `domain-safety-pii` |
55
+ | **Test** | asserts general behavior; expected derived from inputs/seeded data, not hardcoded; boundary + error + abuse cases, not only happy path | `testing-anti-patterns`, `test-driven-development` |
56
+
57
+ ### Backstop greps (authoring-time, cross-stack)
58
+
59
+ ```bash
60
+ # Frontend insecure render / client secrets (React + Vue + vanilla)
61
+ rg -n 'dangerouslySetInnerHTML|v-html|\.innerHTML\s*=|\beval\(|new Function\('
62
+ rg -n 'NEXT_PUBLIC_.*(SECRET|KEY|TOKEN)|VITE_.*(SECRET|KEY)|localStorage\.setItem\([^)]*[Tt]oken'
63
+ # String-built SQL (concatenation / interpolation into a query)
64
+ rg -n 'query\(.*(\+|\$\{|`).*\)|(SELECT|INSERT|UPDATE|DELETE).*(\+|\$\{)'
65
+ # Hardcoded secrets / weak hashing
66
+ rg -n 'AKIA[0-9A-Z]{16}|sk_live_|AIza[0-9A-Za-z_\-]{35}|password\s*=\s*["\x27]|md5\(|sha1\(' .
67
+ # Infra: wildcard IAM / open ingress / disabled TLS
68
+ rg -n '"Action"\s*:\s*"\*"|"Resource"\s*:\s*"\*"|0\.0\.0\.0/0|InsecureSkipVerify|verify=false|curl.*\| *bash' .
69
+ ```
70
+
71
+ The greps name several ecosystems side by side on purpose: keep the ones for the stack in front of you; a hit means read that line, not auto-fix.
72
+
73
+ ## Output format
74
+
75
+ 1. A one-line per-surface confirmation for the change, e.g. `endpoint: authz ✓ tenant-scope ✓ rate-limit wired ✓ validation ✓`, naming file:line where each control lives (or `n/a — <reason>`).
76
+ 2. The backstop grep(s) run for the touched surface(s), with result (zero hits, or the hit + how resolved).
77
+ 3. For any control genuinely out of scope, an explicit note saying so — never a silent omission.
78
+
79
+ ## Gotcha
80
+
81
+ - **Defined-but-not-wired** is the signature AI failure: rate-limit middleware or CSRF guard is *written* but never attached to the route. Check is "wired on THIS path?", not "exists somewhere?".
82
+ - **Semantically-valid-but-ignored**: an IaC attribute the provider silently ignores (a made-up `encrypted = true` on a resource that doesn't support it) *reads* as a present control but does nothing — a scanner catches it, a code read doesn't.
83
+ - A green grep is necessary, not sufficient — proves the obvious anti-pattern absent, not that the control is correct. Read the seam for anything security-sensitive.
84
+ - Routes; doesn't replace the deep skill. For auth/billing/tenant/secret paths, `security-sensitive-stop` still requires a threat pass *before* editing.
85
+
86
+ ## Do NOT
87
+
88
+ - Do NOT treat "the prompt didn't ask for it" as a reason to omit a control — that's the exact blind spot.
89
+ - Do NOT mark a change done on a green happy-path test alone.
90
+ - Do NOT auto-rewrite a grep hit without reading it — some are intentional and belong in an allow-list with a reason.
91
+ - Do NOT duplicate the deep skills here — route to them.
92
+
93
+ ## Auto-trigger keywords
94
+
95
+ - invisible controls
96
+ - ai code blindspots
97
+ - pre-ship checklist
98
+ - what did the AI omit
99
+ - cross-cutting controls
100
+
101
+ ## See also
102
+
103
+ - [`senior-engineering-discipline`](../../rules/senior-engineering-discipline.md) — the anchor rule that routes here.
104
+ - [`frontend-render-security`](../frontend-render-security/SKILL.md), [`supply-chain-intake`](../supply-chain-intake/SKILL.md), [`testing-anti-patterns`](../testing-anti-patterns/SKILL.md).
105
+ - [`authz-review`](../authz-review/SKILL.md), [`threat-modeling`](../threat-modeling/SKILL.md), [`defense-in-depth`](../defense-in-depth/SKILL.md), [`source-discovery`](../source-discovery/SKILL.md), [`secrets-management`](../secrets-management/SKILL.md).
@@ -0,0 +1,52 @@
1
+ {
2
+ "skill": "ai-code-blindspots",
3
+ "last_eval": "2026-07-09",
4
+ "description": "5 should-trigger + 5 should-not-trigger queries. Should-trigger covers DE + EN phrasings for the pre-ship 'what invisible cross-cutting controls did the AI omit?' checklist across code surfaces. Should-not-trigger covers near-miss neighbours (deep single-surface skills, prose/docs edits, adversarial config review) whose vocabulary overlaps.",
5
+ "queries": [
6
+ {
7
+ "q": "I just wrote this endpoint — what invisible controls did I forget before I call it done?",
8
+ "trigger": true
9
+ },
10
+ {
11
+ "q": "run the senior pre-ship checklist over this diff for cross-cutting controls",
12
+ "trigger": true
13
+ },
14
+ {
15
+ "q": "what does AI-generated code usually omit here — authz, tenant scope, validation?",
16
+ "trigger": true
17
+ },
18
+ {
19
+ "q": "prüf meinen Code auf die unsichtbaren Kontrollen, die die KI weglässt",
20
+ "trigger": true
21
+ },
22
+ {
23
+ "q": "before I finish this migration and query, what am I blind to?",
24
+ "trigger": true
25
+ },
26
+ {
27
+ "q": "review this React component specifically for XSS and client secrets",
28
+ "trigger": false,
29
+ "note": "single frontend surface → frontend-render-security"
30
+ },
31
+ {
32
+ "q": "is this npm package safe to add?",
33
+ "trigger": false,
34
+ "note": "dependency intake → supply-chain-intake"
35
+ },
36
+ {
37
+ "q": "threat-model this new payments endpoint before I build it",
38
+ "trigger": false,
39
+ "note": "pre-build threat model → threat-modeling / security-sensitive-stop"
40
+ },
41
+ {
42
+ "q": "fix the typo in this README",
43
+ "trigger": false,
44
+ "note": "prose/docs edit — no code surface"
45
+ },
46
+ {
47
+ "q": "red-team my agent's CLAUDE.md and MCP config",
48
+ "trigger": false,
49
+ "note": "agent-config adversarial review → agent-security-review"
50
+ }
51
+ ]
52
+ }
@@ -48,8 +48,10 @@ Do NOT use when:
48
48
  [`security-audit`](../security-audit/SKILL.md)
49
49
  * The concern is a diff ready for review — route to
50
50
  [`judge-security-auditor`](../judge-security-auditor/SKILL.md)
51
- * The concern is response/log leakage rather than access gating — route to
52
- [`data-exposure-review`](../data-exposure-review/SKILL.md)
51
+ * The concern is PII leakage into logs specifically — route to
52
+ [`data-flow-mapper`](../data-flow-mapper/SKILL.md). (Role-based field-level
53
+ output filtering IS access gating — it stays in scope here + the vertical-BOPLA
54
+ section of [`broken-access-control`](../../rules/broken-access-control.md).)
53
55
  * The concern is implementing a control once identified — route to
54
56
  [`security`](../security/SKILL.md)
55
57
 
@@ -71,8 +73,8 @@ For every entrypoint, analyze the authorization chain and record what you find:
71
73
  | Authentication gate | Is login enforced? By which middleware / guard? |
72
74
  | Authorization layer | Which policy, gate, voter, or check? Which action/ability? |
73
75
  | Data scope | Does the query filter by current user / tenant / owner? |
74
- | Response filter | Are sensitive fields stripped (resource/serializer/DTO)? |
75
- | Tests | Is there a negative test (other-tenant / lower-role returns 403/404)? |
76
+ | Response filter | Are sensitive fields stripped **per role** via a role-scoped resource/serializer/DTO — never the raw model? (a driver role must not receive `price`) |
77
+ | Tests | Are the three negative tests present — unauthenticated → 401, non-owner → 403/404, cross-tenant → 403/404 (404 hides existence)? |
76
78
 
77
79
  Record **what is there**, not what should be there. Use file:line citations.
78
80
 
@@ -160,6 +162,17 @@ Runtime confirmation (e.g. *"reproduce the cross-tenant read against staging"*,
160
162
  authorization. Still need the policy + scope.
161
163
  * **Generic advice without file:line** — reject your own finding if you cannot
162
164
  cite the exact location.
165
+ * **The three negative tests are the security boundary.** Every protected
166
+ entrypoint needs unauthenticated → 401, authenticated-non-owner → 403/404,
167
+ and cross-tenant → 403/404. A happy-path 200 test proves nothing about access
168
+ control (this is BOLA / IDOR — OWASP API #1). Untested authz is also a
169
+ direct GDPR Art. 32 gap. See [`broken-access-control`](../../rules/broken-access-control.md).
170
+ * **Defense-in-depth so one miss can't leak** — stack ≥2 layers on sensitive
171
+ data: query-level ownership scoping (base scope injects the predicate) + a
172
+ centralized default-deny policy layer (a route with no declared policy is
173
+ denied, not silently open) + DB row-level security (Postgres RLS `FORCE ROW
174
+ LEVEL SECURITY`, tenant var via `SET LOCAL`) as the backstop for a forgotten
175
+ `WHERE tenant_id`. A single layer is not enough.
163
176
 
164
177
  ## Do NOT
165
178
 
@@ -178,6 +191,10 @@ Runtime confirmation (e.g. *"reproduce the cross-tenant read against staging"*,
178
191
  - **OWASP Top 10 2021 — A01 Broken Access Control** — canonical failure modes
179
192
  (IDOR, missing function-level checks, forced browsing, metadata tampering).
180
193
  [owasp.org/Top10/A01_2021-Broken_Access_Control/](https://owasp.org/Top10/A01_2021-Broken_Access_Control/)
194
+ - **OWASP API Security Top 10 2023 — API1 BOLA** (Broken Object Level
195
+ Authorization) and **API3 BOPLA** (property-level / mass assignment) — the
196
+ API-layer names for the same object-ownership failures.
197
+ [owasp.org/API-Security/editions/2023/en/0xa1-broken-object-level-authorization/](https://owasp.org/API-Security/editions/2023/en/0xa1-broken-object-level-authorization/)
181
198
  - **NIST SP 800-53 AC family** — AC-3 Access Enforcement, AC-6 Least Privilege
182
199
  — rubric for "minimum control" recommendations.
183
200
  [csrc.nist.gov/projects/risk-management/sp800-53-controls](https://csrc.nist.gov/projects/risk-management/sp800-53-controls/release-search#!/800-53)
@@ -228,11 +228,26 @@ When `composer require` or `npm install` fails with conflicts:
228
228
  3. **Use `--dry-run`** first — `composer require vendor/pkg --dry-run`.
229
229
  4. **Never use `--ignore-platform-reqs`** in production — only for investigation.
230
230
 
231
+ ## Post-update malware & behavior audit
232
+
233
+ CVE scanning (above) catches *known-vulnerable* versions. It does **not** catch a **compromised update**: a trusted package with a legitimate history ships a normal-looking version bump that quietly adds data-exfiltration or other harmful behavior. This is how the biggest supply-chain attacks landed — event-stream (wallet stealer as a new transitive dep), ua-parser-js (`preinstall` miner + credential stealer), @solana/web3.js (key exfil hidden inside expected network calls), chalk/debug + 16 (browser crypto-drainer, 2B weekly downloads), the self-propagating Shai-Hulud worm (added a `.github/workflows` + secret-scanning `postinstall`), xz-utils (backdoor in the released tarball, not the git repo). Routine updates slip through because the version looks normal and install runs scripts across the whole transitive tree silently — the exact [`lethal-trifecta-guard`](../../rules/lethal-trifecta-guard.md) egress shape.
234
+
235
+ **Run this audit during/after any add or upgrade, then surface findings to the user and hold pending confirmation** (per [`active-remediation`](../../rules/active-remediation.md) — a live supply-chain risk is surfaced, never silently accepted):
236
+
237
+ 1. **Install without running scripts first** — `npm install --ignore-scripts` (npm v12 defaults to this), `composer install --no-scripts`, `pip install --only-binary :all:` (wheels only — no sdist build code) — so install-time code (the #1 RCE vector) can't run before inspection.
238
+ 2. **Diff the version delta old→new** — the `scripts` block (any newly-added `pre/post/install` hook), the dependency tree (any **new transitive dependency**), and where feasible the published tarball vs the git source (xz hid in the tarball).
239
+ 3. **Capability / behavior diff** — did the new version add a capability its job doesn't need: network egress (`fetch`/`net`/`dns`/`http`), `child_process`/shell, env/secret/credential reads, filesystem writes, obfuscated/minified blobs, a `.github/workflows` file? Use `socket` / `guarddog <eco> scan <pkg>@<ver>` if available; else read the delta.
240
+ 4. **Purpose-vs-behavior legitimacy check** — a Slack/HTTP client legitimately makes network calls; a date/string/color util does not. For each new capability ask: *does the package's stated purpose require this?* A network/secret capability with no purpose justification — or a **new outbound endpoint** even in a package that already uses the network — is high-risk.
241
+ 5. **Provenance + advisory feeds** — `npm audit signatures` (flag a dep that *had* provenance and lost it — a token-theft-publish hallmark); `osv-scanner --lockfile=…` and the GitHub Advisory / Socket / Snyk malware feeds against the newly-resolved versions.
242
+
243
+ **Surface to the user** any: new install script · new transitive dep · new network endpoint / secret read · obfuscated blob · lost provenance · advisory/malware hit — with the version delta + the purpose-vs-behavior verdict, and hold the update until they decide. Never auto-accept a bump that introduced an unexplained capability.
244
+
231
245
  ## Output format
232
246
 
233
247
  1. Updated dependency with version constraint change
234
248
  2. Breaking changes addressed with code modifications
235
249
  3. Test results confirming compatibility
250
+ 4. Post-update audit result: capability delta old→new, purpose-vs-behavior verdict, provenance/advisory status — and any finding surfaced to the user for confirmation
236
251
 
237
252
  ## Auto-trigger keywords
238
253
 
@@ -240,9 +255,14 @@ When `composer require` or `npm install` fails with conflicts:
240
255
  - package update
241
256
  - breaking changes
242
257
  - changelog review
258
+ - malicious package
259
+ - supply chain
260
+ - compromised update
243
261
 
244
262
  ## Gotcha
245
263
 
264
+ - **A trusted package is not a safe version.** Every major supply-chain attack (event-stream, ua-parser-js, chalk/debug, xz) shipped through a *legitimate* package's normal-looking bump — maintainer-authored ≠ safe. Run the post-update behavior audit, not just `audit` for CVEs.
265
+ - **`audit` (CVE) ≠ malware scan.** `npm/composer audit` only knows *published* vulnerabilities; a fresh compromised version has no CVE yet. The capability/behavior diff + purpose-vs-behavior check is what catches zero-hour malware.
246
266
  - Don't upgrade multiple major versions at once — one major version per upgrade cycle.
247
267
  - The model tends to skip reading the CHANGELOG — breaking changes hide in minor releases too.
248
268
  - Always run the full test suite after upgrading, not just the affected tests.
@@ -0,0 +1,104 @@
1
+ ---
2
+ model_tier: medium
3
+ name: frontend-render-security
4
+ description: "Writing/reviewing client-side UI (React/Vue/vanilla) — insecure-render + client-trust gaps AI ships: XSS via innerHTML, client secrets, client-only auth, CORS wildcard, token in localStorage"
5
+ domain: quality
6
+ workspaces:
7
+ - engineering
8
+ packs:
9
+ - engineering-base
10
+ ---
11
+
12
+ # frontend-render-security
13
+
14
+ AI optimizes for the shortest code producing the requested visible behavior and omits the invisible defensive layer — the sanitizer, origin check, server-side gate, security header. Large samples put XSS in a majority of AI frontend code, ~2.74× more than human; every agent in the Tenzai benchmark shipped client-side flaws. High-precision, grep-catchable patterns — stop them at authoring time.
15
+
16
+ ## When to use
17
+
18
+ - Writing/modifying a component, template, or client-side script that renders data, calls an API, handles auth, or reads the URL / `postMessage`.
19
+ - Reviewing an AI-authored frontend diff.
20
+ - Editing `.tsx` / `.jsx` / `.vue` / `.svelte` / `.html` or client-side `.js` / `.ts`.
21
+
22
+ Do NOT use when: change is server-only, CLI, or non-UI — route to `security` / `security-sensitive-stop`.
23
+
24
+ ## The Iron Law
25
+
26
+ ```
27
+ NEVER RENDER NON-CONSTANT INPUT INTO AN HTML/JS SINK WITHOUT ENCODING OR SANITIZING.
28
+ THE CLIENT IS UNTRUSTED — EVERY CLIENT GATE NEEDS A SERVER-SIDE TWIN.
29
+ NO SECRET, PRIVILEGED KEY, OR SESSION TOKEN LIVES IN CLIENT CODE OR localStorage.
30
+ ```
31
+
32
+ ## Procedure
33
+
34
+ 1. Identify the sinks in the diff: HTML/JS render points, API calls, auth/role checks, URL / `postMessage` reads, secret/token usage.
35
+ 2. Run the backstop greps below; for each hit, apply the matching fix from the patterns table.
36
+ 3. For every client-side gate, confirm a server-side twin exists (the client is never the security boundary).
37
+ 4. Emit the per-diff verdict (Output format); surface any unresolved hit to the user.
38
+
39
+ ## The patterns AI ships by default
40
+
41
+ | Pattern | Why dangerous | Do instead |
42
+ |---|---|---|
43
+ | `dangerouslySetInnerHTML` / `v-html` / `.innerHTML =` on non-constant value | Stored/DOM XSS (CWE-79) | render as text, or sanitize (DOMPurify) if HTML required |
44
+ | Secret / API key inline or in `NEXT_PUBLIC_*` / `VITE_*` | Bundler inlines it into shipped JS (CWE-798) | call third party via backend-for-frontend proxy; only truly-public values get a public prefix |
45
+ | Client-side-only auth / role / validation | Bypassable via dev tools or proxy (CWE-602) | client gate = UX only; enforce server-side |
46
+ | `location.*` / query param → HTML or JS sink | DOM XSS (CWE-79) | `textContent`; never pass URL data into an HTML/exec sink |
47
+ | CORS `origin: '*'` (esp. with credentials) | Any site reads authenticated responses (CWE-942) | explicit origin allow-list; never reflect `Origin` on credentialed routes |
48
+ | Token / JWT in `localStorage` / `sessionStorage` | XSS-exfiltratable (CWE-522) | `HttpOnly; Secure; SameSite` cookie |
49
+ | `addEventListener('message', …)` without `event.origin` check | Any embedder drives the handler (CWE-346) | strict-equality `event.origin` vs allow-list first |
50
+ | `redirect` / `next` param → `location` / `router.push` | Open redirect / phishing (CWE-601) | relative-path or allow-listed-host only; reject external / non-http schemes |
51
+ | `eval` / `new Function` / string-`setTimeout` on input | Eval injection / RCE (CWE-95) | a parser or explicit allow-list |
52
+ | `target="_blank"` without `rel="noopener"` | Reverse tabnabbing (CWE-1022) | add `rel="noopener noreferrer"` |
53
+ | Missing CSP; missing alt/label/contrast | No XSS second line of defense; a11y failures | strict CSP (no `unsafe-inline`); alt text, labels, AA contrast |
54
+
55
+ ## Backstop greps
56
+
57
+ Run before committing frontend changes; each returns zero (or every hit is read + justified):
58
+
59
+ ```bash
60
+ # Insecure render + eval sinks
61
+ rg -n 'dangerouslySetInnerHTML|v-html|\.innerHTML\s*=|document\.write\(|\beval\(|new Function\('
62
+ # Client secrets / token storage
63
+ rg -n 'NEXT_PUBLIC_.*(SECRET|KEY|TOKEN|PASSWORD)|VITE_.*(SECRET|KEY)|localStorage\.setItem\([^)]*[Tt]oken'
64
+ # Wildcard CORS + unchecked postMessage + open redirect
65
+ rg -n "origin:\s*['\"]\*['\"]|Access-Control-Allow-Origin.*\*"
66
+ rg -n "addEventListener\(\s*['\"]message['\"]" src/ # then confirm each checks event.origin
67
+ # Unhardened external links
68
+ rg -n 'target=["'\'']_blank["'\'']' src/ # then confirm rel="noopener" present
69
+ ```
70
+
71
+ ## Output format
72
+
73
+ 1. A per-diff verdict listing each pattern class checked + result (`clean` / `hit at file:line → fixed by <change>`).
74
+ 2. The backstop greps run, with results.
75
+ 3. For any client gate added, file:line of its **server-side twin** (or an explicit note the server check already exists + where).
76
+
77
+ ## Gotcha
78
+
79
+ - Modern browsers default `_blank` to `noopener`, but legacy/embedded webviews don't — keep the `rel` for portability.
80
+ - `NEXT_PUBLIC_`/`VITE_` on a *genuinely* public value (a publishable analytics ID) is fine; the violation is a *sensitive* name behind that prefix. Read the name, don't blanket-block the prefix.
81
+ - A sanitizer (DOMPurify) is the fix only when HTML output is actually required; if plain text suffices, render text and skip the dependency.
82
+ - Client-side validation isn't wrong — it's wrong *as the only* enforcement. Keep it for UX; add the server twin.
83
+
84
+ ## Do NOT
85
+
86
+ - Do NOT render user/DB HTML through `dangerouslySetInnerHTML`/`v-html`/`innerHTML` without a sanitizer.
87
+ - Do NOT put a secret, privileged key, or session token in client code or web storage.
88
+ - Do NOT treat a client-side role/auth check as a security boundary.
89
+ - Do NOT set `origin: '*'` on a credentialed endpoint.
90
+ - Do NOT auto-strip a grep hit without reading it — some innerHTML uses are on constant, trusted markup.
91
+
92
+ ## Auto-trigger keywords
93
+
94
+ - frontend security
95
+ - XSS
96
+ - dangerouslySetInnerHTML
97
+ - client-side secret
98
+ - insecure render
99
+
100
+ ## See also
101
+
102
+ - [`ai-code-blindspots`](../ai-code-blindspots/SKILL.md) — the surface→controls checklist that routes here.
103
+ - [`senior-engineering-discipline`](../../rules/senior-engineering-discipline.md) — anchor rule.
104
+ - [`security`](../security/SKILL.md), [`defense-in-depth`](../defense-in-depth/SKILL.md), [`accessibility-auditor`](../accessibility-auditor/SKILL.md), [`secrets-management`](../secrets-management/SKILL.md).
@@ -0,0 +1,52 @@
1
+ {
2
+ "skill": "frontend-render-security",
3
+ "last_eval": "2026-07-09",
4
+ "description": "5 should-trigger + 5 should-not-trigger queries. Should-trigger covers DE + EN phrasings for client-side insecure-render / client-trust patterns (XSS, client secrets, client-only auth, CORS, localStorage tokens). Should-not-trigger covers near-miss neighbours (server-side security, generic checklist, accessibility-only, dependency intake) whose vocabulary overlaps.",
5
+ "queries": [
6
+ {
7
+ "q": "is it safe to render this user content with dangerouslySetInnerHTML?",
8
+ "trigger": true
9
+ },
10
+ {
11
+ "q": "review this Vue component for XSS and any secrets in the bundle",
12
+ "trigger": true
13
+ },
14
+ {
15
+ "q": "I'm storing the JWT in localStorage — is that ok?",
16
+ "trigger": true
17
+ },
18
+ {
19
+ "q": "prüf mein Frontend auf unsichere Render-Muster und Client-Secrets",
20
+ "trigger": true
21
+ },
22
+ {
23
+ "q": "my CORS is set to origin '*' with credentials — problem?",
24
+ "trigger": true
25
+ },
26
+ {
27
+ "q": "review this API controller's authorization logic",
28
+ "trigger": false,
29
+ "note": "server-side authz → authz-review / security-sensitive-stop"
30
+ },
31
+ {
32
+ "q": "what invisible controls did I omit across this whole diff?",
33
+ "trigger": false,
34
+ "note": "cross-surface checklist → ai-code-blindspots"
35
+ },
36
+ {
37
+ "q": "make this form accessible — keyboard nav and contrast",
38
+ "trigger": false,
39
+ "note": "accessibility only → accessibility-auditor"
40
+ },
41
+ {
42
+ "q": "is this frontend npm dependency real and safe to install?",
43
+ "trigger": false,
44
+ "note": "dependency intake → supply-chain-intake"
45
+ },
46
+ {
47
+ "q": "help me center this div with flexbox",
48
+ "trigger": false,
49
+ "note": "layout/styling — no security surface"
50
+ }
51
+ ]
52
+ }
@@ -61,6 +61,13 @@ in [`.agent-src.uncondensed/templates/roadmaps.md`](../../templates/roadmaps.md)
61
61
  Read it before authoring. Do not restate its rules in the roadmap
62
62
  body — link the template if a phase needs to override one.
63
63
 
64
+ **Naming:** a lone roadmap is `road-to-<slug>.md`. When you create **≥2
65
+ related** roadmaps in one pass (siblings split from one body of work, or
66
+ a follow-up chain), give them a shared `road-to-<family>-<part>.md`
67
+ prefix so relatedness is visible and the dashboard groups them — pick
68
+ the `<family>` slug up front (template rule 21). Follow-ups additionally
69
+ carry `parent_roadmap:` (rule 17).
70
+
64
71
  ### 2. Pick complexity tier honestly
65
72
 
66
73
  Default `lightweight` (≤ 6 phases, ≤ 600 lines). Only use
@@ -0,0 +1,100 @@
1
+ ---
2
+ model_tier: medium
3
+ name: supply-chain-intake
4
+ description: "Before adding/installing any dependency the agent named — verify the package exists (slopsquatting: ~1 in 5 AI suggestions are hallucinated), isn't typo-adjacent, is pinned + locked, and CVE-scanned"
5
+ domain: devops
6
+ workspaces:
7
+ - engineering
8
+ packs:
9
+ - engineering-base
10
+ ---
11
+
12
+ # supply-chain-intake
13
+
14
+ An LLM generates a plausible-sounding package name token-by-token with no lookup against a real registry. ~19.7% of AI-recommended packages don't exist (576k-sample study); the same fake name recurs across runs, so attackers pre-register it as malware — "slopsquatting". The `huggingface-cli` PoC (an empty package matching a common hallucination) drew 30k+ downloads. Endor Labs: only ~1 in 5 AI-recommended dependency versions is both real *and* safe. A dependency the agent named is untrusted until verified — never install it just because the model produced the name.
15
+
16
+ ## When to use
17
+
18
+ - About to add a dependency to `package.json` / `requirements.txt` / `go.mod` / `Cargo.toml` / `composer.json` / `pyproject.toml`, or run `npm/pnpm/yarn install`, `pip install`, `go get`, `cargo add`, `composer require`.
19
+ - Reviewing an AI-authored diff touching a dependency manifest or lockfile.
20
+ - An install command was suggested (especially `curl … | bash`).
21
+
22
+ Do NOT use when: no dependency is added and no manifest/lockfile is touched.
23
+
24
+ ## The Iron Law
25
+
26
+ ```
27
+ VERIFY THE PACKAGE EXISTS ON THE REAL REGISTRY BEFORE YOU INSTALL IT.
28
+ A NAME THE MODEL PRODUCED IS A HYPOTHESIS, NOT A DEPENDENCY.
29
+ PIN IT, LOCK IT, CVE-SCAN IT. NEVER PIPE A REMOTE SCRIPT STRAIGHT TO A SHELL.
30
+ ```
31
+
32
+ ## Procedure — intake gate (run in order before adding a dependency)
33
+
34
+ 1. **Existence** — confirm the exact string resolves on the real registry, published before your session, with real usage:
35
+ ```bash
36
+ npm view <pkg> version # non-zero exit = does not exist (hallucination)
37
+ pip index versions <pkg> # or: pip install <pkg>== to list
38
+ go list -m <module>@latest
39
+ cargo search <crate>
40
+ ```
41
+ Non-existent, brand-new (days old), or near-zero-download → **stop**, treat as hallucination/slopsquat.
42
+ 2. **Typo-adjacency** — name within 1–2 chars of a far-more-popular package (`python-dateutil` vs `dateutil`, `lodahs` vs `lodash`)? Probably want the popular one — confirm before installing.
43
+ 3. **Version safety** — the model's pin may predate a CVE fix (training-cutoff reintroduction). Take the current patched release, then scan:
44
+ ```bash
45
+ npm audit # block on high/critical
46
+ pip-audit
47
+ osv-scanner -r .
48
+ ```
49
+ 4. **Pin + lock** — install exact + commit the lockfile; reject floating ranges (`^`, `latest`, no lockfile) on production deps.
50
+ ```bash
51
+ npm install --save-exact <pkg> && git add package-lock.json
52
+ ```
53
+ 5. **License** — confirm compatible with the project's declared license before it lands.
54
+ 6. **No pipe-to-shell** — never `curl … | bash` an install; download → inspect → execute over pinned HTTPS, or surface it to the user for confirmation.
55
+
56
+ ## Backstop greps
57
+
58
+ ```bash
59
+ # Floating / unpinned production deps (npm)
60
+ rg -n '"[^"]+":\s*"(\^|~|\*|latest)' package.json
61
+ # Missing lockfile alongside a manifest
62
+ [ -f package.json ] && [ ! -f package-lock.json ] && echo "no lockfile"
63
+ # curl|bash install patterns anywhere in the change
64
+ rg -n 'curl[^|]*\|\s*(bash|sh)|wget[^|]*\|\s*(bash|sh)' .
65
+ ```
66
+
67
+ ## Output format
68
+
69
+ 1. Per new dependency: name, resolved registry version, publish date / usage signal, and the existence-check command output (`npm view … → 4.17.21`) — proving it real.
70
+ 2. The lockfile diff staged, and the `audit` / `osv-scanner` result (`0 high/critical`, or the finding + resolution).
71
+ 3. For any suggested install command, confirmation it isn't `curl|bash` and the source is pinned HTTPS.
72
+
73
+ ## Gotcha
74
+
75
+ - Hallucinated names are *repeatable* — re-prompting the same model yields the same fake name, so "it looked confident / consistent" isn't evidence it exists. Only the registry is.
76
+ - Short, "obvious" variants (`X-cli`, `X-client`, `X-sdk`) are the prime hallucination shape — verify these hardest.
77
+ - A package that exists but was published this week with 12 downloads is a slopsquat candidate, not a safe dep — weigh age + usage, not just existence.
78
+ - Lockfile integrity is part of the threat model: an unhashed or floating entry can pull a freshly-poisoned release even when a lockfile is "present".
79
+
80
+ ## Do NOT
81
+
82
+ - Do NOT run an install command for a package you haven't existence-checked this session.
83
+ - Do NOT accept the model's version pin as authoritative — re-check against current CVEs.
84
+ - Do NOT commit a manifest change without its lockfile.
85
+ - Do NOT pipe a fetched script into an interpreter.
86
+ - Do NOT inline code that duplicates a copyleft source without carrying its license.
87
+
88
+ ## Auto-trigger keywords
89
+
90
+ - dependency intake
91
+ - package hallucination
92
+ - slopsquatting
93
+ - add a dependency
94
+ - npm install / pip install / go get
95
+
96
+ ## See also
97
+
98
+ - [`ai-code-blindspots`](../ai-code-blindspots/SKILL.md) — the surface→controls checklist that routes here.
99
+ - [`senior-engineering-discipline`](../../rules/senior-engineering-discipline.md) — anchor rule.
100
+ - [`dependency-upgrade`](../dependency-upgrade/SKILL.md), [`secrets-management`](../secrets-management/SKILL.md), [`security`](../security/SKILL.md).