opena2a-cli 0.1.1 → 0.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 (119) hide show
  1. package/README.md +227 -3
  2. package/dist/adapters/registry.js +1 -1
  3. package/dist/adapters/registry.js.map +1 -1
  4. package/dist/commands/guard-hooks.d.ts +27 -0
  5. package/dist/commands/guard-hooks.d.ts.map +1 -0
  6. package/dist/commands/guard-hooks.js +207 -0
  7. package/dist/commands/guard-hooks.js.map +1 -0
  8. package/dist/commands/guard-policy.d.ts +54 -0
  9. package/dist/commands/guard-policy.d.ts.map +1 -0
  10. package/dist/commands/guard-policy.js +251 -0
  11. package/dist/commands/guard-policy.js.map +1 -0
  12. package/dist/commands/guard-signing.d.ts +52 -0
  13. package/dist/commands/guard-signing.d.ts.map +1 -0
  14. package/dist/commands/guard-signing.js +185 -0
  15. package/dist/commands/guard-signing.js.map +1 -0
  16. package/dist/commands/guard-snapshots.d.ts +54 -0
  17. package/dist/commands/guard-snapshots.d.ts.map +1 -0
  18. package/dist/commands/guard-snapshots.js +346 -0
  19. package/dist/commands/guard-snapshots.js.map +1 -0
  20. package/dist/commands/guard.d.ts +60 -4
  21. package/dist/commands/guard.d.ts.map +1 -1
  22. package/dist/commands/guard.js +475 -95
  23. package/dist/commands/guard.js.map +1 -1
  24. package/dist/commands/init.d.ts.map +1 -1
  25. package/dist/commands/init.js +77 -3
  26. package/dist/commands/init.js.map +1 -1
  27. package/dist/commands/protect.d.ts +2 -0
  28. package/dist/commands/protect.d.ts.map +1 -1
  29. package/dist/commands/protect.js +56 -10
  30. package/dist/commands/protect.js.map +1 -1
  31. package/dist/commands/runtime.d.ts +1 -1
  32. package/dist/commands/runtime.js +5 -5
  33. package/dist/commands/runtime.js.map +1 -1
  34. package/dist/commands/self-register.js +6 -6
  35. package/dist/commands/self-register.js.map +1 -1
  36. package/dist/commands/shield.d.ts +39 -0
  37. package/dist/commands/shield.d.ts.map +1 -0
  38. package/dist/commands/shield.js +1262 -0
  39. package/dist/commands/shield.js.map +1 -0
  40. package/dist/commands/verify.js +1 -1
  41. package/dist/commands/verify.js.map +1 -1
  42. package/dist/index.js +41 -3
  43. package/dist/index.js.map +1 -1
  44. package/dist/router.d.ts.map +1 -1
  45. package/dist/router.js +1 -0
  46. package/dist/router.js.map +1 -1
  47. package/dist/shield/arp-bridge.d.ts +62 -0
  48. package/dist/shield/arp-bridge.d.ts.map +1 -0
  49. package/dist/shield/arp-bridge.js +198 -0
  50. package/dist/shield/arp-bridge.js.map +1 -0
  51. package/dist/shield/baselines.d.ts +58 -0
  52. package/dist/shield/baselines.d.ts.map +1 -0
  53. package/dist/shield/baselines.js +371 -0
  54. package/dist/shield/baselines.js.map +1 -0
  55. package/dist/shield/detect.d.ts +18 -0
  56. package/dist/shield/detect.d.ts.map +1 -0
  57. package/dist/shield/detect.js +402 -0
  58. package/dist/shield/detect.js.map +1 -0
  59. package/dist/shield/events.d.ts +65 -0
  60. package/dist/shield/events.d.ts.map +1 -0
  61. package/dist/shield/events.js +342 -0
  62. package/dist/shield/events.js.map +1 -0
  63. package/dist/shield/findings.d.ts +52 -0
  64. package/dist/shield/findings.d.ts.map +1 -0
  65. package/dist/shield/findings.js +336 -0
  66. package/dist/shield/findings.js.map +1 -0
  67. package/dist/shield/init.d.ts +22 -0
  68. package/dist/shield/init.d.ts.map +1 -0
  69. package/dist/shield/init.js +290 -0
  70. package/dist/shield/init.js.map +1 -0
  71. package/dist/shield/integrity.d.ts +75 -0
  72. package/dist/shield/integrity.d.ts.map +1 -0
  73. package/dist/shield/integrity.js +439 -0
  74. package/dist/shield/integrity.js.map +1 -0
  75. package/dist/shield/llm-backend.d.ts +36 -0
  76. package/dist/shield/llm-backend.d.ts.map +1 -0
  77. package/dist/shield/llm-backend.js +145 -0
  78. package/dist/shield/llm-backend.js.map +1 -0
  79. package/dist/shield/llm.d.ts +116 -0
  80. package/dist/shield/llm.d.ts.map +1 -0
  81. package/dist/shield/llm.js +536 -0
  82. package/dist/shield/llm.js.map +1 -0
  83. package/dist/shield/policy.d.ts +70 -0
  84. package/dist/shield/policy.d.ts.map +1 -0
  85. package/dist/shield/policy.js +399 -0
  86. package/dist/shield/policy.js.map +1 -0
  87. package/dist/shield/report-html.d.ts +29 -0
  88. package/dist/shield/report-html.d.ts.map +1 -0
  89. package/dist/shield/report-html.js +596 -0
  90. package/dist/shield/report-html.js.map +1 -0
  91. package/dist/shield/sarif.d.ts +65 -0
  92. package/dist/shield/sarif.d.ts.map +1 -0
  93. package/dist/shield/sarif.js +108 -0
  94. package/dist/shield/sarif.js.map +1 -0
  95. package/dist/shield/session.d.ts +63 -0
  96. package/dist/shield/session.d.ts.map +1 -0
  97. package/dist/shield/session.js +242 -0
  98. package/dist/shield/session.js.map +1 -0
  99. package/dist/shield/signing.d.ts +41 -0
  100. package/dist/shield/signing.d.ts.map +1 -0
  101. package/dist/shield/signing.js +161 -0
  102. package/dist/shield/signing.js.map +1 -0
  103. package/dist/shield/status.d.ts +4 -0
  104. package/dist/shield/status.d.ts.map +1 -0
  105. package/dist/shield/status.js +241 -0
  106. package/dist/shield/status.js.map +1 -0
  107. package/dist/shield/types.d.ts +416 -0
  108. package/dist/shield/types.d.ts.map +1 -0
  109. package/dist/shield/types.js +32 -0
  110. package/dist/shield/types.js.map +1 -0
  111. package/dist/util/drift-liveness.d.ts +37 -0
  112. package/dist/util/drift-liveness.d.ts.map +1 -0
  113. package/dist/util/drift-liveness.js +114 -0
  114. package/dist/util/drift-liveness.js.map +1 -0
  115. package/dist/util/drift-verification.d.ts +60 -0
  116. package/dist/util/drift-verification.d.ts.map +1 -0
  117. package/dist/util/drift-verification.js +457 -0
  118. package/dist/util/drift-verification.js.map +1 -0
  119. package/package.json +4 -2
@@ -0,0 +1,399 @@
1
+ "use strict";
2
+ /**
3
+ * Shield: Policy loading, evaluation, and default generation.
4
+ *
5
+ * Loads YAML-formatted policies (stored as JSON with .yaml extension),
6
+ * evaluates actions against allow/deny rules, and generates default
7
+ * policies from environment scans.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.matchesPattern = matchesPattern;
11
+ exports.getDefaultPolicyRules = getDefaultPolicyRules;
12
+ exports.createDefaultPolicy = createDefaultPolicy;
13
+ exports.generatePolicyFromScan = generatePolicyFromScan;
14
+ exports.loadPolicy = loadPolicy;
15
+ exports.savePolicy = savePolicy;
16
+ exports.loadPolicyCache = loadPolicyCache;
17
+ exports.savePolicyCache = savePolicyCache;
18
+ exports.evaluatePolicy = evaluatePolicy;
19
+ const node_fs_1 = require("node:fs");
20
+ const node_path_1 = require("node:path");
21
+ const node_os_1 = require("node:os");
22
+ const types_js_1 = require("./types.js");
23
+ // ---------------------------------------------------------------------------
24
+ // Helpers
25
+ // ---------------------------------------------------------------------------
26
+ /** Return the path to the user-level shield directory. */
27
+ function getShieldDir() {
28
+ return (0, node_path_1.join)((0, node_os_1.homedir)(), '.opena2a', 'shield');
29
+ }
30
+ /** Expand leading ~/ to the user home directory. */
31
+ function expandHomedir(pattern) {
32
+ if (pattern.startsWith('~/')) {
33
+ return (0, node_path_1.join)((0, node_os_1.homedir)(), pattern.slice(2));
34
+ }
35
+ return pattern;
36
+ }
37
+ // ---------------------------------------------------------------------------
38
+ // Pattern matching
39
+ // ---------------------------------------------------------------------------
40
+ /**
41
+ * Glob-like pattern matching.
42
+ *
43
+ * Supports:
44
+ * - `*` matches any sequence of characters
45
+ * - Exact string match
46
+ * - Path prefix matching: pattern ending with `/` matches anything under
47
+ * that path (e.g. `~/.ssh/` matches `~/.ssh/id_rsa`)
48
+ */
49
+ function matchesPattern(value, pattern) {
50
+ // Universal wildcard
51
+ if (pattern === '*') {
52
+ return true;
53
+ }
54
+ // Path prefix matching: pattern ending with '/' matches anything under it
55
+ if (pattern.endsWith('/')) {
56
+ const prefix = pattern;
57
+ return value === pattern.slice(0, -1) || value.startsWith(prefix);
58
+ }
59
+ // Glob with wildcards
60
+ if (pattern.includes('*')) {
61
+ const parts = pattern.split('*');
62
+ if (parts.length === 2) {
63
+ const [prefix, suffix] = parts;
64
+ return value.startsWith(prefix) && value.endsWith(suffix);
65
+ }
66
+ // Multi-wildcard: convert to regex
67
+ const escaped = pattern
68
+ .replace(/[.+^${}()|[\]\\]/g, '\\$&')
69
+ .replace(/\*/g, '.*');
70
+ return new RegExp(`^${escaped}$`).test(value);
71
+ }
72
+ // Exact match
73
+ return value === pattern;
74
+ }
75
+ // ---------------------------------------------------------------------------
76
+ // Default rules
77
+ // ---------------------------------------------------------------------------
78
+ /** Return sensible default policy rules for a developer workstation. */
79
+ function getDefaultPolicyRules() {
80
+ return {
81
+ processes: {
82
+ deny: ['aws', 'gcloud', 'az', 'kubectl', 'terraform', 'rm -rf'],
83
+ allow: [
84
+ 'git', 'npm', 'node', 'npx', 'tsc', 'eslint', 'prettier',
85
+ 'cargo', 'go', 'python', 'pip', 'pytest', 'bun', 'deno',
86
+ ],
87
+ },
88
+ credentials: {
89
+ deny: ['~/.ssh/*', '~/.aws/*', '~/.config/gcloud/*', '~/.azure/*'],
90
+ allow: [],
91
+ },
92
+ network: {
93
+ deny: [],
94
+ allow: ['localhost', '127.0.0.1', 'registry.npmjs.org', 'github.com'],
95
+ },
96
+ filesystem: {
97
+ deny: ['~/.ssh/', '~/.gnupg/'],
98
+ allow: [],
99
+ },
100
+ mcpServers: {
101
+ deny: [],
102
+ allow: [],
103
+ },
104
+ supplyChain: {
105
+ requireTrustScore: 0,
106
+ blockAdvisories: false,
107
+ },
108
+ };
109
+ }
110
+ // ---------------------------------------------------------------------------
111
+ // Policy creation
112
+ // ---------------------------------------------------------------------------
113
+ /** Create a default policy with standard rules and no agent-specific overrides. */
114
+ function createDefaultPolicy(mode = 'adaptive') {
115
+ return {
116
+ version: 1,
117
+ mode,
118
+ default: getDefaultPolicyRules(),
119
+ agents: {},
120
+ };
121
+ }
122
+ // ---------------------------------------------------------------------------
123
+ // Policy generation from environment scan
124
+ // ---------------------------------------------------------------------------
125
+ /** Map project types to additional tools that should be in the allow list. */
126
+ const PROJECT_TYPE_TOOLS = {
127
+ node: ['node', 'npm', 'npx', 'tsc', 'eslint', 'prettier'],
128
+ go: ['go', 'golangci-lint', 'gopls'],
129
+ python: ['python', 'pip', 'pytest', 'ruff', 'mypy'],
130
+ };
131
+ /**
132
+ * Generate a policy tailored to the scanned environment.
133
+ * Detected CLIs are added to the process deny list. Detected MCP servers
134
+ * are added to the mcpServers allow list. Project-type-appropriate tools
135
+ * are added to the process allow list. Mode is set to 'adaptive'.
136
+ */
137
+ function generatePolicyFromScan(scan) {
138
+ const policy = createDefaultPolicy('adaptive');
139
+ // Add detected cloud CLIs to processes.deny
140
+ for (const cli of scan.clis) {
141
+ if (!policy.default.processes.deny.includes(cli.name)) {
142
+ policy.default.processes.deny.push(cli.name);
143
+ }
144
+ }
145
+ // Add detected CLI config dirs to filesystem.deny
146
+ for (const cli of scan.clis) {
147
+ if (cli.configDir && !policy.default.filesystem.deny.includes(cli.configDir)) {
148
+ policy.default.filesystem.deny.push(cli.configDir);
149
+ }
150
+ }
151
+ // Add project-appropriate dev tools to processes.allow based on projectType
152
+ const tools = PROJECT_TYPE_TOOLS[scan.projectType];
153
+ if (tools) {
154
+ for (const tool of tools) {
155
+ if (!policy.default.processes.allow.includes(tool)) {
156
+ policy.default.processes.allow.push(tool);
157
+ }
158
+ }
159
+ }
160
+ // Add detected MCP server names to mcpServers.allow
161
+ for (const server of scan.mcpServers) {
162
+ if (!policy.default.mcpServers.allow.includes(server.name)) {
163
+ policy.default.mcpServers.allow.push(server.name);
164
+ }
165
+ }
166
+ return policy;
167
+ }
168
+ // ---------------------------------------------------------------------------
169
+ // Policy persistence
170
+ // ---------------------------------------------------------------------------
171
+ /**
172
+ * Load a shield policy from disk.
173
+ *
174
+ * Checks the user-level policy file at `~/.opena2a/shield/policy.yaml`.
175
+ * The file is stored as JSON despite the .yaml extension (simplest approach
176
+ * since we control the format).
177
+ *
178
+ * Returns null if no policy file exists or it cannot be parsed.
179
+ */
180
+ function loadPolicy(targetDir) {
181
+ // Try project-level first if a target directory is provided
182
+ if (targetDir) {
183
+ const projectPolicyPath = (0, node_path_1.join)(targetDir, types_js_1.SHIELD_DIR, types_js_1.SHIELD_POLICY_FILE);
184
+ try {
185
+ if ((0, node_fs_1.existsSync)(projectPolicyPath)) {
186
+ const raw = (0, node_fs_1.readFileSync)(projectPolicyPath, 'utf-8');
187
+ return JSON.parse(raw);
188
+ }
189
+ }
190
+ catch {
191
+ // Fall through to user-level
192
+ }
193
+ }
194
+ // Try user-level
195
+ const userPolicyPath = (0, node_path_1.join)((0, node_os_1.homedir)(), types_js_1.SHIELD_DIR, types_js_1.SHIELD_POLICY_FILE);
196
+ try {
197
+ if ((0, node_fs_1.existsSync)(userPolicyPath)) {
198
+ const raw = (0, node_fs_1.readFileSync)(userPolicyPath, 'utf-8');
199
+ return JSON.parse(raw);
200
+ }
201
+ }
202
+ catch {
203
+ return null;
204
+ }
205
+ return null;
206
+ }
207
+ /**
208
+ * Write a policy to disk as JSON with restrictive permissions (0o600).
209
+ * Creates parent directories if they do not exist.
210
+ */
211
+ function savePolicy(policy, path) {
212
+ const dir = (0, node_path_1.dirname)(path);
213
+ if (!(0, node_fs_1.existsSync)(dir)) {
214
+ (0, node_fs_1.mkdirSync)(dir, { recursive: true });
215
+ }
216
+ (0, node_fs_1.writeFileSync)(path, JSON.stringify(policy, null, 2) + '\n', { mode: 0o600 });
217
+ }
218
+ // ---------------------------------------------------------------------------
219
+ // Policy cache
220
+ // ---------------------------------------------------------------------------
221
+ /** Return the path to the policy cache file. */
222
+ function getPolicyCachePath() {
223
+ return (0, node_path_1.join)(getShieldDir(), types_js_1.SHIELD_POLICY_CACHE);
224
+ }
225
+ /** Return the path to the user-level policy file. */
226
+ function getUserPolicyPath() {
227
+ return (0, node_path_1.join)(getShieldDir(), types_js_1.SHIELD_POLICY_FILE);
228
+ }
229
+ /**
230
+ * Load the cached policy. Returns null if the cache does not exist or
231
+ * if the policy file has been modified more recently than the cache.
232
+ */
233
+ function loadPolicyCache() {
234
+ const cachePath = getPolicyCachePath();
235
+ if (!(0, node_fs_1.existsSync)(cachePath)) {
236
+ return null;
237
+ }
238
+ // Invalidate cache if the policy file is newer
239
+ const policyPath = getUserPolicyPath();
240
+ if ((0, node_fs_1.existsSync)(policyPath)) {
241
+ try {
242
+ const cacheStat = (0, node_fs_1.statSync)(cachePath);
243
+ const policyStat = (0, node_fs_1.statSync)(policyPath);
244
+ if (policyStat.mtimeMs > cacheStat.mtimeMs) {
245
+ return null;
246
+ }
247
+ }
248
+ catch {
249
+ return null;
250
+ }
251
+ }
252
+ try {
253
+ const raw = (0, node_fs_1.readFileSync)(cachePath, 'utf-8');
254
+ return JSON.parse(raw);
255
+ }
256
+ catch {
257
+ return null;
258
+ }
259
+ }
260
+ /** Save a policy to the cache file with restrictive permissions. */
261
+ function savePolicyCache(policy) {
262
+ const cachePath = getPolicyCachePath();
263
+ const dir = (0, node_path_1.dirname)(cachePath);
264
+ if (!(0, node_fs_1.existsSync)(dir)) {
265
+ (0, node_fs_1.mkdirSync)(dir, { recursive: true });
266
+ }
267
+ (0, node_fs_1.writeFileSync)(cachePath, JSON.stringify(policy, null, 2) + '\n', { mode: 0o600 });
268
+ }
269
+ // ---------------------------------------------------------------------------
270
+ // Policy evaluation
271
+ // ---------------------------------------------------------------------------
272
+ /**
273
+ * Map action strings (used by callers like shield evaluate) to policy
274
+ * rule category keys. This allows callers to pass either an action string
275
+ * like 'process.spawn' or a direct category name like 'processes'.
276
+ */
277
+ const ACTION_CATEGORY_MAP = {
278
+ 'process.spawn': 'processes',
279
+ 'credential.read': 'credentials',
280
+ 'file.access': 'filesystem',
281
+ 'network.connect': 'network',
282
+ 'mcp.call': 'mcpServers',
283
+ };
284
+ /** Valid category keys that can be used directly. */
285
+ const VALID_CATEGORIES = new Set([
286
+ 'processes', 'credentials', 'network', 'filesystem', 'mcpServers',
287
+ ]);
288
+ /**
289
+ * Merge agent-specific rule overrides onto a base set of rules.
290
+ * Agent-specific rules completely replace the base for any category they define.
291
+ */
292
+ function mergeRules(base, overrides) {
293
+ const merged = JSON.parse(JSON.stringify(base));
294
+ for (const key of ['credentials', 'processes', 'network', 'filesystem', 'mcpServers']) {
295
+ const override = overrides[key];
296
+ if (override && 'allow' in override && 'deny' in override) {
297
+ merged[key] = {
298
+ allow: [...override.allow],
299
+ deny: [...override.deny],
300
+ };
301
+ }
302
+ }
303
+ if (overrides.supplyChain) {
304
+ merged.supplyChain = { ...merged.supplyChain, ...overrides.supplyChain };
305
+ }
306
+ return merged;
307
+ }
308
+ /**
309
+ * Evaluate an action against the policy.
310
+ *
311
+ * Resolution order:
312
+ * 1. Agent-specific rules are merged over default rules if the agent
313
+ * has overrides defined.
314
+ * 2. Deny rules are checked first -- deny takes precedence over allow.
315
+ * 3. In adaptive/monitor mode, denied actions are logged but not blocked
316
+ * (outcome='monitored'). In enforce mode, they are blocked
317
+ * (outcome='blocked').
318
+ * 4. If no rule matches, the action is implicitly allowed.
319
+ *
320
+ * @param policy - The loaded shield policy.
321
+ * @param agent - Agent identifier (or null for unknown agents).
322
+ * @param category - The action or category string (e.g. 'process.spawn' or 'processes').
323
+ * @param target - The target of the action (e.g. binary name, file path, hostname).
324
+ */
325
+ function evaluatePolicy(policy, agent, category, target) {
326
+ // Resolve effective rules: agent-specific merged over defaults
327
+ let effectiveRules = policy.default;
328
+ if (agent && policy.agents[agent]) {
329
+ effectiveRules = mergeRules(policy.default, policy.agents[agent]);
330
+ }
331
+ // Resolve category: support both action strings and direct category names
332
+ let resolvedCategory = ACTION_CATEGORY_MAP[category];
333
+ if (!resolvedCategory && VALID_CATEGORIES.has(category)) {
334
+ resolvedCategory = category;
335
+ }
336
+ if (!resolvedCategory) {
337
+ return {
338
+ allowed: true,
339
+ outcome: 'allowed',
340
+ rule: `no-policy-for-action:${category}`,
341
+ agent,
342
+ };
343
+ }
344
+ const rules = effectiveRules[resolvedCategory];
345
+ // supplyChain does not have allow/deny arrays
346
+ if (!rules || !('allow' in rules) || !('deny' in rules)) {
347
+ return {
348
+ allowed: true,
349
+ outcome: 'allowed',
350
+ rule: `${resolvedCategory}:no-allow-deny-rules`,
351
+ agent,
352
+ };
353
+ }
354
+ const { allow, deny } = rules;
355
+ // For credentials and filesystem categories, expand ~ in patterns
356
+ const shouldExpandHome = resolvedCategory === 'filesystem' || resolvedCategory === 'credentials';
357
+ const expandPattern = shouldExpandHome ? expandHomedir : (p) => p;
358
+ // Check deny first (deny takes precedence)
359
+ for (const pattern of deny) {
360
+ const expanded = expandPattern(pattern);
361
+ if (matchesPattern(target, expanded)) {
362
+ if (policy.mode === 'enforce') {
363
+ return {
364
+ allowed: false,
365
+ outcome: 'blocked',
366
+ rule: `${resolvedCategory}.deny:${pattern}`,
367
+ agent,
368
+ };
369
+ }
370
+ // adaptive or monitor mode: allow but mark as monitored
371
+ return {
372
+ allowed: true,
373
+ outcome: 'monitored',
374
+ rule: `${resolvedCategory}.deny:${pattern}`,
375
+ agent,
376
+ };
377
+ }
378
+ }
379
+ // Check allow
380
+ for (const pattern of allow) {
381
+ const expanded = expandPattern(pattern);
382
+ if (matchesPattern(target, expanded)) {
383
+ return {
384
+ allowed: true,
385
+ outcome: 'allowed',
386
+ rule: `${resolvedCategory}.allow:${pattern}`,
387
+ agent,
388
+ };
389
+ }
390
+ }
391
+ // No explicit match: implicitly allowed
392
+ return {
393
+ allowed: true,
394
+ outcome: 'allowed',
395
+ rule: `${resolvedCategory}:no-match`,
396
+ agent,
397
+ };
398
+ }
399
+ //# sourceMappingURL=policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.js","sourceRoot":"","sources":["../../src/shield/policy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Shield HTML Posture Report Generator.
3
+ *
4
+ * Generates a self-contained HTML file with:
5
+ * - Dark theme (slate-900 background, slate-800 cards)
6
+ * - Posture score circular gauge with grade letter
7
+ * - Severity breakdown horizontal bar chart
8
+ * - Agent activity table
9
+ * - Policy violations table with severity filter
10
+ * - Runtime protection, credential exposure, supply chain cards
11
+ * - Event timeline / narrative section
12
+ *
13
+ * Design tokens:
14
+ * Background: #0f172a (slate-900), Card: #1e293b (slate-800)
15
+ * Primary: #06b6d4 (teal), Score: teal
16
+ * Critical: #ef4444, High: #f97316, Medium: #eab308, Low: #3b82f6, Info: #6b7280
17
+ * Font: system monospace (JetBrains Mono fallback)
18
+ *
19
+ * No external dependencies. No emojis.
20
+ */
21
+ import type { WeeklyReport, ReportNarrative, PostureTrend } from './types.js';
22
+ import type { ClassifiedFinding } from './findings.js';
23
+ /**
24
+ * Generate the executive summary text from report data.
25
+ * No LLM needed -- deterministic sentence generation.
26
+ */
27
+ export declare function generateExecutiveSummary(report: WeeklyReport, findings: ClassifiedFinding[], trend: PostureTrend | null): string;
28
+ export declare function generateShieldHtmlReport(report: WeeklyReport, narrative?: ReportNarrative | null, findings?: ClassifiedFinding[], trend?: PostureTrend | null): string;
29
+ //# sourceMappingURL=report-html.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report-html.d.ts","sourceRoot":"","sources":["../../src/shield/report-html.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC9E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAEvD;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,iBAAiB,EAAE,EAC7B,KAAK,EAAE,YAAY,GAAG,IAAI,GACzB,MAAM,CAkER;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,YAAY,EACpB,SAAS,CAAC,EAAE,eAAe,GAAG,IAAI,EAClC,QAAQ,CAAC,EAAE,iBAAiB,EAAE,EAC9B,KAAK,CAAC,EAAE,YAAY,GAAG,IAAI,GAC1B,MAAM,CAsER"}