@panguard-ai/panguard 1.5.3 → 1.5.5

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 (65) hide show
  1. package/dist/cli/auth-guard.d.ts +58 -2
  2. package/dist/cli/auth-guard.d.ts.map +1 -1
  3. package/dist/cli/auth-guard.js +96 -2
  4. package/dist/cli/auth-guard.js.map +1 -1
  5. package/dist/cli/commands/audit.d.ts.map +1 -1
  6. package/dist/cli/commands/audit.js +45 -6
  7. package/dist/cli/commands/audit.js.map +1 -1
  8. package/dist/cli/commands/doctor.d.ts.map +1 -1
  9. package/dist/cli/commands/doctor.js +25 -31
  10. package/dist/cli/commands/doctor.js.map +1 -1
  11. package/dist/cli/commands/login.d.ts +19 -3
  12. package/dist/cli/commands/login.d.ts.map +1 -1
  13. package/dist/cli/commands/login.js +181 -9
  14. package/dist/cli/commands/login.js.map +1 -1
  15. package/dist/cli/commands/logout.d.ts +13 -3
  16. package/dist/cli/commands/logout.d.ts.map +1 -1
  17. package/dist/cli/commands/logout.js +63 -8
  18. package/dist/cli/commands/logout.js.map +1 -1
  19. package/dist/cli/commands/report.d.ts +27 -2
  20. package/dist/cli/commands/report.d.ts.map +1 -1
  21. package/dist/cli/commands/report.js +698 -45
  22. package/dist/cli/commands/report.js.map +1 -1
  23. package/dist/cli/commands/scan.d.ts.map +1 -1
  24. package/dist/cli/commands/scan.js +42 -3
  25. package/dist/cli/commands/scan.js.map +1 -1
  26. package/dist/cli/commands/sensor.d.ts +17 -0
  27. package/dist/cli/commands/sensor.d.ts.map +1 -0
  28. package/dist/cli/commands/sensor.js +183 -0
  29. package/dist/cli/commands/sensor.js.map +1 -0
  30. package/dist/cli/commands/setup.d.ts.map +1 -1
  31. package/dist/cli/commands/setup.js +8 -5
  32. package/dist/cli/commands/setup.js.map +1 -1
  33. package/dist/cli/commands/status.js +22 -5
  34. package/dist/cli/commands/status.js.map +1 -1
  35. package/dist/cli/commands/up.d.ts.map +1 -1
  36. package/dist/cli/commands/up.js +53 -2
  37. package/dist/cli/commands/up.js.map +1 -1
  38. package/dist/cli/commands/whoami.d.ts +30 -2
  39. package/dist/cli/commands/whoami.d.ts.map +1 -1
  40. package/dist/cli/commands/whoami.js +109 -16
  41. package/dist/cli/commands/whoami.js.map +1 -1
  42. package/dist/cli/device-flow.d.ts +72 -0
  43. package/dist/cli/device-flow.d.ts.map +1 -0
  44. package/dist/cli/device-flow.js +126 -0
  45. package/dist/cli/device-flow.js.map +1 -0
  46. package/dist/cli/index.js +14 -4
  47. package/dist/cli/index.js.map +1 -1
  48. package/dist/cli/interactive/actions/misc.d.ts.map +1 -1
  49. package/dist/cli/interactive/actions/misc.js +31 -7
  50. package/dist/cli/interactive/actions/misc.js.map +1 -1
  51. package/dist/cli/interactive/menu-defs.d.ts.map +1 -1
  52. package/dist/cli/interactive/menu-defs.js +4 -4
  53. package/dist/cli/interactive/menu-defs.js.map +1 -1
  54. package/dist/cli/interactive.d.ts.map +1 -1
  55. package/dist/cli/interactive.js +6 -1
  56. package/dist/cli/interactive.js.map +1 -1
  57. package/dist/cli/telemetry.d.ts +17 -0
  58. package/dist/cli/telemetry.d.ts.map +1 -1
  59. package/dist/cli/telemetry.js +33 -0
  60. package/dist/cli/telemetry.js.map +1 -1
  61. package/dist/cli/workspace-sync.d.ts +108 -0
  62. package/dist/cli/workspace-sync.d.ts.map +1 -0
  63. package/dist/cli/workspace-sync.js +199 -0
  64. package/dist/cli/workspace-sync.js.map +1 -0
  65. package/package.json +17 -12
@@ -1,22 +1,194 @@
1
1
  /**
2
- * `panguard login` - Authentication removed
3
- * `panguard login` - 驗證功能已移除
2
+ * `pga login` OAuth 2.0 Device Code Flow (RFC 8628).
4
3
  *
5
- * All features are free and open source. No login required.
4
+ * Same UX as `gh auth login`, `aws sso login`, and Claude Code CLI:
5
+ * 1. Request a device code from the server.
6
+ * 2. Print the short user code + verification URL.
7
+ * 3. Try to open the browser automatically (best effort).
8
+ * 4. Poll until the user authorises in the browser.
9
+ * 5. Persist `{ api_key, workspace, user }` to `~/.panguard/auth.json`
10
+ * with mode 0600.
11
+ *
12
+ * Secrets policy: the `api_key`, `device_code`, and `Authorization` header
13
+ * values are never printed or logged.
6
14
  *
7
15
  * @module @panguard-ai/panguard/cli/commands/login
8
16
  */
9
17
  import { Command } from 'commander';
18
+ import { mkdir, writeFile } from 'node:fs/promises';
19
+ import { dirname } from 'node:path';
20
+ import { c, symbols, box } from '@panguard-ai/core';
21
+ import { authConfigPath, loadAuth } from '../auth-guard.js';
22
+ import { DEFAULT_APP_URL, openBrowser, pollOnce, requestDeviceCode, resolveAppUrl, } from '../device-flow.js';
10
23
  export function loginCommand() {
11
24
  return new Command('login')
12
- .description('Authentication removed - all features are free')
13
- .action(async () => {
14
- console.log('');
15
- console.log(' Authentication removed. All features are free and open source.');
16
- console.log(' 驗證功能已移除。所有功能皆免費開源。');
25
+ .description('Sign in to PanGuard (opens browser for authorization)')
26
+ .option('--app-url <url>', `PanGuard app URL (default: ${DEFAULT_APP_URL})`)
27
+ .option('--no-browser', 'Do not attempt to open the browser')
28
+ .option('--force', 'Re-authenticate even if already logged in')
29
+ .option('--quiet', 'Suppress non-essential output')
30
+ .action(async (opts) => {
31
+ await runLogin(opts);
32
+ });
33
+ }
34
+ export async function runLogin(opts) {
35
+ const appUrl = resolveAppUrl(opts.appUrl);
36
+ const quiet = opts.quiet === true;
37
+ // If a valid session already exists, short-circuit unless --force.
38
+ if (!opts.force) {
39
+ const existing = await loadAuth();
40
+ if (existing) {
41
+ if (!quiet) {
42
+ console.log('');
43
+ console.log(` ${symbols.pass} Already logged in as ${c.bold(existing.user_email)} ` +
44
+ `(workspace: ${c.bold(existing.workspace_name)}).`);
45
+ console.log(` ${c.dim('Use `pga login --force` to switch accounts.')}`);
46
+ console.log('');
47
+ }
48
+ return;
49
+ }
50
+ }
51
+ // Step 1: request a device code.
52
+ let device;
53
+ try {
54
+ device = await requestDeviceCode(appUrl);
55
+ }
56
+ catch (err) {
57
+ console.error('');
58
+ console.error(` ${c.critical(symbols.fail)} Could not start login.`);
59
+ console.error(` ${c.dim(err instanceof Error ? err.message : String(err))}`);
60
+ console.error('');
61
+ process.exitCode = 1;
62
+ return;
63
+ }
64
+ // Step 2: print the panel.
65
+ printDevicePanel(device, quiet);
66
+ // Step 3: best-effort browser open.
67
+ if (opts.browser !== false) {
68
+ openBrowser(device.verification_uri_complete);
69
+ }
70
+ // Step 4: set up SIGINT handler for a clean cancel.
71
+ let cancelled = false;
72
+ const onSigint = () => {
73
+ cancelled = true;
17
74
  console.log('');
18
- console.log(' Visit https://github.com/panguard-ai/panguard-ai for more info.');
75
+ console.log(` ${c.caution(symbols.warn)} Login cancelled.`);
19
76
  console.log('');
77
+ process.exit(130); // 128 + SIGINT(2)
78
+ };
79
+ process.once('SIGINT', onSigint);
80
+ // Step 5: poll loop. `interval` may grow on `slow_down`.
81
+ try {
82
+ const success = await pollUntilDone(appUrl, device, () => cancelled);
83
+ if (!success) {
84
+ // pollUntilDone already printed a specific failure reason.
85
+ process.exitCode = 1;
86
+ return;
87
+ }
88
+ // Step 6: persist the session.
89
+ const authInfo = toAuthInfo(success);
90
+ await persistAuth(authInfo);
91
+ // Step 7: success banner.
92
+ if (!quiet)
93
+ printSuccessBanner(authInfo);
94
+ }
95
+ finally {
96
+ process.removeListener('SIGINT', onSigint);
97
+ }
98
+ }
99
+ function printDevicePanel(device, quiet) {
100
+ if (quiet) {
101
+ // Still print the code — the user needs it.
102
+ console.log(`Code: ${device.user_code}`);
103
+ console.log(`URL: ${device.verification_uri_complete}`);
104
+ return;
105
+ }
106
+ const content = [
107
+ c.heading('Authorize PanGuard CLI'),
108
+ '',
109
+ `${c.dim('Visit:')} ${c.bold(device.verification_uri)}`,
110
+ `${c.dim('Code:')} ${c.bold(device.user_code)}`,
111
+ '',
112
+ c.dim('Or open this link directly:'),
113
+ c.sage(device.verification_uri_complete),
114
+ '',
115
+ c.dim('Waiting for authorization ... (press Ctrl+C to cancel)'),
116
+ ].join('\n');
117
+ console.log('');
118
+ console.log(box(content, { padding: 2 }));
119
+ console.log('');
120
+ }
121
+ function printSuccessBanner(auth) {
122
+ console.log('');
123
+ console.log(` ${c.safe(symbols.pass)} Logged in as ${c.bold(auth.user_email)}.`);
124
+ console.log(` ${c.dim('Workspace:')} ${c.bold(auth.workspace_name)} ${c.dim(`(${auth.workspace_slug})`)}`);
125
+ console.log(` ${c.dim('Tier:')} ${c.bold(auth.tier)}`);
126
+ console.log('');
127
+ }
128
+ /**
129
+ * Poll the server until a terminal state is reached.
130
+ * Returns the success payload on auth, or null on expiry/error/cancel
131
+ * (after printing a user-facing message). Never throws.
132
+ */
133
+ async function pollUntilDone(appUrl, device, isCancelled) {
134
+ let intervalSec = Math.max(1, device.interval);
135
+ const deadlineMs = Date.now() + device.expires_in * 1000;
136
+ while (!isCancelled()) {
137
+ if (Date.now() > deadlineMs) {
138
+ console.error('');
139
+ console.error(` ${c.critical(symbols.fail)} Login code expired. Please run \`pga login\` again.`);
140
+ console.error('');
141
+ return null;
142
+ }
143
+ await sleep(intervalSec * 1000);
144
+ if (isCancelled())
145
+ return null;
146
+ const outcome = await pollOnce(appUrl, device.device_code);
147
+ switch (outcome.kind) {
148
+ case 'success':
149
+ return outcome.payload;
150
+ case 'pending':
151
+ continue;
152
+ case 'slow_down':
153
+ intervalSec += 5;
154
+ continue;
155
+ case 'expired':
156
+ console.error('');
157
+ console.error(` ${c.critical(symbols.fail)} Login code expired. Please run \`pga login\` again.`);
158
+ console.error('');
159
+ return null;
160
+ case 'error':
161
+ console.error('');
162
+ console.error(` ${c.critical(symbols.fail)} Login failed: ${outcome.message}`);
163
+ console.error('');
164
+ return null;
165
+ }
166
+ }
167
+ return null;
168
+ }
169
+ function toAuthInfo(payload) {
170
+ return Object.freeze({
171
+ api_key: payload.api_key,
172
+ workspace_id: payload.workspace.id,
173
+ workspace_slug: payload.workspace.slug,
174
+ workspace_name: payload.workspace.name,
175
+ tier: payload.workspace.tier,
176
+ user_email: payload.user.email,
177
+ logged_in_at: new Date().toISOString(),
178
+ // Optional TC correlation id — only written to auth.json when the server
179
+ // returns it. Older workspaces without a TC link omit this field.
180
+ ...(typeof payload.workspace.tc_org_id === 'string'
181
+ ? { tc_org_id: payload.workspace.tc_org_id }
182
+ : {}),
20
183
  });
21
184
  }
185
+ /** Write the session file with mode 0600. Creates parent dir if missing. */
186
+ async function persistAuth(auth) {
187
+ const target = authConfigPath();
188
+ await mkdir(dirname(target), { recursive: true, mode: 0o700 });
189
+ await writeFile(target, JSON.stringify(auth, null, 2), { mode: 0o600 });
190
+ }
191
+ function sleep(ms) {
192
+ return new Promise((resolve) => setTimeout(resolve, ms));
193
+ }
22
194
  //# sourceMappingURL=login.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"login.js","sourceRoot":"","sources":["../../../src/cli/commands/login.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,UAAU,YAAY;IAC1B,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC;SACxB,WAAW,CAAC,gDAAgD,CAAC;SAC7D,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,kEAAkE,CAAC,CAAC;QAChF,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;QACpC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,mEAAmE,CAAC,CAAC;QACjF,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACP,CAAC"}
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../../src/cli/commands/login.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,21 @@
1
1
  /**
2
- * `panguard logout` - Authentication removed
3
- * `panguard logout` - 驗證功能已移除
2
+ * `pga logout` clear the local session.
4
3
  *
5
- * All features are free and open source. No login required.
4
+ * 1. Best-effort POST to `${APP_URL}/api/auth/revoke` to invalidate the
5
+ * api_key server-side. Failures are swallowed — the local file is the
6
+ * source of truth for a logged-in session.
7
+ * 2. Delete `~/.panguard/auth.json`.
8
+ *
9
+ * The `api_key` is sent only in the Authorization header and is never logged.
6
10
  *
7
11
  * @module @panguard-ai/panguard/cli/commands/logout
8
12
  */
9
13
  import { Command } from 'commander';
14
+ interface LogoutOptions {
15
+ appUrl?: string;
16
+ quiet?: boolean;
17
+ }
10
18
  export declare function logoutCommand(): Command;
19
+ export declare function runLogout(opts: LogoutOptions): Promise<void>;
20
+ export {};
11
21
  //# sourceMappingURL=logout.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/logout.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,wBAAgB,aAAa,IAAI,OAAO,CASvC"}
1
+ {"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/logout.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,UAAU,aAAa;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,wBAAgB,aAAa,IAAI,OAAO,CAQvC;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAmDlE"}
@@ -1,20 +1,75 @@
1
1
  /**
2
- * `panguard logout` - Authentication removed
3
- * `panguard logout` - 驗證功能已移除
2
+ * `pga logout` clear the local session.
4
3
  *
5
- * All features are free and open source. No login required.
4
+ * 1. Best-effort POST to `${APP_URL}/api/auth/revoke` to invalidate the
5
+ * api_key server-side. Failures are swallowed — the local file is the
6
+ * source of truth for a logged-in session.
7
+ * 2. Delete `~/.panguard/auth.json`.
8
+ *
9
+ * The `api_key` is sent only in the Authorization header and is never logged.
6
10
  *
7
11
  * @module @panguard-ai/panguard/cli/commands/logout
8
12
  */
9
13
  import { Command } from 'commander';
14
+ import { rm } from 'node:fs/promises';
15
+ import { c, symbols } from '@panguard-ai/core';
16
+ import { authConfigPath, loadAuth } from '../auth-guard.js';
17
+ import { DEFAULT_APP_URL, resolveAppUrl } from '../device-flow.js';
10
18
  export function logoutCommand() {
11
19
  return new Command('logout')
12
- .description('Authentication removed - all features are free')
13
- .action(async () => {
20
+ .description('Sign out and clear local PanGuard session')
21
+ .option('--app-url <url>', `PanGuard app URL (default: ${DEFAULT_APP_URL})`)
22
+ .option('--quiet', 'Suppress non-essential output')
23
+ .action(async (opts) => {
24
+ await runLogout(opts);
25
+ });
26
+ }
27
+ export async function runLogout(opts) {
28
+ const auth = await loadAuth();
29
+ const quiet = opts.quiet === true;
30
+ if (!auth) {
31
+ if (!quiet) {
32
+ console.log('');
33
+ console.log(` ${c.dim(symbols.info)} Not logged in — nothing to do.`);
34
+ console.log('');
35
+ }
36
+ return;
37
+ }
38
+ // Best-effort server-side revoke. We intentionally ignore failures so a
39
+ // dropped network (e.g. offline laptop) never blocks local cleanup.
40
+ const appUrl = resolveAppUrl(opts.appUrl);
41
+ try {
42
+ await fetch(`${appUrl}/api/auth/revoke`, {
43
+ method: 'POST',
44
+ headers: {
45
+ Authorization: `Bearer ${auth.api_key}`,
46
+ 'Content-Type': 'application/json',
47
+ },
48
+ body: JSON.stringify({}),
49
+ signal: AbortSignal.timeout(5_000),
50
+ });
51
+ }
52
+ catch {
53
+ // Swallow — local cleanup still happens below.
54
+ }
55
+ // Always remove the local file. `rm --force` behaviour via { force: true }.
56
+ try {
57
+ await rm(authConfigPath(), { force: true });
58
+ }
59
+ catch (err) {
60
+ if (!quiet) {
61
+ console.error('');
62
+ console.error(` ${c.critical(symbols.fail)} Could not remove local session file: ` +
63
+ (err instanceof Error ? err.message : String(err)));
64
+ console.error('');
65
+ }
66
+ process.exitCode = 1;
67
+ return;
68
+ }
69
+ if (!quiet) {
14
70
  console.log('');
15
- console.log(' Authentication removed. All features are free and open source.');
16
- console.log(' 驗證功能已移除。所有功能皆免費開源。');
71
+ console.log(` ${c.safe(symbols.pass)} Logged out.`);
17
72
  console.log('');
18
- });
73
+ }
19
74
  }
20
75
  //# sourceMappingURL=logout.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"logout.js","sourceRoot":"","sources":["../../../src/cli/commands/logout.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,UAAU,aAAa;IAC3B,OAAO,IAAI,OAAO,CAAC,QAAQ,CAAC;SACzB,WAAW,CAAC,gDAAgD,CAAC;SAC7D,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,kEAAkE,CAAC,CAAC;QAChF,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;QACpC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACP,CAAC"}
1
+ {"version":3,"file":"logout.js","sourceRoot":"","sources":["../../../src/cli/commands/logout.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACtC,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAOnE,MAAM,UAAU,aAAa;IAC3B,OAAO,IAAI,OAAO,CAAC,QAAQ,CAAC;SACzB,WAAW,CAAC,2CAA2C,CAAC;SACxD,MAAM,CAAC,iBAAiB,EAAE,8BAA8B,eAAe,GAAG,CAAC;SAC3E,MAAM,CAAC,SAAS,EAAE,+BAA+B,CAAC;SAClD,MAAM,CAAC,KAAK,EAAE,IAAmB,EAAE,EAAE;QACpC,MAAM,SAAS,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC,CAAC,CAAC;AACP,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAmB;IACjD,MAAM,IAAI,GAAG,MAAM,QAAQ,EAAE,CAAC;IAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC;IAElC,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAChB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;YACvE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClB,CAAC;QACD,OAAO;IACT,CAAC;IAED,wEAAwE;IACxE,oEAAoE;IACpE,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC1C,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,GAAG,MAAM,kBAAkB,EAAE;YACvC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,aAAa,EAAE,UAAU,IAAI,CAAC,OAAO,EAAE;gBACvC,cAAc,EAAE,kBAAkB;aACnC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;YACxB,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC;SACnC,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,+CAA+C;IACjD,CAAC;IAED,4EAA4E;IAC5E,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,cAAc,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAClB,OAAO,CAAC,KAAK,CACX,KAAK,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,wCAAwC;gBACnE,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CACrD,CAAC;YACF,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACpB,CAAC;QACD,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACrD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
@@ -1,6 +1,31 @@
1
1
  /**
2
- * panguard report - Compliance report generation (Coming Soon)
3
- * panguard report - 合規報告產生(即將推出)
2
+ * panguard report AI Compliance Audit Evidence report generator
3
+ *
4
+ * Reads ATR rule YAML (from @panguard-ai/agent-threat-rules node_modules) and
5
+ * produces auditor-readable reports mapping each rule to compliance framework
6
+ * articles / clauses / subcategories. This is the Enterprise tier's core
7
+ * differentiator (product "D1").
8
+ *
9
+ * Usage:
10
+ * pga report list-frameworks
11
+ * pga report summary --framework <name>
12
+ * pga report generate --framework <name> [--format md|json|pdf] [--output <path>] [--sign <key>]
13
+ *
14
+ * Every report includes a SHA-256 integrity hash computed over the
15
+ * canonical JSON representation, and optionally an HMAC-SHA256
16
+ * signature (via --sign or PANGUARD_REPORT_SIGNING_KEY env var).
17
+ * PDFs additionally write a sidecar <output>.hash file for auditor
18
+ * verification.
19
+ *
20
+ * Supported framework ids:
21
+ * owasp-agentic — OWASP Agentic Top 10 (2026)
22
+ * owasp-llm — OWASP LLM Top 10 (2025)
23
+ * eu-ai-act — EU AI Act (Regulation 2024/1689)
24
+ * colorado-ai-act — Colorado SB24-205
25
+ * nist-ai-rmf — NIST AI RMF 1.0
26
+ * iso-42001 — ISO/IEC 42001:2023
27
+ *
28
+ * @module @panguard-ai/panguard/cli/commands/report
4
29
  */
5
30
  import { Command } from 'commander';
6
31
  export declare function reportCommand(): Command;
@@ -1 +1 @@
1
- {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/report.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkBpC,wBAAgB,aAAa,IAAI,OAAO,CA4CvC"}
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/report.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgyBpC,wBAAgB,aAAa,IAAI,OAAO,CAkDvC"}