guardlink 1.0.0 → 1.2.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 (91) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/README.md +14 -0
  3. package/dist/agents/config.d.ts +8 -0
  4. package/dist/agents/config.d.ts.map +1 -1
  5. package/dist/agents/config.js +28 -5
  6. package/dist/agents/config.js.map +1 -1
  7. package/dist/agents/index.d.ts +2 -1
  8. package/dist/agents/index.d.ts.map +1 -1
  9. package/dist/agents/index.js +1 -1
  10. package/dist/agents/index.js.map +1 -1
  11. package/dist/agents/launcher.d.ts +14 -0
  12. package/dist/agents/launcher.d.ts.map +1 -1
  13. package/dist/agents/launcher.js +126 -1
  14. package/dist/agents/launcher.js.map +1 -1
  15. package/dist/agents/prompts.d.ts +2 -2
  16. package/dist/agents/prompts.d.ts.map +1 -1
  17. package/dist/agents/prompts.js +251 -31
  18. package/dist/agents/prompts.js.map +1 -1
  19. package/dist/analyze/index.d.ts +34 -1
  20. package/dist/analyze/index.d.ts.map +1 -1
  21. package/dist/analyze/index.js +281 -8
  22. package/dist/analyze/index.js.map +1 -1
  23. package/dist/analyze/llm.d.ts +54 -3
  24. package/dist/analyze/llm.d.ts.map +1 -1
  25. package/dist/analyze/llm.js +418 -97
  26. package/dist/analyze/llm.js.map +1 -1
  27. package/dist/analyze/prompts.d.ts +3 -2
  28. package/dist/analyze/prompts.d.ts.map +1 -1
  29. package/dist/analyze/prompts.js +227 -111
  30. package/dist/analyze/prompts.js.map +1 -1
  31. package/dist/analyze/tools.d.ts +22 -0
  32. package/dist/analyze/tools.d.ts.map +1 -0
  33. package/dist/analyze/tools.js +230 -0
  34. package/dist/analyze/tools.js.map +1 -0
  35. package/dist/analyzer/sarif.js +1 -1
  36. package/dist/cli/index.d.ts +15 -7
  37. package/dist/cli/index.d.ts.map +1 -1
  38. package/dist/cli/index.js +290 -150
  39. package/dist/cli/index.js.map +1 -1
  40. package/dist/dashboard/data.d.ts +5 -0
  41. package/dist/dashboard/data.d.ts.map +1 -1
  42. package/dist/dashboard/data.js +24 -12
  43. package/dist/dashboard/data.js.map +1 -1
  44. package/dist/dashboard/diagrams.d.ts.map +1 -1
  45. package/dist/dashboard/diagrams.js +310 -37
  46. package/dist/dashboard/diagrams.js.map +1 -1
  47. package/dist/dashboard/generate.d.ts.map +1 -1
  48. package/dist/dashboard/generate.js +197 -64
  49. package/dist/dashboard/generate.js.map +1 -1
  50. package/dist/init/picker.d.ts.map +1 -1
  51. package/dist/init/picker.js +2 -2
  52. package/dist/init/picker.js.map +1 -1
  53. package/dist/init/templates.d.ts.map +1 -1
  54. package/dist/init/templates.js +52 -32
  55. package/dist/init/templates.js.map +1 -1
  56. package/dist/mcp/server.d.ts.map +1 -1
  57. package/dist/mcp/server.js +14 -28
  58. package/dist/mcp/server.js.map +1 -1
  59. package/dist/parser/index.d.ts +1 -0
  60. package/dist/parser/index.d.ts.map +1 -1
  61. package/dist/parser/index.js +1 -0
  62. package/dist/parser/index.js.map +1 -1
  63. package/dist/parser/parse-line.js +3 -3
  64. package/dist/parser/parse-line.js.map +1 -1
  65. package/dist/parser/parse-project.js +1 -1
  66. package/dist/parser/validate.d.ts +31 -0
  67. package/dist/parser/validate.d.ts.map +1 -0
  68. package/dist/parser/validate.js +149 -0
  69. package/dist/parser/validate.js.map +1 -0
  70. package/dist/report/report.d.ts.map +1 -1
  71. package/dist/report/report.js +64 -0
  72. package/dist/report/report.js.map +1 -1
  73. package/dist/tui/commands.d.ts +3 -3
  74. package/dist/tui/commands.d.ts.map +1 -1
  75. package/dist/tui/commands.js +390 -206
  76. package/dist/tui/commands.js.map +1 -1
  77. package/dist/tui/config.d.ts +2 -0
  78. package/dist/tui/config.d.ts.map +1 -1
  79. package/dist/tui/config.js.map +1 -1
  80. package/dist/tui/format.d.ts +7 -0
  81. package/dist/tui/format.d.ts.map +1 -1
  82. package/dist/tui/format.js +59 -0
  83. package/dist/tui/format.js.map +1 -1
  84. package/dist/tui/index.d.ts.map +1 -1
  85. package/dist/tui/index.js +32 -19
  86. package/dist/tui/index.js.map +1 -1
  87. package/dist/tui/input.d.ts +2 -2
  88. package/dist/tui/input.js +2 -2
  89. package/dist/types/index.d.ts +1 -1
  90. package/dist/types/index.d.ts.map +1 -1
  91. package/package.json +1 -1
@@ -8,8 +8,8 @@ import { resolve } from 'node:path';
8
8
  /**
9
9
  * Build a prompt for annotation agents.
10
10
  *
11
- * Includes the GuardLink reference doc (truncated), current model summary,
12
- * user instructions, and precise GAL syntax rules with common pitfalls.
11
+ * Includes the GuardLink reference doc, current model summary with flows and exposures,
12
+ * flow-first threat modeling methodology, and precise GAL syntax rules.
13
13
  */
14
14
  export function buildAnnotatePrompt(userPrompt, root, model) {
15
15
  // Read the reference doc if available
@@ -18,8 +18,17 @@ export function buildAnnotatePrompt(userPrompt, root, model) {
18
18
  if (existsSync(refPath)) {
19
19
  refDoc = readFileSync(refPath, 'utf-8');
20
20
  }
21
- let modelSummary = 'No threat model parsed yet. Run `guardlink parse` after annotating.';
21
+ // Fall back to docs/GUARDLINK_REFERENCE.md
22
+ if (!refDoc) {
23
+ const docsRefPath = resolve(root, 'docs', 'GUARDLINK_REFERENCE.md');
24
+ if (existsSync(docsRefPath)) {
25
+ refDoc = readFileSync(docsRefPath, 'utf-8');
26
+ }
27
+ }
28
+ let modelSummary = 'No threat model parsed yet. This may be a fresh project — define assets, threats, and controls first.';
22
29
  let existingIds = '';
30
+ let existingFlows = '';
31
+ let existingExposures = '';
23
32
  if (model) {
24
33
  const parts = [
25
34
  `${model.annotations_parsed} annotations`,
@@ -28,6 +37,8 @@ export function buildAnnotatePrompt(userPrompt, root, model) {
28
37
  `${model.threats.length} threats`,
29
38
  `${model.controls.length} controls`,
30
39
  `${model.mitigations.length} mitigations`,
40
+ `${model.flows.length} flows`,
41
+ `${model.boundaries.length} boundaries`,
31
42
  ];
32
43
  modelSummary = `Current model: ${parts.join(', ')}.`;
33
44
  // Include existing IDs so the agent doesn't create duplicates or dangling refs
@@ -36,45 +47,235 @@ export function buildAnnotatePrompt(userPrompt, root, model) {
36
47
  const controlIds = model.controls.filter(c => c.id).map(c => `#${c.id}`);
37
48
  if (threatIds.length + assetIds.length + controlIds.length > 0) {
38
49
  const sections = [];
39
- if (threatIds.length)
40
- sections.push(`Threats: ${threatIds.join(', ')}`);
41
50
  if (assetIds.length)
42
51
  sections.push(`Assets: ${assetIds.join(', ')}`);
52
+ if (threatIds.length)
53
+ sections.push(`Threats: ${threatIds.join(', ')}`);
43
54
  if (controlIds.length)
44
55
  sections.push(`Controls: ${controlIds.join(', ')}`);
45
- existingIds = `\n\nExisting defined IDs (use these in @exposes, @mitigates, etc.):\n${sections.join('\n')}`;
56
+ existingIds = `\n\nExisting defined IDs (REUSE these do NOT redefine):\n${sections.join('\n')}`;
57
+ }
58
+ // Include existing flows so agent understands the current flow graph
59
+ if (model.flows.length > 0) {
60
+ const flowLines = model.flows.slice(0, 30).map(f => ` ${f.source} -> ${f.target}${f.mechanism ? ` via ${f.mechanism}` : ''} (${f.location.file}:${f.location.line})`);
61
+ existingFlows = `\n\nExisting data flows (extend these, don't duplicate):\n${flowLines.join('\n')}`;
62
+ if (model.flows.length > 30)
63
+ existingFlows += `\n ... and ${model.flows.length - 30} more`;
64
+ }
65
+ // Include unmitigated exposures so agent knows what still needs attention
66
+ // NOTE: Do NOT filter out @accepts — agents should see ALL exposures without real mitigations
67
+ const unmitigatedExposures = model.exposures.filter(e => {
68
+ return !model.mitigations.some(m => m.asset === e.asset && m.threat === e.threat);
69
+ });
70
+ if (unmitigatedExposures.length > 0) {
71
+ const expLines = unmitigatedExposures.slice(0, 20).map(e => ` ${e.asset} exposed to ${e.threat} [${e.severity || 'unrated'}] (${e.location.file}:${e.location.line})`);
72
+ existingExposures = `\n\nOpen exposures (no mitigation in code — add @mitigates if a control exists, or @audit to flag for human review):\n${expLines.join('\n')}`;
73
+ if (unmitigatedExposures.length > 20)
74
+ existingExposures += `\n ... and ${unmitigatedExposures.length - 20} more`;
46
75
  }
47
76
  }
48
- return `You are annotating a codebase with GuardLink security annotations.
77
+ return `You are an expert security engineer performing threat modeling as code.
78
+ Your job is to read this codebase deeply, understand how code flows between components, and annotate it with GuardLink (GAL) security annotations that accurately represent the security posture.
49
79
 
50
- ${refDoc ? '## GuardLink Reference\n\n' + refDoc.slice(0, 4000) + '\n\n' : ''}## Current State
51
- ${modelSummary}${existingIds}
80
+ This is NOT a vulnerability scanner. You are building a living threat model embedded in the code itself.
81
+ Annotations capture what COULD go wrong, what controls exist, and how data moves — not just confirmed bugs.
52
82
 
53
- ## Task
83
+ ${refDoc ? '## GuardLink Annotation Language Reference\n\n' + refDoc.slice(0, 4000) + '\n\n' : ''}## Current State
84
+ ${modelSummary}${existingIds}${existingFlows}${existingExposures}
85
+
86
+ ## Your Task
54
87
  ${userPrompt}
55
88
 
56
- ## PRECISE Annotation Syntax (follow EXACTLY)
89
+ ## HOW TO THINK Flow-First Threat Modeling
90
+
91
+ Before writing ANY annotation, you MUST understand the code deeply:
92
+
93
+ ### Step 1: Map the Architecture
94
+ Read ALL source files related to the area you're annotating. Trace:
95
+ - Entry points (HTTP handlers, CLI commands, message consumers, event listeners)
96
+ - Data paths (how user input flows through functions, classes, middleware, to storage or output)
97
+ - Exit points (database writes, API calls, file I/O, rendered templates, responses)
98
+ - Class hierarchies, inherited methods, shared utilities, middleware chains
99
+ - Configuration and environment variable usage
100
+
101
+ ### Step 2: Identify Trust Boundaries
102
+ Look for where trust changes:
103
+ - External user → application code (HTTP boundary)
104
+ - Application → database (data layer boundary)
105
+ - Service → service (network boundary)
106
+ - Frontend → backend (client/server boundary)
107
+ - Application → third-party API (vendor boundary)
108
+ - Internal code → spawned process (process boundary)
57
109
 
58
- Definitions go in .guardlink/definitions.js (or .py/.rs). Source files use only relationship verbs.
110
+ ### Step 3: Identify What Could Go Wrong
111
+ At each boundary crossing and data transformation, ask:
112
+ - What if this input is malicious? (@exposes)
113
+ - What validation/sanitization exists? (@mitigates)
114
+ - What sensitive data passes through here? (@handles)
115
+ - Is there an assumption that could be violated? (@assumes)
116
+ - Does this need human security review? (@audit)
117
+ - Is this risk handled by someone else? (@transfers)
118
+
119
+ ### Step 4: Write Coupled Annotation Blocks
120
+ NEVER write a single annotation in isolation. Every annotated location should tell a complete story.
121
+
122
+ ## ANNOTATION STYLE GUIDE — Write Like a Developer
123
+
124
+ ### Always Couple Annotations Together
125
+ A file's doc-block should paint the full security picture of that module. Group annotations logically:
59
126
 
60
- ### Definitions
61
127
  \`\`\`
62
- // @shield:begin -- "Example annotations for agent prompt, excluded from parsing"
63
- // @asset Server.Auth (#auth) -- "Authentication service"
64
- // @threat SQL_Injection (#sqli) [P0] cwe:CWE-89 -- "Unsanitized input in SQL"
65
- // @control Prepared_Statements (#prepared-stmts) -- "Parameterized queries"
128
+ // @shield:begin -- "Example annotation block for reference, excluded from parsing"
129
+ //
130
+ // GOOD Complete story at a single code location:
131
+ // @exposes #auth-api to #sqli [P1] cwe:CWE-89 -- "User-supplied email passed to findUser() query builder"
132
+ // @mitigates #auth-api against #sqli using #input-validation -- "Zod schema validates email format before query"
133
+ // @flows User_Input -> #auth-api via POST./login -- "Login form submits credentials"
134
+ // @flows #auth-api -> #user-db via TypeORM.findOne -- "Authenticated user lookup"
135
+ // @handles pii on #auth-api -- "Processes email, password, session tokens"
136
+ // @comment -- "Password comparison uses bcrypt.compare with timing-safe equality"
137
+ //
138
+ // BAD — Isolated annotation with no context:
139
+ // @exposes #auth-api to #sqli -- "SQL injection possible"
140
+ //
66
141
  // @shield:end
67
142
  \`\`\`
68
143
 
69
- ### Relationships (use in source files)
144
+ ### Description Style Reference Actual Code
145
+ Descriptions must reference the real code: function names, variable names, libraries, mechanisms.
146
+
147
+ \`\`\`
148
+ // @shield:begin -- "Description examples, excluded from parsing"
149
+ //
150
+ // GOOD: -- "req.body.token passed to jwt.verify() without audience check"
151
+ // GOOD: -- "bcrypt rounds set to 12 via BCRYPT_COST env var"
152
+ // GOOD: -- "Rate limiter uses express-rate-limit at 100req/15min on /api/*"
153
+ //
154
+ // BAD: -- "Input not validated" (too vague — WHICH input? WHERE?)
155
+ // BAD: -- "Uses encryption" (WHAT encryption? On WHAT data?)
156
+ // BAD: -- "Security vulnerability exists" (meaningless — be specific)
157
+ //
158
+ // @shield:end
159
+ \`\`\`
160
+
161
+ ### @flows — Stitch the Complete Data Path
162
+ @flows is the backbone of the threat model. Trace data movement accurately:
163
+
164
+ \`\`\`
165
+ // @shield:begin -- "Flow examples, excluded from parsing"
166
+ //
167
+ // Trace a request through the full stack:
168
+ // @flows User_Browser -> #api-gateway via HTTPS -- "Client sends auth request"
169
+ // @flows #api-gateway -> #auth-service via internal.gRPC -- "Gateway forwards to auth microservice"
170
+ // @flows #auth-service -> #user-db via pg.query -- "Looks up user record by email"
171
+ // @flows #auth-service -> #session-store via redis.set -- "Stores session token with TTL"
172
+ // @flows #auth-service -> User_Browser via Set-Cookie -- "Returns session cookie to client"
173
+ //
174
+ // @shield:end
175
+ \`\`\`
176
+
177
+ ### @boundary — Mark Every Trust Zone Crossing
178
+ Place @boundary annotations where trust level changes between two components:
179
+
180
+ \`\`\`
181
+ // @shield:begin -- "Boundary examples, excluded from parsing"
182
+ //
183
+ // @boundary between #api-gateway and External_Internet (#public-boundary) -- "TLS termination, rate limiting at edge"
184
+ // @boundary between #backend and #database (#data-boundary) -- "Application to persistence layer, connection pooling via pgBouncer"
185
+ // @boundary between #app and #payment-provider (#vendor-boundary) -- "PCI-DSS scope boundary, tokenized card data only"
186
+ //
187
+ // @shield:end
188
+ \`\`\`
189
+
190
+ ### Where to Place Annotations
191
+ Annotations go in the file's top doc-block comment OR directly above the security-relevant code:
192
+
70
193
  \`\`\`
71
- // @shield:begin -- "Example annotations for agent prompt, excluded from parsing"
194
+ // @shield:begin -- "Placement examples, excluded from parsing"
195
+ //
196
+ // FILE-LEVEL (top doc-block) — for module-wide security properties:
197
+ // Place @exposes, @mitigates, @flows, @handles, @boundary that describe the module as a whole
198
+ //
199
+ // INLINE (above specific functions/methods) — for function-specific concerns:
200
+ // Place @exposes, @mitigates above the exact function where the risk or control lives
201
+ // Place @comment above tricky security-relevant code to explain intent
202
+ //
203
+ // @shield:end
204
+ \`\`\`
205
+
206
+ ### Severity — Be Honest, Not Alarmist
207
+ Annotations capture what COULD go wrong, calibrated to realistic risk:
208
+ - **[P0] / [critical]**: Directly exploitable by external attacker, severe impact (RCE, auth bypass, data breach)
209
+ - **[P1] / [high]**: Exploitable with some conditions, significant impact (privilege escalation, data leak)
210
+ - **[P2] / [medium]**: Requires specific conditions or insider access (SSRF, info disclosure)
211
+ - **[P3] / [low]**: Minor impact or very difficult to exploit (timing side-channels, verbose errors)
212
+
213
+ Don't rate everything P0. A SQL injection in an admin-only internal tool is different from one in a public API.
214
+
215
+ ### @comment — Always Add Context
216
+ Every annotation block should include at least one @comment explaining non-obvious security decisions, assumptions, or context that helps future developers (and AI tools) understand the "why".
217
+
218
+ ### @accepts — NEVER USE (Human-Only Decision)
219
+ @accepts marks a risk as intentionally unmitigated. This is a **human-only governance decision** — it requires conscious risk ownership by a person or team.
220
+ As an AI agent, you MUST NEVER write @accepts annotations. You cannot accept risk on behalf of humans.
221
+
222
+ Instead, when you find an exposure with no mitigation in the code:
223
+ 1. Write the @exposes annotation to document the risk
224
+ 2. Add @audit to flag it for human security review
225
+ 3. Add @comment explaining what controls COULD be added
226
+ 4. Optionally add @assumes to document any assumptions the code makes
227
+
228
+ Example — what to do when no mitigation exists:
229
+ \`\`\`
230
+ // @shield:begin -- "@accepts alternative examples, excluded from parsing"
231
+ //
232
+ // WRONG (AI rubber-stamping risk):
233
+ // @accepts #prompt-injection on #ai-endpoint -- "Relying on model safety filters"
234
+ //
235
+ // RIGHT (flag for human review):
236
+ // @exposes #ai-endpoint to #prompt-injection [P1] cwe:CWE-77 -- "User prompt passed directly to LLM API without sanitization"
237
+ // @audit #ai-endpoint -- "No prompt sanitization — needs human review to decide: add input filter or accept risk"
238
+ // @comment -- "Potential controls: #prompt-filter (input sanitization), #output-validator (response filtering)"
239
+ //
240
+ // @shield:end
241
+ \`\`\`
242
+
243
+ Leaving exposures unmitigated is HONEST. The dashboard and reports will surface them as open risks for humans to triage.
244
+
245
+ ### @shield — DO NOT USE Unless Explicitly Asked
246
+ @shield and @shield:begin/@shield:end block AI coding assistants from reading the annotated code.
247
+ This means any shielded code becomes invisible to AI tools — they cannot analyze, refactor, or annotate it.
248
+ Do NOT add @shield annotations unless the user has EXPLICITLY requested it (e.g., "shield the crypto module").
249
+ Adding @shield on your own initiative would actively harm the threat model by creating blind spots where AI cannot help.
250
+
251
+ ## PRECISE GAL Syntax
252
+
253
+ Definitions go in .guardlink/definitions.{ts,js,py,rs}. Source files use only relationship verbs.
254
+
255
+ ### Definitions (in .guardlink/definitions file)
256
+ \`\`\`
257
+ // @shield:begin -- "Definition syntax examples, excluded from parsing"
258
+ // @asset Server.Auth (#auth) -- "Authentication service handling login and session management"
259
+ // @threat SQL_Injection (#sqli) [P0] cwe:CWE-89 -- "Unsanitized input reaches SQL query builder"
260
+ // @control Prepared_Statements (#prepared-stmts) -- "Parameterized queries via ORM or driver placeholders"
261
+ // @shield:end
262
+ \`\`\`
263
+
264
+ ### Relationships (in source files)
265
+ \`\`\`
266
+ // @shield:begin -- "Relationship syntax examples, excluded from parsing"
72
267
  // @exposes #auth to #sqli [P0] cwe:CWE-89 owasp:A03:2021 -- "User input concatenated into query"
73
- // @mitigates #auth against #sqli using #prepared-stmts -- "Uses parameterized queries"
268
+ // @mitigates #auth against #sqli using #prepared-stmts -- "Uses parameterized queries via sqlx"
269
+ // @audit #auth -- "Timing attack risk — needs human review to decide if bcrypt constant-time comparison is sufficient"
270
+ // @transfers #ddos from #api to #cdn -- "Cloudflare handles L7 DDoS mitigation"
74
271
  // @flows req.body.username -> db.query via string-concat -- "User input flows to SQL"
75
- // @boundary between #frontend and #api (#trust-boundary) -- "Public/private boundary"
76
- // @handles pii on #auth -- "Processes user credentials"
77
- // @comment -- "TODO: add rate limiting to prevent brute force"
272
+ // @boundary between #frontend and #api (#web-boundary) -- "TLS-terminated public/private boundary"
273
+ // @handles pii on #auth -- "Processes email, password, session tokens"
274
+ // @validates #prepared-stmts for #auth -- "Integration test sqlInjectionTest.ts confirms parameterized queries block SQLi payloads"
275
+ // @audit #auth -- "Session token rotation logic needs cryptographic review"
276
+ // @assumes #auth -- "Upstream API gateway has already validated TLS and rate-limited requests"
277
+ // @owns security-team for #auth -- "Security team reviews all auth PRs"
278
+ // @comment -- "Password hashing uses bcrypt with cost factor 12, migration from SHA256 completed in v2.1"
78
279
  // @shield:end
79
280
  \`\`\`
80
281
 
@@ -84,13 +285,13 @@ Definitions go in .guardlink/definitions.js (or .py/.rs). Source files use only
84
285
  WRONG: \`@boundary api -- "desc"\` (only one argument — will NOT parse)
85
286
  RIGHT: \`@boundary between #api and #client (#api-boundary) -- "Trust boundary"\`
86
287
 
87
- 2. **@flows is ONE source ONE target per line**: \`@flows <source> -> <target> via <mechanism>\`.
288
+ 2. **@flows is ONE source -> ONE target per line**: \`@flows <source> -> <target> via <mechanism>\`.
88
289
  WRONG: \`@flows A -> B, C -> D -- "desc"\` (commas not supported)
89
290
  RIGHT: \`@flows A -> B via mechanism -- "desc"\` (one per line, repeat for multiple)
90
291
 
91
292
  3. **@exposes / @mitigates require DEFINED #id refs**: Every \`#id\` you reference must exist as a definition.
92
293
  Before using \`@exposes #app to #sqli\`, ensure \`@threat SQL_Injection (#sqli)\` exists in definitions.
93
- Add new definitions to .guardlink/definitions.js FIRST, then reference them in source files.
294
+ Add new definitions to the .guardlink/definitions file FIRST, then reference them in source files.
94
295
 
95
296
  4. **Severity in square brackets**: \`[P0]\` \`[P1]\` \`[P2]\` \`[P3]\` or \`[critical]\` \`[high]\` \`[medium]\` \`[low]\`.
96
297
  Goes AFTER the threat ref in @exposes: \`@exposes #app to #sqli [P0] cwe:CWE-89\`
@@ -108,13 +309,32 @@ Definitions go in .guardlink/definitions.js (or .py/.rs). Source files use only
108
309
 
109
310
  8. **External refs are space-separated after severity**: \`cwe:CWE-89 owasp:A03:2021 capec:CAPEC-66\`
110
311
 
312
+ 9. **@comment always needs -- and quotes**: \`@comment -- "your note here"\`.
313
+ A bare \`@comment\` without description is valid but useless. Always include context.
314
+
315
+ 10. **One annotation per comment line.** Do NOT put two @verbs on the same line.
316
+
111
317
  ## Workflow
112
- 1. Read existing definitions in .guardlink/definitions.js — reuse existing IDs
113
- 2. Add any NEW threat/control definitions FIRST
114
- 3. Then add relationship annotations (@exposes, @mitigates, @flows, etc.) in source files
115
- 4. Use the project's comment style (// for JS/TS, # for Python, etc.)
116
- 5. Run guardlink_validate (MCP) or \`guardlink validate\` to check for errors
117
- 6. Fix any validation errors before finishing
318
+
319
+ 1. **Read first, annotate second.** Read ALL related source files before writing any annotation.
320
+ Trace the full call chain: entry point middleware handler → service → repository → database.
321
+ Understand class hierarchies, shared utilities, and configuration.
322
+
323
+ 2. **Read existing definitions** in the .guardlink/definitions file — reuse existing IDs, never duplicate.
324
+
325
+ 3. **Add NEW definitions FIRST** if you need new assets, threats, or controls.
326
+ Group related definitions together with section comments.
327
+
328
+ 4. **Annotate in coupled blocks.** For each security-relevant location, write the complete story:
329
+ @exposes + @mitigates (or @audit if no mitigation exists) + @flows + @comment at minimum.
330
+ Think: "what's the risk, what's the defense, how does data flow here, and what should the next developer know?"
331
+ NEVER write @accepts — that is a human-only governance decision. Use @audit to flag unmitigated risks for review.
332
+
333
+ 5. **Use the project's comment style** (// for JS/TS/Go/Rust, # for Python/Ruby/Shell, etc.)
334
+
335
+ 6. **Run validation** via guardlink_validate (MCP) or \`guardlink validate\` to check for errors.
336
+
337
+ 7. **Fix any validation errors** before finishing — especially dangling refs and malformed syntax.
118
338
  `;
119
339
  }
120
340
  //# sourceMappingURL=prompts.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../src/agents/prompts.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../src/agents/prompts.ts"],"names":[],"mappings":"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"}
@@ -18,6 +18,8 @@ import { type AnalysisFramework } from './prompts.js';
18
18
  import { type LLMConfig } from './llm.js';
19
19
  export { type AnalysisFramework, FRAMEWORK_LABELS, FRAMEWORK_PROMPTS, buildUserMessage } from './prompts.js';
20
20
  export { type LLMConfig, type LLMProvider, buildConfig, autoDetectConfig } from './llm.js';
21
+ export { GUARDLINK_TOOLS, createToolExecutor } from './tools.js';
22
+ export type { ToolDefinition, ToolCall, ToolResult, ToolExecutor } from './llm.js';
21
23
  export interface ThreatReportOptions {
22
24
  root: string;
23
25
  model: ThreatModel;
@@ -26,6 +28,18 @@ export interface ThreatReportOptions {
26
28
  customPrompt?: string;
27
29
  stream?: boolean;
28
30
  onChunk?: (text: string) => void;
31
+ /** Max lines of context to include around each annotated line (default: 8) */
32
+ snippetContext?: number;
33
+ /** Max total characters for all code snippets combined (default: 40000) */
34
+ snippetBudget?: number;
35
+ /** Enable web search grounding (OpenAI Responses API) */
36
+ webSearch?: boolean;
37
+ /** Enable extended thinking (Anthropic) / reasoning (DeepSeek) */
38
+ extendedThinking?: boolean;
39
+ /** Token budget for thinking (default: 10000) */
40
+ thinkingBudget?: number;
41
+ /** Enable agentic tool use (CVE lookup, model validation, codebase search) */
42
+ enableTools?: boolean;
29
43
  }
30
44
  export interface ThreatReportResult {
31
45
  framework: AnalysisFramework;
@@ -36,10 +50,29 @@ export interface ThreatReportResult {
36
50
  savedTo?: string;
37
51
  inputTokens?: number;
38
52
  outputTokens?: number;
53
+ /** Thinking/reasoning content (if extended thinking was enabled) */
54
+ thinking?: string;
55
+ thinkingTokens?: number;
39
56
  }
57
+ /**
58
+ * Collect project-level context for the LLM: language/framework, key
59
+ * dependencies, and deployment signals (Dockerfile, CI, etc.).
60
+ * Keeps output compact — targets ~2-4 KB.
61
+ */
62
+ export declare function buildProjectContext(root: string): string;
63
+ /**
64
+ * Extract source code snippets around annotated lines.
65
+ *
66
+ * For each annotation that has a file + line location, reads the
67
+ * surrounding `contextLines` lines from disk and returns a formatted
68
+ * block. Deduplicates overlapping ranges within the same file.
69
+ * Respects a total character budget to keep token usage bounded.
70
+ */
71
+ export declare function extractCodeSnippets(root: string, model: ThreatModel, contextLines?: number, budgetChars?: number): string;
40
72
  /**
41
73
  * Serialize the threat model to a compact representation for LLM context.
42
- * Strips empty arrays and location details to save tokens.
74
+ * Includes file:line locations for all security-relevant annotations so
75
+ * the LLM can cross-reference with code snippets.
43
76
  */
44
77
  export declare function serializeModel(model: ThreatModel): string;
45
78
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/analyze/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,KAAK,iBAAiB,EAAyD,MAAM,cAAc,CAAC;AAC7G,OAAO,EAAE,KAAK,SAAS,EAA+B,MAAM,UAAU,CAAC;AAEvE,OAAO,EAAE,KAAK,iBAAiB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAC7G,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,WAAW,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAI3F,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,WAAW,CAAC;IACnB,SAAS,EAAE,iBAAiB,CAAC;IAC7B,SAAS,EAAE,SAAS,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,iBAAiB,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAID;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAwEzD;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAwEhE;AASD,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAwDjG;AAID,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+CAA+C;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AA8BD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAenE;AAID,MAAM,WAAW,uBAAwB,SAAQ,iBAAiB;IAChE,OAAO,EAAE,MAAM,CAAC;CACjB;AAID,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,MAAM,GAAG,uBAAuB,EAAE,CAcrF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/analyze/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,KAAK,iBAAiB,EAAyD,MAAM,cAAc,CAAC;AAC7G,OAAO,EAAE,KAAK,SAAS,EAA+B,MAAM,UAAU,CAAC;AAGvE,OAAO,EAAE,KAAK,iBAAiB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAC7G,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,WAAW,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC3F,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACjE,YAAY,EAAE,cAAc,EAAE,QAAQ,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAInF,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,WAAW,CAAC;IACnB,SAAS,EAAE,iBAAiB,CAAC;IAC7B,SAAS,EAAE,SAAS,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,8EAA8E;IAC9E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,2EAA2E;IAC3E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,yDAAyD;IACzD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,kEAAkE;IAClE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,iDAAiD;IACjD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8EAA8E;IAC9E,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,iBAAiB,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAID;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAoIxD;AAID;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,WAAW,EAClB,YAAY,SAAI,EAChB,WAAW,SAAS,GACnB,MAAM,CA+FR;AAID;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAsFzD;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAwEhE;AASD,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA0EjG;AAID,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+CAA+C;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AA8BD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAenE;AAID,MAAM,WAAW,uBAAwB,SAAQ,iBAAiB;IAChE,OAAO,EAAE,MAAM,CAAC;CACjB;AAID,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,MAAM,GAAG,uBAAuB,EAAE,CAcrF"}