@panguard-ai/panguard 1.5.4 → 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.
- package/dist/cli/auth-guard.d.ts +58 -2
- package/dist/cli/auth-guard.d.ts.map +1 -1
- package/dist/cli/auth-guard.js +96 -2
- package/dist/cli/auth-guard.js.map +1 -1
- package/dist/cli/commands/audit.d.ts.map +1 -1
- package/dist/cli/commands/audit.js +45 -6
- package/dist/cli/commands/audit.js.map +1 -1
- package/dist/cli/commands/doctor.d.ts.map +1 -1
- package/dist/cli/commands/doctor.js +25 -31
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/login.d.ts +19 -3
- package/dist/cli/commands/login.d.ts.map +1 -1
- package/dist/cli/commands/login.js +181 -9
- package/dist/cli/commands/login.js.map +1 -1
- package/dist/cli/commands/logout.d.ts +13 -3
- package/dist/cli/commands/logout.d.ts.map +1 -1
- package/dist/cli/commands/logout.js +63 -8
- package/dist/cli/commands/logout.js.map +1 -1
- package/dist/cli/commands/report.d.ts +27 -2
- package/dist/cli/commands/report.d.ts.map +1 -1
- package/dist/cli/commands/report.js +698 -45
- package/dist/cli/commands/report.js.map +1 -1
- package/dist/cli/commands/scan.d.ts.map +1 -1
- package/dist/cli/commands/scan.js +21 -1
- package/dist/cli/commands/scan.js.map +1 -1
- package/dist/cli/commands/sensor.d.ts +17 -0
- package/dist/cli/commands/sensor.d.ts.map +1 -0
- package/dist/cli/commands/sensor.js +183 -0
- package/dist/cli/commands/sensor.js.map +1 -0
- package/dist/cli/commands/setup.d.ts.map +1 -1
- package/dist/cli/commands/setup.js +8 -5
- package/dist/cli/commands/setup.js.map +1 -1
- package/dist/cli/commands/status.js +22 -5
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/commands/up.d.ts.map +1 -1
- package/dist/cli/commands/up.js +53 -2
- package/dist/cli/commands/up.js.map +1 -1
- package/dist/cli/commands/whoami.d.ts +30 -2
- package/dist/cli/commands/whoami.d.ts.map +1 -1
- package/dist/cli/commands/whoami.js +109 -16
- package/dist/cli/commands/whoami.js.map +1 -1
- package/dist/cli/device-flow.d.ts +72 -0
- package/dist/cli/device-flow.d.ts.map +1 -0
- package/dist/cli/device-flow.js +126 -0
- package/dist/cli/device-flow.js.map +1 -0
- package/dist/cli/index.js +14 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/interactive/actions/misc.d.ts.map +1 -1
- package/dist/cli/interactive/actions/misc.js +31 -7
- package/dist/cli/interactive/actions/misc.js.map +1 -1
- package/dist/cli/interactive/menu-defs.d.ts.map +1 -1
- package/dist/cli/interactive/menu-defs.js +4 -4
- package/dist/cli/interactive/menu-defs.js.map +1 -1
- package/dist/cli/interactive.d.ts.map +1 -1
- package/dist/cli/interactive.js +6 -1
- package/dist/cli/interactive.js.map +1 -1
- package/dist/cli/telemetry.d.ts +17 -0
- package/dist/cli/telemetry.d.ts.map +1 -1
- package/dist/cli/telemetry.js +33 -0
- package/dist/cli/telemetry.js.map +1 -1
- package/dist/cli/workspace-sync.d.ts +108 -0
- package/dist/cli/workspace-sync.d.ts.map +1 -0
- package/dist/cli/workspace-sync.js +199 -0
- package/dist/cli/workspace-sync.js.map +1 -0
- package/package.json +17 -12
|
@@ -1,22 +1,194 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `
|
|
3
|
-
* `panguard login` - 驗證功能已移除
|
|
2
|
+
* `pga login` — OAuth 2.0 Device Code Flow (RFC 8628).
|
|
4
3
|
*
|
|
5
|
-
*
|
|
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('
|
|
13
|
-
.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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(
|
|
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
|
|
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
|
-
* `
|
|
3
|
-
* `panguard logout` - 驗證功能已移除
|
|
2
|
+
* `pga logout` — clear the local session.
|
|
4
3
|
*
|
|
5
|
-
*
|
|
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
|
|
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
|
-
* `
|
|
3
|
-
* `panguard logout` - 驗證功能已移除
|
|
2
|
+
* `pga logout` — clear the local session.
|
|
4
3
|
*
|
|
5
|
-
*
|
|
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('
|
|
13
|
-
.
|
|
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(
|
|
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
|
|
1
|
+
{"version":3,"file":"logout.js","sourceRoot":"","sources":["../../../src/cli/commands/logout.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* panguard report
|
|
3
|
-
*
|
|
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
|
|
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"}
|