cap-pro 1.0.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 (275) hide show
  1. package/.claude-plugin/README.md +26 -0
  2. package/.claude-plugin/marketplace.json +24 -0
  3. package/.claude-plugin/plugin.json +24 -0
  4. package/LICENSE +21 -0
  5. package/README.ja-JP.md +834 -0
  6. package/README.ko-KR.md +823 -0
  7. package/README.md +806 -0
  8. package/README.pt-BR.md +452 -0
  9. package/README.zh-CN.md +800 -0
  10. package/agents/cap-architect.md +269 -0
  11. package/agents/cap-brainstormer.md +207 -0
  12. package/agents/cap-curator.md +276 -0
  13. package/agents/cap-debugger.md +365 -0
  14. package/agents/cap-designer.md +246 -0
  15. package/agents/cap-historian.md +464 -0
  16. package/agents/cap-migrator.md +291 -0
  17. package/agents/cap-prototyper.md +197 -0
  18. package/agents/cap-validator.md +308 -0
  19. package/bin/install.js +5433 -0
  20. package/cap/bin/cap-tools.cjs +853 -0
  21. package/cap/bin/lib/arc-scanner.cjs +344 -0
  22. package/cap/bin/lib/cap-affinity-engine.cjs +862 -0
  23. package/cap/bin/lib/cap-anchor.cjs +228 -0
  24. package/cap/bin/lib/cap-annotation-writer.cjs +340 -0
  25. package/cap/bin/lib/cap-checkpoint.cjs +434 -0
  26. package/cap/bin/lib/cap-cluster-detect.cjs +945 -0
  27. package/cap/bin/lib/cap-cluster-display.cjs +52 -0
  28. package/cap/bin/lib/cap-cluster-format.cjs +245 -0
  29. package/cap/bin/lib/cap-cluster-helpers.cjs +295 -0
  30. package/cap/bin/lib/cap-cluster-io.cjs +212 -0
  31. package/cap/bin/lib/cap-completeness.cjs +540 -0
  32. package/cap/bin/lib/cap-deps.cjs +583 -0
  33. package/cap/bin/lib/cap-design-families.cjs +332 -0
  34. package/cap/bin/lib/cap-design.cjs +966 -0
  35. package/cap/bin/lib/cap-divergence-detector.cjs +400 -0
  36. package/cap/bin/lib/cap-doctor.cjs +752 -0
  37. package/cap/bin/lib/cap-feature-map-internals.cjs +19 -0
  38. package/cap/bin/lib/cap-feature-map-migrate.cjs +335 -0
  39. package/cap/bin/lib/cap-feature-map-monorepo.cjs +885 -0
  40. package/cap/bin/lib/cap-feature-map-shard.cjs +315 -0
  41. package/cap/bin/lib/cap-feature-map.cjs +1943 -0
  42. package/cap/bin/lib/cap-fitness-score.cjs +1075 -0
  43. package/cap/bin/lib/cap-impact-analysis.cjs +652 -0
  44. package/cap/bin/lib/cap-learn-review.cjs +1072 -0
  45. package/cap/bin/lib/cap-learning-signals.cjs +627 -0
  46. package/cap/bin/lib/cap-loader.cjs +227 -0
  47. package/cap/bin/lib/cap-logger.cjs +57 -0
  48. package/cap/bin/lib/cap-memory-bridge.cjs +764 -0
  49. package/cap/bin/lib/cap-memory-confidence.cjs +452 -0
  50. package/cap/bin/lib/cap-memory-dir.cjs +987 -0
  51. package/cap/bin/lib/cap-memory-engine.cjs +698 -0
  52. package/cap/bin/lib/cap-memory-extends.cjs +398 -0
  53. package/cap/bin/lib/cap-memory-graph.cjs +790 -0
  54. package/cap/bin/lib/cap-memory-migrate.cjs +2015 -0
  55. package/cap/bin/lib/cap-memory-pin.cjs +183 -0
  56. package/cap/bin/lib/cap-memory-platform.cjs +490 -0
  57. package/cap/bin/lib/cap-memory-prune.cjs +707 -0
  58. package/cap/bin/lib/cap-memory-schema.cjs +812 -0
  59. package/cap/bin/lib/cap-migrate-tags.cjs +309 -0
  60. package/cap/bin/lib/cap-migrate.cjs +540 -0
  61. package/cap/bin/lib/cap-pattern-apply.cjs +1203 -0
  62. package/cap/bin/lib/cap-pattern-pipeline.cjs +1034 -0
  63. package/cap/bin/lib/cap-plugin-manifest.cjs +80 -0
  64. package/cap/bin/lib/cap-realtime-affinity.cjs +399 -0
  65. package/cap/bin/lib/cap-reconcile.cjs +570 -0
  66. package/cap/bin/lib/cap-research-gate.cjs +218 -0
  67. package/cap/bin/lib/cap-scope-filter.cjs +402 -0
  68. package/cap/bin/lib/cap-semantic-pipeline.cjs +1038 -0
  69. package/cap/bin/lib/cap-session-extract.cjs +987 -0
  70. package/cap/bin/lib/cap-session.cjs +445 -0
  71. package/cap/bin/lib/cap-snapshot-linkage.cjs +963 -0
  72. package/cap/bin/lib/cap-stack-docs.cjs +646 -0
  73. package/cap/bin/lib/cap-tag-observer.cjs +371 -0
  74. package/cap/bin/lib/cap-tag-scanner.cjs +1766 -0
  75. package/cap/bin/lib/cap-telemetry.cjs +466 -0
  76. package/cap/bin/lib/cap-test-audit.cjs +1438 -0
  77. package/cap/bin/lib/cap-thread-migrator.cjs +307 -0
  78. package/cap/bin/lib/cap-thread-synthesis.cjs +545 -0
  79. package/cap/bin/lib/cap-thread-tracker.cjs +519 -0
  80. package/cap/bin/lib/cap-trace.cjs +399 -0
  81. package/cap/bin/lib/cap-trust-mode.cjs +336 -0
  82. package/cap/bin/lib/cap-ui-design-editor.cjs +642 -0
  83. package/cap/bin/lib/cap-ui-mind-map.cjs +712 -0
  84. package/cap/bin/lib/cap-ui-thread-nav.cjs +693 -0
  85. package/cap/bin/lib/cap-ui.cjs +1245 -0
  86. package/cap/bin/lib/cap-upgrade.cjs +1028 -0
  87. package/cap/bin/lib/cli/arg-helpers.cjs +49 -0
  88. package/cap/bin/lib/cli/frontmatter-router.cjs +31 -0
  89. package/cap/bin/lib/cli/init-router.cjs +68 -0
  90. package/cap/bin/lib/cli/phase-router.cjs +102 -0
  91. package/cap/bin/lib/cli/state-router.cjs +61 -0
  92. package/cap/bin/lib/cli/template-router.cjs +37 -0
  93. package/cap/bin/lib/cli/uat-router.cjs +29 -0
  94. package/cap/bin/lib/cli/validation-router.cjs +26 -0
  95. package/cap/bin/lib/cli/verification-router.cjs +31 -0
  96. package/cap/bin/lib/cli/workstream-router.cjs +39 -0
  97. package/cap/bin/lib/commands.cjs +961 -0
  98. package/cap/bin/lib/config.cjs +467 -0
  99. package/cap/bin/lib/convention-reader.cjs +258 -0
  100. package/cap/bin/lib/core.cjs +1241 -0
  101. package/cap/bin/lib/feature-aggregator.cjs +423 -0
  102. package/cap/bin/lib/frontmatter.cjs +337 -0
  103. package/cap/bin/lib/init.cjs +1443 -0
  104. package/cap/bin/lib/manifest-generator.cjs +383 -0
  105. package/cap/bin/lib/milestone.cjs +253 -0
  106. package/cap/bin/lib/model-profiles.cjs +69 -0
  107. package/cap/bin/lib/monorepo-context.cjs +226 -0
  108. package/cap/bin/lib/monorepo-migrator.cjs +509 -0
  109. package/cap/bin/lib/phase.cjs +889 -0
  110. package/cap/bin/lib/profile-output.cjs +989 -0
  111. package/cap/bin/lib/profile-pipeline.cjs +540 -0
  112. package/cap/bin/lib/roadmap.cjs +330 -0
  113. package/cap/bin/lib/security.cjs +394 -0
  114. package/cap/bin/lib/session-manager.cjs +292 -0
  115. package/cap/bin/lib/skeleton-generator.cjs +179 -0
  116. package/cap/bin/lib/state.cjs +1032 -0
  117. package/cap/bin/lib/template.cjs +231 -0
  118. package/cap/bin/lib/test-detector.cjs +62 -0
  119. package/cap/bin/lib/uat.cjs +283 -0
  120. package/cap/bin/lib/verify.cjs +889 -0
  121. package/cap/bin/lib/workspace-detector.cjs +371 -0
  122. package/cap/bin/lib/workstream.cjs +492 -0
  123. package/cap/commands/gsd/workstreams.md +63 -0
  124. package/cap/references/arc-standard.md +315 -0
  125. package/cap/references/cap-agent-architecture.md +101 -0
  126. package/cap/references/cap-gitignore-template +9 -0
  127. package/cap/references/cap-zero-deps.md +158 -0
  128. package/cap/references/checkpoints.md +778 -0
  129. package/cap/references/continuation-format.md +249 -0
  130. package/cap/references/contract-test-templates.md +312 -0
  131. package/cap/references/feature-map-template.md +25 -0
  132. package/cap/references/git-integration.md +295 -0
  133. package/cap/references/git-planning-commit.md +38 -0
  134. package/cap/references/model-profiles.md +174 -0
  135. package/cap/references/phase-numbering.md +126 -0
  136. package/cap/references/planning-config.md +202 -0
  137. package/cap/references/property-test-templates.md +316 -0
  138. package/cap/references/security-test-templates.md +347 -0
  139. package/cap/references/session-template.json +8 -0
  140. package/cap/references/tdd.md +263 -0
  141. package/cap/references/user-profiling.md +681 -0
  142. package/cap/references/verification-patterns.md +612 -0
  143. package/cap/templates/UAT.md +265 -0
  144. package/cap/templates/claude-md.md +175 -0
  145. package/cap/templates/codebase/architecture.md +255 -0
  146. package/cap/templates/codebase/concerns.md +310 -0
  147. package/cap/templates/codebase/conventions.md +307 -0
  148. package/cap/templates/codebase/integrations.md +280 -0
  149. package/cap/templates/codebase/stack.md +186 -0
  150. package/cap/templates/codebase/structure.md +285 -0
  151. package/cap/templates/codebase/testing.md +480 -0
  152. package/cap/templates/config.json +44 -0
  153. package/cap/templates/context.md +352 -0
  154. package/cap/templates/continue-here.md +78 -0
  155. package/cap/templates/copilot-instructions.md +7 -0
  156. package/cap/templates/debug-subagent-prompt.md +91 -0
  157. package/cap/templates/discussion-log.md +63 -0
  158. package/cap/templates/milestone-archive.md +123 -0
  159. package/cap/templates/milestone.md +115 -0
  160. package/cap/templates/phase-prompt.md +610 -0
  161. package/cap/templates/planner-subagent-prompt.md +117 -0
  162. package/cap/templates/project.md +186 -0
  163. package/cap/templates/requirements.md +231 -0
  164. package/cap/templates/research-project/ARCHITECTURE.md +204 -0
  165. package/cap/templates/research-project/FEATURES.md +147 -0
  166. package/cap/templates/research-project/PITFALLS.md +200 -0
  167. package/cap/templates/research-project/STACK.md +120 -0
  168. package/cap/templates/research-project/SUMMARY.md +170 -0
  169. package/cap/templates/research.md +552 -0
  170. package/cap/templates/roadmap.md +202 -0
  171. package/cap/templates/state.md +176 -0
  172. package/cap/templates/summary.md +364 -0
  173. package/cap/templates/user-preferences.md +498 -0
  174. package/cap/templates/verification-report.md +322 -0
  175. package/cap/workflows/add-phase.md +112 -0
  176. package/cap/workflows/add-tests.md +351 -0
  177. package/cap/workflows/add-todo.md +158 -0
  178. package/cap/workflows/audit-milestone.md +340 -0
  179. package/cap/workflows/audit-uat.md +109 -0
  180. package/cap/workflows/autonomous.md +891 -0
  181. package/cap/workflows/check-todos.md +177 -0
  182. package/cap/workflows/cleanup.md +152 -0
  183. package/cap/workflows/complete-milestone.md +767 -0
  184. package/cap/workflows/diagnose-issues.md +231 -0
  185. package/cap/workflows/discovery-phase.md +289 -0
  186. package/cap/workflows/discuss-phase-assumptions.md +653 -0
  187. package/cap/workflows/discuss-phase.md +1049 -0
  188. package/cap/workflows/do.md +104 -0
  189. package/cap/workflows/execute-phase.md +846 -0
  190. package/cap/workflows/execute-plan.md +514 -0
  191. package/cap/workflows/fast.md +105 -0
  192. package/cap/workflows/forensics.md +265 -0
  193. package/cap/workflows/health.md +181 -0
  194. package/cap/workflows/help.md +660 -0
  195. package/cap/workflows/insert-phase.md +130 -0
  196. package/cap/workflows/list-phase-assumptions.md +178 -0
  197. package/cap/workflows/list-workspaces.md +56 -0
  198. package/cap/workflows/manager.md +362 -0
  199. package/cap/workflows/map-codebase.md +377 -0
  200. package/cap/workflows/milestone-summary.md +223 -0
  201. package/cap/workflows/new-milestone.md +486 -0
  202. package/cap/workflows/new-project.md +1250 -0
  203. package/cap/workflows/new-workspace.md +237 -0
  204. package/cap/workflows/next.md +97 -0
  205. package/cap/workflows/node-repair.md +92 -0
  206. package/cap/workflows/note.md +156 -0
  207. package/cap/workflows/pause-work.md +176 -0
  208. package/cap/workflows/plan-milestone-gaps.md +273 -0
  209. package/cap/workflows/plan-phase.md +857 -0
  210. package/cap/workflows/plant-seed.md +169 -0
  211. package/cap/workflows/pr-branch.md +129 -0
  212. package/cap/workflows/profile-user.md +449 -0
  213. package/cap/workflows/progress.md +507 -0
  214. package/cap/workflows/quick.md +757 -0
  215. package/cap/workflows/remove-phase.md +155 -0
  216. package/cap/workflows/remove-workspace.md +90 -0
  217. package/cap/workflows/research-phase.md +82 -0
  218. package/cap/workflows/resume-project.md +326 -0
  219. package/cap/workflows/review.md +228 -0
  220. package/cap/workflows/session-report.md +146 -0
  221. package/cap/workflows/settings.md +283 -0
  222. package/cap/workflows/ship.md +228 -0
  223. package/cap/workflows/stats.md +60 -0
  224. package/cap/workflows/transition.md +671 -0
  225. package/cap/workflows/ui-phase.md +298 -0
  226. package/cap/workflows/ui-review.md +161 -0
  227. package/cap/workflows/update.md +323 -0
  228. package/cap/workflows/validate-phase.md +170 -0
  229. package/cap/workflows/verify-phase.md +254 -0
  230. package/cap/workflows/verify-work.md +637 -0
  231. package/commands/cap/annotate.md +165 -0
  232. package/commands/cap/brainstorm.md +393 -0
  233. package/commands/cap/checkpoint.md +106 -0
  234. package/commands/cap/completeness.md +94 -0
  235. package/commands/cap/continue.md +72 -0
  236. package/commands/cap/debug.md +588 -0
  237. package/commands/cap/deps.md +169 -0
  238. package/commands/cap/design.md +479 -0
  239. package/commands/cap/init.md +354 -0
  240. package/commands/cap/iterate.md +249 -0
  241. package/commands/cap/learn.md +459 -0
  242. package/commands/cap/memory.md +275 -0
  243. package/commands/cap/migrate-feature-map.md +91 -0
  244. package/commands/cap/migrate-memory.md +108 -0
  245. package/commands/cap/migrate-tags.md +91 -0
  246. package/commands/cap/migrate.md +131 -0
  247. package/commands/cap/prototype.md +510 -0
  248. package/commands/cap/reconcile.md +121 -0
  249. package/commands/cap/review.md +360 -0
  250. package/commands/cap/save.md +72 -0
  251. package/commands/cap/scan.md +404 -0
  252. package/commands/cap/start.md +356 -0
  253. package/commands/cap/status.md +118 -0
  254. package/commands/cap/test-audit.md +262 -0
  255. package/commands/cap/test.md +394 -0
  256. package/commands/cap/trace.md +133 -0
  257. package/commands/cap/ui.md +167 -0
  258. package/hooks/dist/cap-check-update.js +115 -0
  259. package/hooks/dist/cap-context-monitor.js +185 -0
  260. package/hooks/dist/cap-learn-review-hook.js +114 -0
  261. package/hooks/dist/cap-learning-hook.js +192 -0
  262. package/hooks/dist/cap-memory.js +299 -0
  263. package/hooks/dist/cap-prompt-guard.js +97 -0
  264. package/hooks/dist/cap-statusline.js +157 -0
  265. package/hooks/dist/cap-tag-observer.js +115 -0
  266. package/hooks/dist/cap-version-check.js +112 -0
  267. package/hooks/dist/cap-workflow-guard.js +175 -0
  268. package/hooks/hooks.json +55 -0
  269. package/package.json +58 -0
  270. package/scripts/base64-scan.sh +262 -0
  271. package/scripts/build-hooks.js +93 -0
  272. package/scripts/cap-removal-checklist.md +202 -0
  273. package/scripts/prompt-injection-scan.sh +199 -0
  274. package/scripts/run-tests.cjs +181 -0
  275. package/scripts/secret-scan.sh +227 -0
@@ -0,0 +1,347 @@
1
+ # Security Test Templates
2
+
3
+ Reference document for the cap-validator agent (test mode) when generating security-focused tests. Use these templates as starting points, adapting table names, column names, and auth patterns to the target project.
4
+
5
+ ---
6
+
7
+ ## 1. RLS Policy Tests (Supabase)
8
+
9
+ Row-Level Security tests verify that database policies enforce data isolation between users.
10
+
11
+ ### User isolation -- read
12
+
13
+ ```typescript
14
+ import { describe, it, expect } from 'vitest';
15
+ import { createClient } from '@supabase/supabase-js';
16
+
17
+ describe('RLS: TABLE_NAME read isolation', () => {
18
+ it('user cannot read other user data', async () => {
19
+ // Arrange: create client authenticated as User A
20
+ const supabaseA = createClient(SUPABASE_URL, SUPABASE_ANON_KEY, {
21
+ global: { headers: { Authorization: `Bearer ${userAToken}` } },
22
+ });
23
+
24
+ // Act: query data belonging to User B
25
+ const { data, error } = await supabaseA
26
+ .from('TABLE_NAME')
27
+ .select('*')
28
+ .eq('user_id', userBId);
29
+
30
+ // Assert: no data returned (RLS blocks access)
31
+ expect(error).toBeNull();
32
+ expect(data).toHaveLength(0);
33
+ });
34
+
35
+ it('user can read own data', async () => {
36
+ const supabaseA = createClient(SUPABASE_URL, SUPABASE_ANON_KEY, {
37
+ global: { headers: { Authorization: `Bearer ${userAToken}` } },
38
+ });
39
+
40
+ const { data, error } = await supabaseA
41
+ .from('TABLE_NAME')
42
+ .select('*')
43
+ .eq('user_id', userAId);
44
+
45
+ expect(error).toBeNull();
46
+ expect(data.length).toBeGreaterThan(0);
47
+ });
48
+ });
49
+ ```
50
+
51
+ ### User isolation -- write
52
+
53
+ ```typescript
54
+ describe('RLS: TABLE_NAME write isolation', () => {
55
+ it('user cannot update other user data', async () => {
56
+ const supabaseA = createClient(SUPABASE_URL, SUPABASE_ANON_KEY, {
57
+ global: { headers: { Authorization: `Bearer ${userAToken}` } },
58
+ });
59
+
60
+ const { error } = await supabaseA
61
+ .from('TABLE_NAME')
62
+ .update({ name: 'hacked' })
63
+ .eq('user_id', userBId);
64
+
65
+ // Either error or zero affected rows
66
+ expect(error || true).toBeTruthy();
67
+ });
68
+
69
+ it('user cannot delete other user data', async () => {
70
+ const supabaseA = createClient(SUPABASE_URL, SUPABASE_ANON_KEY, {
71
+ global: { headers: { Authorization: `Bearer ${userAToken}` } },
72
+ });
73
+
74
+ const { error } = await supabaseA
75
+ .from('TABLE_NAME')
76
+ .delete()
77
+ .eq('user_id', userBId);
78
+
79
+ expect(error || true).toBeTruthy();
80
+ });
81
+ });
82
+ ```
83
+
84
+ ### Anon access blocked
85
+
86
+ ```typescript
87
+ describe('RLS: TABLE_NAME anon access', () => {
88
+ it('anonymous user cannot read any data', async () => {
89
+ const supabaseAnon = createClient(SUPABASE_URL, SUPABASE_ANON_KEY);
90
+
91
+ const { data, error } = await supabaseAnon
92
+ .from('TABLE_NAME')
93
+ .select('*');
94
+
95
+ // Either empty result or permission error
96
+ expect(data?.length ?? 0).toBe(0);
97
+ });
98
+ });
99
+ ```
100
+
101
+ ---
102
+
103
+ ## 2. Auth Bypass Tests
104
+
105
+ Tests that verify authentication cannot be bypassed through common attack vectors.
106
+
107
+ ### JWT validation
108
+
109
+ ```typescript
110
+ describe('Auth: JWT validation', () => {
111
+ it('rejects expired JWT token', async () => {
112
+ const expiredToken = createJWT({ sub: userId, exp: Math.floor(Date.now() / 1000) - 3600 });
113
+ const response = await fetch(`${API_URL}/protected`, {
114
+ headers: { Authorization: `Bearer ${expiredToken}` },
115
+ });
116
+ expect(response.status).toBe(401);
117
+ });
118
+
119
+ it('rejects modified JWT payload', async () => {
120
+ const validToken = createJWT({ sub: userId, role: 'user' });
121
+ // Tamper with payload (change role to admin without re-signing)
122
+ const parts = validToken.split('.');
123
+ const payload = JSON.parse(Buffer.from(parts[1], 'base64url').toString());
124
+ payload.role = 'admin';
125
+ parts[1] = Buffer.from(JSON.stringify(payload)).toString('base64url');
126
+ const tamperedToken = parts.join('.');
127
+
128
+ const response = await fetch(`${API_URL}/protected`, {
129
+ headers: { Authorization: `Bearer ${tamperedToken}` },
130
+ });
131
+ expect(response.status).toBe(401);
132
+ });
133
+
134
+ it('rejects missing auth header', async () => {
135
+ const response = await fetch(`${API_URL}/protected`);
136
+ expect(response.status).toBe(401);
137
+ });
138
+
139
+ it('rejects token from wrong issuer', async () => {
140
+ const wrongIssuerToken = createJWT({ sub: userId, iss: 'https://evil.example.com' });
141
+ const response = await fetch(`${API_URL}/protected`, {
142
+ headers: { Authorization: `Bearer ${wrongIssuerToken}` },
143
+ });
144
+ expect(response.status).toBe(401);
145
+ });
146
+
147
+ it('rejects token with invalid signature', async () => {
148
+ const token = createJWT({ sub: userId });
149
+ const corruptedToken = token.slice(0, -5) + 'XXXXX';
150
+ const response = await fetch(`${API_URL}/protected`, {
151
+ headers: { Authorization: `Bearer ${corruptedToken}` },
152
+ });
153
+ expect(response.status).toBe(401);
154
+ });
155
+ });
156
+ ```
157
+
158
+ ### Role escalation
159
+
160
+ ```typescript
161
+ describe('Auth: role escalation prevention', () => {
162
+ it('regular user cannot access admin endpoint', async () => {
163
+ const userToken = await loginAs('regular-user');
164
+ const response = await fetch(`${API_URL}/admin/users`, {
165
+ headers: { Authorization: `Bearer ${userToken}` },
166
+ });
167
+ expect(response.status).toBe(403);
168
+ });
169
+
170
+ it('regular user cannot modify own role', async () => {
171
+ const userToken = await loginAs('regular-user');
172
+ const response = await fetch(`${API_URL}/users/me`, {
173
+ method: 'PATCH',
174
+ headers: {
175
+ Authorization: `Bearer ${userToken}`,
176
+ 'Content-Type': 'application/json',
177
+ },
178
+ body: JSON.stringify({ role: 'admin' }),
179
+ });
180
+ // Should either reject or ignore the role field
181
+ expect(response.status).not.toBe(200);
182
+ });
183
+ });
184
+ ```
185
+
186
+ ---
187
+
188
+ ## 3. Input Sanitization Tests
189
+
190
+ Tests that verify user input is properly sanitized against injection attacks.
191
+
192
+ ### XSS prevention
193
+
194
+ ```typescript
195
+ describe('Input: XSS prevention', () => {
196
+ it('rejects script tags in text fields', async () => {
197
+ const response = await createResource({
198
+ name: '<script>alert("xss")</script>',
199
+ });
200
+ // Should either reject or escape the input
201
+ if (response.status === 200) {
202
+ const data = await response.json();
203
+ expect(data.name).not.toContain('<script>');
204
+ } else {
205
+ expect(response.status).toBe(400);
206
+ }
207
+ });
208
+
209
+ it('rejects event handler injection', async () => {
210
+ const response = await createResource({
211
+ name: '" onmouseover="alert(1)',
212
+ });
213
+ if (response.status === 200) {
214
+ const data = await response.json();
215
+ expect(data.name).not.toContain('onmouseover');
216
+ } else {
217
+ expect(response.status).toBe(400);
218
+ }
219
+ });
220
+ });
221
+ ```
222
+
223
+ ### SQL injection prevention
224
+
225
+ ```typescript
226
+ describe('Input: SQL injection prevention', () => {
227
+ it('rejects SQL injection in search parameter', async () => {
228
+ const response = await fetch(`${API_URL}/search?q=' OR '1'='1`);
229
+ // Should not return all records
230
+ expect(response.status).toBe(200);
231
+ const data = await response.json();
232
+ expect(data.length).toBeLessThan(100); // Sanity check
233
+ });
234
+
235
+ it('rejects UNION-based injection', async () => {
236
+ const response = await fetch(`${API_URL}/search?q=' UNION SELECT * FROM users --`);
237
+ expect(response.status).toBe(200);
238
+ const data = await response.json();
239
+ // Should not contain user table data
240
+ expect(data.some(d => d.password_hash)).toBe(false);
241
+ });
242
+ });
243
+ ```
244
+
245
+ ### Path traversal prevention
246
+
247
+ ```typescript
248
+ describe('Input: path traversal prevention', () => {
249
+ it('rejects directory traversal in file path', async () => {
250
+ const response = await fetch(`${API_URL}/files/../../../etc/passwd`);
251
+ expect(response.status).toBe(400);
252
+ });
253
+
254
+ it('rejects encoded directory traversal', async () => {
255
+ const response = await fetch(`${API_URL}/files/%2e%2e%2f%2e%2e%2f%2e%2e%2fetc%2fpasswd`);
256
+ expect([400, 403, 404]).toContain(response.status);
257
+ });
258
+ });
259
+ ```
260
+
261
+ ---
262
+
263
+ ## 4. Data Leakage Tests
264
+
265
+ Tests that verify sensitive data is never exposed in API responses or error messages.
266
+
267
+ ### Sensitive field filtering
268
+
269
+ ```typescript
270
+ describe('Data leakage: sensitive field filtering', () => {
271
+ it('API does not return password hash', async () => {
272
+ const response = await fetch(`${API_URL}/users/me`, {
273
+ headers: { Authorization: `Bearer ${validToken}` },
274
+ });
275
+ const data = await response.json();
276
+ expect(data).not.toHaveProperty('password_hash');
277
+ expect(data).not.toHaveProperty('password');
278
+ expect(data).not.toHaveProperty('hashed_password');
279
+ });
280
+
281
+ it('API does not return internal database IDs in list endpoints', async () => {
282
+ const response = await fetch(`${API_URL}/resources`, {
283
+ headers: { Authorization: `Bearer ${validToken}` },
284
+ });
285
+ const data = await response.json();
286
+ for (const item of data) {
287
+ expect(item).not.toHaveProperty('_id'); // MongoDB internal ID
288
+ expect(item).not.toHaveProperty('internal_id');
289
+ }
290
+ });
291
+
292
+ it('API does not expose other users email addresses', async () => {
293
+ const response = await fetch(`${API_URL}/users`, {
294
+ headers: { Authorization: `Bearer ${validToken}` },
295
+ });
296
+ const data = await response.json();
297
+ const otherUsers = data.filter(u => u.id !== currentUserId);
298
+ for (const user of otherUsers) {
299
+ expect(user).not.toHaveProperty('email');
300
+ }
301
+ });
302
+ });
303
+ ```
304
+
305
+ ### Error message safety
306
+
307
+ ```typescript
308
+ describe('Data leakage: error messages', () => {
309
+ it('error responses do not leak stack traces', async () => {
310
+ const response = await fetch(`${API_URL}/trigger-error`);
311
+ const body = await response.text();
312
+ expect(body).not.toMatch(/at\s+\w+\s+\(/); // Stack trace pattern
313
+ expect(body).not.toContain('node_modules');
314
+ expect(body).not.toContain('.js:');
315
+ });
316
+
317
+ it('error responses do not leak database details', async () => {
318
+ const response = await fetch(`${API_URL}/trigger-error`);
319
+ const body = await response.text();
320
+ expect(body).not.toMatch(/SELECT|INSERT|UPDATE|DELETE/i);
321
+ expect(body).not.toContain('postgresql://');
322
+ expect(body).not.toContain('SQLSTATE');
323
+ });
324
+
325
+ it('404 does not reveal valid resource IDs', async () => {
326
+ const response = await fetch(`${API_URL}/users/nonexistent-id`);
327
+ const body = await response.text();
328
+ expect(body).not.toMatch(/valid IDs include/i);
329
+ expect(body).not.toMatch(/did you mean/i);
330
+ });
331
+ });
332
+ ```
333
+
334
+ ---
335
+
336
+ ## Usage Notes
337
+
338
+ When generating security tests:
339
+
340
+ 1. **Adapt table/column names** to the target project's schema
341
+ 2. **Use the project's actual auth mechanism** (Supabase, NextAuth, custom JWT, etc.)
342
+ 3. **Test both happy and sad paths** -- a secure system rejects bad input AND accepts good input
343
+ 4. **Cover the OWASP Top 10** relevant to the application type
344
+ 5. **For RLS tests**: create two test users, try cross-user access in both directions
345
+ 6. **For auth tests**: test expired, tampered, missing, and wrong-issuer tokens
346
+ 7. **For input tests**: use payloads from OWASP cheat sheets
347
+ 8. **For leakage tests**: check every API endpoint that returns user data
@@ -0,0 +1,8 @@
1
+ {
2
+ "version": "2.0.0",
3
+ "lastCommand": null,
4
+ "lastCommandTimestamp": null,
5
+ "activeFeature": null,
6
+ "activeDebugSession": null,
7
+ "metadata": {}
8
+ }
@@ -0,0 +1,263 @@
1
+ <overview>
2
+ TDD is about design quality, not coverage metrics. The red-green-refactor cycle forces you to think about behavior before implementation, producing cleaner interfaces and more testable code.
3
+
4
+ **Principle:** If you can describe the behavior as `expect(fn(input)).toBe(output)` before writing `fn`, TDD improves the result.
5
+
6
+ **Key insight:** TDD work is fundamentally heavier than standard tasks—it requires 2-3 execution cycles (RED → GREEN → REFACTOR), each with file reads, test runs, and potential debugging. TDD features get dedicated plans to ensure full context is available throughout the cycle.
7
+ </overview>
8
+
9
+ <when_to_use_tdd>
10
+ ## When TDD Improves Quality
11
+
12
+ **TDD candidates (create a TDD plan):**
13
+ - Business logic with defined inputs/outputs
14
+ - API endpoints with request/response contracts
15
+ - Data transformations, parsing, formatting
16
+ - Validation rules and constraints
17
+ - Algorithms with testable behavior
18
+ - State machines and workflows
19
+ - Utility functions with clear specifications
20
+
21
+ **Skip TDD (use standard plan with `type="auto"` tasks):**
22
+ - UI layout, styling, visual components
23
+ - Configuration changes
24
+ - Glue code connecting existing components
25
+ - One-off scripts and migrations
26
+ - Simple CRUD with no business logic
27
+ - Exploratory prototyping
28
+
29
+ **Heuristic:** Can you write `expect(fn(input)).toBe(output)` before writing `fn`?
30
+ → Yes: Create a TDD plan
31
+ → No: Use standard plan, add tests after if needed
32
+ </when_to_use_tdd>
33
+
34
+ <tdd_plan_structure>
35
+ ## TDD Plan Structure
36
+
37
+ Each TDD plan implements **one feature** through the full RED-GREEN-REFACTOR cycle.
38
+
39
+ ```markdown
40
+ ---
41
+ phase: XX-name
42
+ plan: NN
43
+ type: tdd
44
+ ---
45
+
46
+ <objective>
47
+ [What feature and why]
48
+ Purpose: [Design benefit of TDD for this feature]
49
+ Output: [Working, tested feature]
50
+ </objective>
51
+
52
+ <context>
53
+ @.planning/PROJECT.md
54
+ @.planning/ROADMAP.md
55
+ @relevant/source/files.ts
56
+ </context>
57
+
58
+ <feature>
59
+ <name>[Feature name]</name>
60
+ <files>[source file, test file]</files>
61
+ <behavior>
62
+ [Expected behavior in testable terms]
63
+ Cases: input → expected output
64
+ </behavior>
65
+ <implementation>[How to implement once tests pass]</implementation>
66
+ </feature>
67
+
68
+ <verification>
69
+ [Test command that proves feature works]
70
+ </verification>
71
+
72
+ <success_criteria>
73
+ - Failing test written and committed
74
+ - Implementation passes test
75
+ - Refactor complete (if needed)
76
+ - All 2-3 commits present
77
+ </success_criteria>
78
+
79
+ <output>
80
+ After completion, create SUMMARY.md with:
81
+ - RED: What test was written, why it failed
82
+ - GREEN: What implementation made it pass
83
+ - REFACTOR: What cleanup was done (if any)
84
+ - Commits: List of commits produced
85
+ </output>
86
+ ```
87
+
88
+ **One feature per TDD plan.** If features are trivial enough to batch, they're trivial enough to skip TDD—use a standard plan and add tests after.
89
+ </tdd_plan_structure>
90
+
91
+ <execution_flow>
92
+ ## Red-Green-Refactor Cycle
93
+
94
+ **RED - Write failing test:**
95
+ 1. Create test file following project conventions
96
+ 2. Write test describing expected behavior (from `<behavior>` element)
97
+ 3. Run test - it MUST fail
98
+ 4. If test passes: feature exists or test is wrong. Investigate.
99
+ 5. Commit: `test({phase}-{plan}): add failing test for [feature]`
100
+
101
+ **GREEN - Implement to pass:**
102
+ 1. Write minimal code to make test pass
103
+ 2. No cleverness, no optimization - just make it work
104
+ 3. Run test - it MUST pass
105
+ 4. Commit: `feat({phase}-{plan}): implement [feature]`
106
+
107
+ **REFACTOR (if needed):**
108
+ 1. Clean up implementation if obvious improvements exist
109
+ 2. Run tests - MUST still pass
110
+ 3. Only commit if changes made: `refactor({phase}-{plan}): clean up [feature]`
111
+
112
+ **Result:** Each TDD plan produces 2-3 atomic commits.
113
+ </execution_flow>
114
+
115
+ <test_quality>
116
+ ## Good Tests vs Bad Tests
117
+
118
+ **Test behavior, not implementation:**
119
+ - Good: "returns formatted date string"
120
+ - Bad: "calls formatDate helper with correct params"
121
+ - Tests should survive refactors
122
+
123
+ **One concept per test:**
124
+ - Good: Separate tests for valid input, empty input, malformed input
125
+ - Bad: Single test checking all edge cases with multiple assertions
126
+
127
+ **Descriptive names:**
128
+ - Good: "should reject empty email", "returns null for invalid ID"
129
+ - Bad: "test1", "handles error", "works correctly"
130
+
131
+ **No implementation details:**
132
+ - Good: Test public API, observable behavior
133
+ - Bad: Mock internals, test private methods, assert on internal state
134
+ </test_quality>
135
+
136
+ <framework_setup>
137
+ ## Test Framework Setup (If None Exists)
138
+
139
+ When executing a TDD plan but no test framework is configured, set it up as part of the RED phase:
140
+
141
+ **1. Detect project type:**
142
+ ```bash
143
+ # JavaScript/TypeScript
144
+ if [ -f package.json ]; then echo "node"; fi
145
+
146
+ # Python
147
+ if [ -f requirements.txt ] || [ -f pyproject.toml ]; then echo "python"; fi
148
+
149
+ # Go
150
+ if [ -f go.mod ]; then echo "go"; fi
151
+
152
+ # Rust
153
+ if [ -f Cargo.toml ]; then echo "rust"; fi
154
+ ```
155
+
156
+ **2. Install minimal framework:**
157
+ | Project | Framework | Install |
158
+ |---------|-----------|---------|
159
+ | Node.js | Jest | `npm install -D jest @types/jest ts-jest` |
160
+ | Node.js (Vite) | Vitest | `npm install -D vitest` |
161
+ | Python | pytest | `pip install pytest` |
162
+ | Go | testing | Built-in |
163
+ | Rust | cargo test | Built-in |
164
+
165
+ **3. Create config if needed:**
166
+ - Jest: `jest.config.js` with ts-jest preset
167
+ - Vitest: `vitest.config.ts` with test globals
168
+ - pytest: `pytest.ini` or `pyproject.toml` section
169
+
170
+ **4. Verify setup:**
171
+ ```bash
172
+ # Run empty test suite - should pass with 0 tests
173
+ npm test # Node
174
+ pytest # Python
175
+ go test ./... # Go
176
+ cargo test # Rust
177
+ ```
178
+
179
+ **5. Create first test file:**
180
+ Follow project conventions for test location:
181
+ - `*.test.ts` / `*.spec.ts` next to source
182
+ - `__tests__/` directory
183
+ - `tests/` directory at root
184
+
185
+ Framework setup is a one-time cost included in the first TDD plan's RED phase.
186
+ </framework_setup>
187
+
188
+ <error_handling>
189
+ ## Error Handling
190
+
191
+ **Test doesn't fail in RED phase:**
192
+ - Feature may already exist - investigate
193
+ - Test may be wrong (not testing what you think)
194
+ - Fix before proceeding
195
+
196
+ **Test doesn't pass in GREEN phase:**
197
+ - Debug implementation
198
+ - Don't skip to refactor
199
+ - Keep iterating until green
200
+
201
+ **Tests fail in REFACTOR phase:**
202
+ - Undo refactor
203
+ - Commit was premature
204
+ - Refactor in smaller steps
205
+
206
+ **Unrelated tests break:**
207
+ - Stop and investigate
208
+ - May indicate coupling issue
209
+ - Fix before proceeding
210
+ </error_handling>
211
+
212
+ <commit_pattern>
213
+ ## Commit Pattern for TDD Plans
214
+
215
+ TDD plans produce 2-3 atomic commits (one per phase):
216
+
217
+ ```
218
+ test(08-02): add failing test for email validation
219
+
220
+ - Tests valid email formats accepted
221
+ - Tests invalid formats rejected
222
+ - Tests empty input handling
223
+
224
+ feat(08-02): implement email validation
225
+
226
+ - Regex pattern matches RFC 5322
227
+ - Returns boolean for validity
228
+ - Handles edge cases (empty, null)
229
+
230
+ refactor(08-02): extract regex to constant (optional)
231
+
232
+ - Moved pattern to EMAIL_REGEX constant
233
+ - No behavior changes
234
+ - Tests still pass
235
+ ```
236
+
237
+ **Comparison with standard plans:**
238
+ - Standard plans: 1 commit per task, 2-4 commits per plan
239
+ - TDD plans: 2-3 commits for single feature
240
+
241
+ Both follow same format: `{type}({phase}-{plan}): {description}`
242
+
243
+ **Benefits:**
244
+ - Each commit independently revertable
245
+ - Git bisect works at commit level
246
+ - Clear history showing TDD discipline
247
+ - Consistent with overall commit strategy
248
+ </commit_pattern>
249
+
250
+ <context_budget>
251
+ ## Context Budget
252
+
253
+ TDD plans target **~40% context usage** (lower than standard plans' ~50%).
254
+
255
+ Why lower:
256
+ - RED phase: write test, run test, potentially debug why it didn't fail
257
+ - GREEN phase: implement, run test, potentially iterate on failures
258
+ - REFACTOR phase: modify code, run tests, verify no regressions
259
+
260
+ Each phase involves reading files, running commands, analyzing output. The back-and-forth is inherently heavier than linear task execution.
261
+
262
+ Single feature focus ensures full quality throughout the cycle.
263
+ </context_budget>