@peac/cli 0.13.4 → 0.14.1
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/commands/emit-lifecycle.d.ts +140 -0
- package/dist/commands/emit-lifecycle.d.ts.map +1 -0
- package/dist/commands/observe-command.d.ts +135 -0
- package/dist/commands/observe-command.d.ts.map +1 -0
- package/dist/commands/record-command.d.ts +102 -0
- package/dist/commands/record-command.d.ts.map +1 -0
- package/dist/index.cjs +1922 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +1930 -10
- package/dist/index.mjs.map +1 -1
- package/dist/lib/capture.d.ts +118 -0
- package/dist/lib/capture.d.ts.map +1 -0
- package/dist/lib/cli-limits.d.ts +49 -0
- package/dist/lib/cli-limits.d.ts.map +1 -0
- package/dist/lib/command-option-validation.d.ts +94 -0
- package/dist/lib/command-option-validation.d.ts.map +1 -0
- package/dist/lib/issuer-key-loader.d.ts +56 -0
- package/dist/lib/issuer-key-loader.d.ts.map +1 -0
- package/dist/lib/observation-builder.d.ts +79 -0
- package/dist/lib/observation-builder.d.ts.map +1 -0
- package/dist/lib/observation-pipeline.d.ts +96 -0
- package/dist/lib/observation-pipeline.d.ts.map +1 -0
- package/dist/lib/output-preflight.d.ts +28 -0
- package/dist/lib/output-preflight.d.ts.map +1 -0
- package/dist/lib/secret-scan.d.ts +35 -0
- package/dist/lib/secret-scan.d.ts.map +1 -0
- package/package.json +8 -8
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI subprocess capture.
|
|
3
|
+
*
|
|
4
|
+
* Implements the bounded-capture wrapper used by `peac observe command`
|
|
5
|
+
* and `peac record command`. Hard implementation invariants:
|
|
6
|
+
*
|
|
7
|
+
* - Spawn discipline: `spawn(prog, args, { shell: false })`
|
|
8
|
+
* exclusively. NEVER `exec()`. The wrapper does NOT synthesize
|
|
9
|
+
* shell syntax or rewrite the command. `--shell-mode` is
|
|
10
|
+
* acknowledgement only.
|
|
11
|
+
* - Streaming capture: `node:crypto.createHash` updated chunk-by-chunk.
|
|
12
|
+
* Byte counter incremented chunk-by-chunk. Bounded sample buffer
|
|
13
|
+
* is the ONLY buffer retained, and ONLY when raw capture is
|
|
14
|
+
* double-opted-in. Full streams NEVER held in memory.
|
|
15
|
+
* - Stdin: `--capture-stdin-mode` controls BOTH whether the wrapper
|
|
16
|
+
* pipes parent stdin to the child AND what the wrapper records.
|
|
17
|
+
* `none` (default) closes child stdin and does NOT read parent stdin.
|
|
18
|
+
* The stdin pump must terminate when the child exits even if the
|
|
19
|
+
* parent stream is still open.
|
|
20
|
+
* - Timeout: `--timeout-ms` / `--kill-grace-ms` cascade SIGTERM then
|
|
21
|
+
* SIGKILL; the record IS still emitted. The nested SIGKILL timer
|
|
22
|
+
* is cleared on child close so it cannot keep the event loop alive.
|
|
23
|
+
* - Signal exit codes follow POSIX `128 + signal-num`: SIGINT=130,
|
|
24
|
+
* SIGTERM=143, SIGKILL=137; unknown signals fall back to 128.
|
|
25
|
+
* - Stdin pumping is listener-based (event handlers attached to the
|
|
26
|
+
* parent stream and child stdin). Backpressure pauses the parent
|
|
27
|
+
* until child stdin emits 'drain'. The pump is reliably abortable
|
|
28
|
+
* via an external AbortSignal even if the parent stream stays
|
|
29
|
+
* open and idle, and removes ONLY pump-owned listeners on cleanup
|
|
30
|
+
* (the parent is caller-owned).
|
|
31
|
+
*/
|
|
32
|
+
import type { Readable } from 'node:stream';
|
|
33
|
+
/**
|
|
34
|
+
* Thrown by `captureCommand` when the child process fails to spawn
|
|
35
|
+
* (missing binary, ENOENT, EACCES, etc.). Node emits the `'error'`
|
|
36
|
+
* event in this case and never emits `'spawn'`/`'close'` -- without
|
|
37
|
+
* explicit handling the wrapper would hang waiting for `'close'`.
|
|
38
|
+
*/
|
|
39
|
+
export declare class CliSpawnFailedError extends Error {
|
|
40
|
+
readonly cause?: unknown | undefined;
|
|
41
|
+
readonly code = "cli.spawn_failed";
|
|
42
|
+
constructor(message: string, cause?: unknown | undefined);
|
|
43
|
+
}
|
|
44
|
+
export type StdinMode = 'none' | 'length-only' | 'hashed';
|
|
45
|
+
export type CaptureMode = 'hashed' | 'redacted' | 'raw';
|
|
46
|
+
export interface CaptureOptions {
|
|
47
|
+
/** Resolved program path (passed verbatim to `spawn`). */
|
|
48
|
+
program: string;
|
|
49
|
+
/** Argv tail (passed verbatim to `spawn`; never wrapped in a shell). */
|
|
50
|
+
args: string[];
|
|
51
|
+
/** Working directory for the child (passed to `spawn`); not the recorded cwd. */
|
|
52
|
+
cwd: string;
|
|
53
|
+
/**
|
|
54
|
+
* Environment passed to the child. REQUIRED. Callers (the
|
|
55
|
+
* pipeline / pure handler) must construct the env explicitly so
|
|
56
|
+
* the env source is auditable; this function does NOT silently
|
|
57
|
+
* fall back to `process.env`.
|
|
58
|
+
*/
|
|
59
|
+
env: NodeJS.ProcessEnv;
|
|
60
|
+
stdinMode: StdinMode;
|
|
61
|
+
/**
|
|
62
|
+
* Whether raw sample emission is enabled (requires `--capture-mode raw`
|
|
63
|
+
* AND `--unsafe-allow-raw-capture`). When false, no `sample_base64` is
|
|
64
|
+
* retained for stdout / stderr and the bounded sample buffer stays
|
|
65
|
+
* empty even though the streams are still hashed and counted.
|
|
66
|
+
*/
|
|
67
|
+
rawCaptureEnabled: boolean;
|
|
68
|
+
/** Bounded sample cap for stdout (raw mode only). */
|
|
69
|
+
stdoutSampleBytes: number;
|
|
70
|
+
/** Bounded sample cap for stderr (raw mode only). */
|
|
71
|
+
stderrSampleBytes: number;
|
|
72
|
+
/** Wrapper timeout (ms). After this, the wrapper sends SIGTERM. */
|
|
73
|
+
timeoutMs: number;
|
|
74
|
+
/** SIGTERM-to-SIGKILL grace (ms). */
|
|
75
|
+
killGraceMs: number;
|
|
76
|
+
/**
|
|
77
|
+
* Optional readable from which to source parent stdin. Defaults to
|
|
78
|
+
* `process.stdin`. Tests inject a custom stream.
|
|
79
|
+
*/
|
|
80
|
+
parentStdin?: Readable;
|
|
81
|
+
}
|
|
82
|
+
export interface StreamCaptureRef {
|
|
83
|
+
length: number;
|
|
84
|
+
/** sha256 hex digest with the canonical `sha256:` prefix. */
|
|
85
|
+
sha256: string;
|
|
86
|
+
truncated: boolean;
|
|
87
|
+
/** Present only when raw capture is enabled and the secret-scan does not suppress it. */
|
|
88
|
+
sample_base64?: string;
|
|
89
|
+
}
|
|
90
|
+
export interface StdinCaptureRef {
|
|
91
|
+
mode: StdinMode;
|
|
92
|
+
length?: number;
|
|
93
|
+
sha256?: string;
|
|
94
|
+
truncated?: boolean;
|
|
95
|
+
}
|
|
96
|
+
export interface CaptureResult {
|
|
97
|
+
exitCode: number;
|
|
98
|
+
/** OS-reported child exit signal. Distinct from `terminationSignal`. */
|
|
99
|
+
signal: string | null;
|
|
100
|
+
/** True when the wrapper sent termination signals due to `--timeout-ms` elapsing. */
|
|
101
|
+
timedOut: boolean;
|
|
102
|
+
/** Signal sent BY THE WRAPPER after timeout. */
|
|
103
|
+
terminationSignal: string | null;
|
|
104
|
+
startedAt: string;
|
|
105
|
+
finishedAt: string;
|
|
106
|
+
durationMs: number;
|
|
107
|
+
stdout: StreamCaptureRef;
|
|
108
|
+
stderr: StreamCaptureRef;
|
|
109
|
+
stdin: StdinCaptureRef;
|
|
110
|
+
}
|
|
111
|
+
export declare function exitCodeForSignal(signal: string | null | undefined): number;
|
|
112
|
+
/**
|
|
113
|
+
* Run the bounded-capture wrapper. The promise resolves when the child
|
|
114
|
+
* exits OR is killed by the wrapper after timeout; it does NOT reject
|
|
115
|
+
* on non-zero exit; the record IS still emitted regardless of child exit code.
|
|
116
|
+
*/
|
|
117
|
+
export declare function captureCommand(opts: CaptureOptions): Promise<CaptureResult>;
|
|
118
|
+
//# sourceMappingURL=capture.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capture.d.ts","sourceRoot":"","sources":["../../src/lib/capture.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAIH,OAAO,KAAK,EAAE,QAAQ,EAAY,MAAM,aAAa,CAAC;AAEtD;;;;;GAKG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;IAI1C,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO;IAH1B,QAAQ,CAAC,IAAI,sBAAsB;gBAEjC,OAAO,EAAE,MAAM,EACN,KAAK,CAAC,EAAE,OAAO,YAAA;CAK3B;AAED,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,aAAa,GAAG,QAAQ,CAAC;AAC1D,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,UAAU,GAAG,KAAK,CAAC;AAyCxD,MAAM,WAAW,cAAc;IAC7B,0DAA0D;IAC1D,OAAO,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,iFAAiF;IACjF,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;OAKG;IACH,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,SAAS,EAAE,SAAS,CAAC;IACrB;;;;;OAKG;IACH,iBAAiB,EAAE,OAAO,CAAC;IAC3B,qDAAqD;IACrD,iBAAiB,EAAE,MAAM,CAAC;IAC1B,qDAAqD;IACrD,iBAAiB,EAAE,MAAM,CAAC;IAC1B,mEAAmE;IACnE,SAAS,EAAE,MAAM,CAAC;IAClB,qCAAqC;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,WAAW,CAAC,EAAE,QAAQ,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;IACnB,yFAAyF;IACzF,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,SAAS,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,qFAAqF;IACrF,QAAQ,EAAE,OAAO,CAAC;IAClB,gDAAgD;IAChD,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,gBAAgB,CAAC;IACzB,MAAM,EAAE,gBAAgB,CAAC;IACzB,KAAK,EAAE,eAAe,CAAC;CACxB;AAsBD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAG3E;AAsND;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CAgJjF"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI capture limits and security defaults.
|
|
3
|
+
*
|
|
4
|
+
* Centralizes the bounded-capture caps and security-default constants
|
|
5
|
+
* used by `peac observe command` and `peac record command`. Mirrored
|
|
6
|
+
* (but enforced separately) by the Zod ranges in
|
|
7
|
+
* `@peac/schema/src/extensions/cli-execution.ts`; keep both sides in
|
|
8
|
+
* sync when changing.
|
|
9
|
+
*
|
|
10
|
+
* All values are POSIX-first. Windows behavior is not guaranteed by
|
|
11
|
+
* the current CLI carrier profile; see `docs/specs/CLI-CARRIER-PROFILE.md`.
|
|
12
|
+
*/
|
|
13
|
+
/** Bounded-capture caps. */
|
|
14
|
+
export declare const CLI_LIMITS: {
|
|
15
|
+
/** Default max bytes retained in the stdout sample buffer (raw mode only). */
|
|
16
|
+
readonly defaultStdoutSampleBytes: 16384;
|
|
17
|
+
/** Default max bytes retained in the stderr sample buffer (raw mode only). */
|
|
18
|
+
readonly defaultStderrSampleBytes: 16384;
|
|
19
|
+
/** Hard ceiling for the stdout / stderr sample buffer (raw mode only). */
|
|
20
|
+
readonly maxStdoutSampleBytes: 65536;
|
|
21
|
+
readonly maxStderrSampleBytes: 65536;
|
|
22
|
+
/** Default max bytes recorded in argv (raw mode only). */
|
|
23
|
+
readonly defaultArgvCaptureBytes: 4096;
|
|
24
|
+
/** Hard ceiling for argv bytes (raw mode only). */
|
|
25
|
+
readonly maxArgvCaptureBytes: 16384;
|
|
26
|
+
/** Hard ceiling for env entry count (deny-by-default; allowlist <= this). */
|
|
27
|
+
readonly maxEnvEntries: 32;
|
|
28
|
+
/** Default wrapper timeout (10 minutes). */
|
|
29
|
+
readonly defaultTimeoutMs: 600000;
|
|
30
|
+
/** Wrapper timeout hard ceiling (24 hours). */
|
|
31
|
+
readonly maxTimeoutMs: 86400000;
|
|
32
|
+
/** Wrapper timeout floor (1 ms). */
|
|
33
|
+
readonly minTimeoutMs: 1;
|
|
34
|
+
/** Default SIGTERM-to-SIGKILL grace (5 seconds). */
|
|
35
|
+
readonly defaultKillGraceMs: 5000;
|
|
36
|
+
/** SIGTERM-to-SIGKILL grace hard ceiling (60 seconds). */
|
|
37
|
+
readonly maxKillGraceMs: 60000;
|
|
38
|
+
/** SIGTERM-to-SIGKILL grace floor. */
|
|
39
|
+
readonly minKillGraceMs: 0;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Shell binaries that, when detected as the program basename, REQUIRE
|
|
43
|
+
* the explicit `--shell-mode` acknowledgement. PEAC NEVER synthesizes
|
|
44
|
+
* shell syntax; the wrapper is an observer, not a shell orchestrator.
|
|
45
|
+
*/
|
|
46
|
+
export declare const SHELL_BINARY_BASENAMES: Set<string>;
|
|
47
|
+
/** Returns true when the resolved program basename is a known shell binary. */
|
|
48
|
+
export declare function isShellBinary(programBasename: string): boolean;
|
|
49
|
+
//# sourceMappingURL=cli-limits.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-limits.d.ts","sourceRoot":"","sources":["../../src/lib/cli-limits.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,4BAA4B;AAC5B,eAAO,MAAM,UAAU;IACrB,8EAA8E;;IAE9E,8EAA8E;;IAE9E,0EAA0E;;;IAI1E,0DAA0D;;IAE1D,mDAAmD;;IAGnD,6EAA6E;;IAG7E,4CAA4C;;IAE5C,+CAA+C;;IAE/C,oCAAoC;;IAGpC,oDAAoD;;IAEpD,0DAA0D;;IAE1D,sCAAsC;;CAE9B,CAAC;AAEX;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,aAQjC,CAAC;AAEH,+EAA+E;AAC/E,wBAAgB,aAAa,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAE9D"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared command-option validation for `observe command` and
|
|
3
|
+
* `record command`. Single source of truth for:
|
|
4
|
+
*
|
|
5
|
+
* - numeric flag range / NaN-safe checks
|
|
6
|
+
* - env-allowlist key grammar + byte cap
|
|
7
|
+
* - record-only digest / opaque-ref preflights
|
|
8
|
+
* - raw capture / raw env / secret-scan unsafe-flag pairing
|
|
9
|
+
* - shell-binary detection acknowledgement
|
|
10
|
+
* - raw argv per-token cap
|
|
11
|
+
*
|
|
12
|
+
* Both commands consume `validateCoreCommandOptions` so their
|
|
13
|
+
* preflight semantics never drift. Record-command additionally calls
|
|
14
|
+
* `validateSigningOptions` for the signing-input mutex and canonical
|
|
15
|
+
* issuer URL check.
|
|
16
|
+
*/
|
|
17
|
+
import type { ArgvMode, CwdMode, BinaryPathMode, EnvMode, StdinMode, ExitCodeMode, ExecutionMode } from './observation-builder.js';
|
|
18
|
+
/**
|
|
19
|
+
* Stable error codes shared by observe command and record command. The
|
|
20
|
+
* subcommands re-export the relevant subset under their own
|
|
21
|
+
* `OBSERVE_COMMAND_ERROR_CODES` / `RECORD_COMMAND_ERROR_CODES` for
|
|
22
|
+
* call-site clarity; both names point at these strings.
|
|
23
|
+
*/
|
|
24
|
+
export declare const COMMAND_OPTION_ERROR_CODES: {
|
|
25
|
+
readonly programRequired: "cli.program_required";
|
|
26
|
+
readonly unsafeFlagRequired: "cli.unsafe_flag_required";
|
|
27
|
+
readonly secretScanDisableRequiresUnsafeFlag: "cli.secret_scan_disable_requires_unsafe_flag";
|
|
28
|
+
readonly shellModeRequired: "cli.shell_mode_required";
|
|
29
|
+
readonly argvTokenTooLong: "cli.argv_token_too_long";
|
|
30
|
+
readonly outOfRange: "cli.out_of_range";
|
|
31
|
+
readonly invalidPolicyDigest: "cli.invalid_policy_digest";
|
|
32
|
+
readonly invalidConfigDigest: "cli.invalid_config_digest";
|
|
33
|
+
readonly invalidApprovalRef: "cli.invalid_approval_ref";
|
|
34
|
+
readonly invalidEnvKey: "cli.invalid_env_key";
|
|
35
|
+
readonly signingInputRequired: "cli.signing_input_required";
|
|
36
|
+
readonly signingInputConflict: "cli.signing_input_conflict";
|
|
37
|
+
readonly issuerIdRequired: "cli.issuer_id_required";
|
|
38
|
+
readonly issuerIdInvalid: "cli.issuer_id_invalid";
|
|
39
|
+
};
|
|
40
|
+
export interface ValidationFailure {
|
|
41
|
+
code: string;
|
|
42
|
+
message: string;
|
|
43
|
+
}
|
|
44
|
+
/** Common option shape both subcommands share (no signing fields). */
|
|
45
|
+
export interface CoreCommandOptions {
|
|
46
|
+
captureMode: ArgvMode;
|
|
47
|
+
unsafeAllowRawCapture: boolean;
|
|
48
|
+
captureStdinMode: StdinMode;
|
|
49
|
+
captureStdoutBytes: number;
|
|
50
|
+
captureStderrBytes: number;
|
|
51
|
+
captureArgvBytes: number;
|
|
52
|
+
envAllow: string[];
|
|
53
|
+
envMode: EnvMode;
|
|
54
|
+
unsafeAllowRawEnv: boolean;
|
|
55
|
+
captureCwdMode: CwdMode;
|
|
56
|
+
captureBinaryPath: BinaryPathMode;
|
|
57
|
+
secretScan: boolean;
|
|
58
|
+
unsafeDisableSecretScan: boolean;
|
|
59
|
+
policyDigest?: string;
|
|
60
|
+
configDigest?: string;
|
|
61
|
+
approvalRef?: string;
|
|
62
|
+
executionMode: ExecutionMode;
|
|
63
|
+
shellMode: boolean;
|
|
64
|
+
timeoutMs: number;
|
|
65
|
+
killGraceMs: number;
|
|
66
|
+
exitCodeMode: ExitCodeMode;
|
|
67
|
+
}
|
|
68
|
+
/** Signing-input shape consumed by record command. */
|
|
69
|
+
export interface SigningOptions {
|
|
70
|
+
issuerKey?: string;
|
|
71
|
+
issuerId?: string;
|
|
72
|
+
unsafeEphemeralKey: boolean;
|
|
73
|
+
}
|
|
74
|
+
/** True iff `n` is a finite, in-range integer (rejects NaN, Infinity, floats). */
|
|
75
|
+
export declare function isValidIntInRange(n: unknown, min: number, max: number): boolean;
|
|
76
|
+
/** UTF-8 byte length of a string. */
|
|
77
|
+
export declare function utf8Bytes(s: string): number;
|
|
78
|
+
/** Platform-agnostic basename -- strips both `/` and `\`. */
|
|
79
|
+
export declare function basenameAny(p: string): string;
|
|
80
|
+
/**
|
|
81
|
+
* Validate flags shared by observe command and record command. Returns
|
|
82
|
+
* an array of failures; empty when the options + child argv are
|
|
83
|
+
* acceptable. Caller surfaces failures to stderr and exits 2 BEFORE
|
|
84
|
+
* spawning the child.
|
|
85
|
+
*/
|
|
86
|
+
export declare function validateCoreCommandOptions(opts: CoreCommandOptions, childArgv: string[]): ValidationFailure[];
|
|
87
|
+
/**
|
|
88
|
+
* Validate signing-input flags consumed by record command. Enforces
|
|
89
|
+
* mutex (--issuer-key XOR --unsafe-ephemeral-key), required
|
|
90
|
+
* --issuer-id, and canonical-issuer-URL form. Caller appends these
|
|
91
|
+
* failures to the core failures and exits 2 BEFORE running the child.
|
|
92
|
+
*/
|
|
93
|
+
export declare function validateSigningOptions(opts: SigningOptions): ValidationFailure[];
|
|
94
|
+
//# sourceMappingURL=command-option-validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-option-validation.d.ts","sourceRoot":"","sources":["../../src/lib/command-option-validation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,OAAO,KAAK,EACV,QAAQ,EACR,OAAO,EACP,cAAc,EACd,OAAO,EACP,SAAS,EACT,YAAY,EACZ,aAAa,EACd,MAAM,0BAA0B,CAAC;AAElC;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;CAgB7B,CAAC;AAEX,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,sEAAsE;AACtE,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,QAAQ,CAAC;IACtB,qBAAqB,EAAE,OAAO,CAAC;IAC/B,gBAAgB,EAAE,SAAS,CAAC;IAC5B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,cAAc,EAAE,OAAO,CAAC;IACxB,iBAAiB,EAAE,cAAc,CAAC;IAClC,UAAU,EAAE,OAAO,CAAC;IACpB,uBAAuB,EAAE,OAAO,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,aAAa,CAAC;IAC7B,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,YAAY,CAAC;CAC5B;AAED,sDAAsD;AACtD,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kBAAkB,EAAE,OAAO,CAAC;CAC7B;AAMD,kFAAkF;AAClF,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAE/E;AAED,qCAAqC;AACrC,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE3C;AAED,6DAA6D;AAC7D,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,kBAAkB,EACxB,SAAS,EAAE,MAAM,EAAE,GAClB,iBAAiB,EAAE,CA6IrB;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,cAAc,GAAG,iBAAiB,EAAE,CA6BhF"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Issuer-key loader for `peac record command`.
|
|
3
|
+
*
|
|
4
|
+
* Implements the same issuer-key reference convention used by other
|
|
5
|
+
* PEAC tools: env:VAR_NAME and file:/path. Keeps the CLI signing UX
|
|
6
|
+
* aligned with the existing PEAC convention without coupling
|
|
7
|
+
* @peac/cli to any other package's loader implementation.
|
|
8
|
+
*
|
|
9
|
+
* Supported schemes:
|
|
10
|
+
* env:VAR_NAME loads JSON from process.env.VAR_NAME (or
|
|
11
|
+
* caller-supplied env)
|
|
12
|
+
* file:/path loads JSON from the file path
|
|
13
|
+
*
|
|
14
|
+
* The value at the resolved location is a JSON-encoded
|
|
15
|
+
* Ed25519PrivateJwk:
|
|
16
|
+
*
|
|
17
|
+
* { "kty": "OKP", "crv": "Ed25519", "x": <b64url>, "d": <b64url>,
|
|
18
|
+
* "kid": "optional" }
|
|
19
|
+
*
|
|
20
|
+
* `kid` is extracted from the JWK if present, otherwise derived from
|
|
21
|
+
* the public key (truncated SHA-256 of the base64url-encoded public
|
|
22
|
+
* key) so runs are reproducible.
|
|
23
|
+
*
|
|
24
|
+
* The loader NEVER logs key bytes; error messages reference field
|
|
25
|
+
* names and structural problems only.
|
|
26
|
+
*/
|
|
27
|
+
export declare class IssuerKeyLoadError extends Error {
|
|
28
|
+
readonly cause?: unknown | undefined;
|
|
29
|
+
readonly code = "cli.issuer_key_load_failed";
|
|
30
|
+
constructor(message: string, cause?: unknown | undefined);
|
|
31
|
+
}
|
|
32
|
+
export declare class IssuerKeyInvalidError extends Error {
|
|
33
|
+
readonly cause?: unknown | undefined;
|
|
34
|
+
readonly code = "cli.issuer_key_invalid";
|
|
35
|
+
constructor(message: string, cause?: unknown | undefined);
|
|
36
|
+
}
|
|
37
|
+
export interface LoadedIssuerKey {
|
|
38
|
+
privateKey: Uint8Array;
|
|
39
|
+
publicKey: Uint8Array;
|
|
40
|
+
kid: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Load the issuer key from a `--issuer-key` reference.
|
|
44
|
+
*
|
|
45
|
+
* @param schemeUri - One of `env:VAR` or `file:/path`.
|
|
46
|
+
* @param env - Environment to consult for `env:` references.
|
|
47
|
+
* Defaults to `process.env`. Tests inject custom env.
|
|
48
|
+
*/
|
|
49
|
+
export declare function loadIssuerKey(schemeUri: string, env?: NodeJS.ProcessEnv): Promise<LoadedIssuerKey>;
|
|
50
|
+
/**
|
|
51
|
+
* Derive a `kid` from a freshly-generated ephemeral public key. Same
|
|
52
|
+
* formula as the loader's fallback so observation records are
|
|
53
|
+
* consistent with the JWK-based path.
|
|
54
|
+
*/
|
|
55
|
+
export declare function deriveKidFromPublicKey(publicKey: Uint8Array): Promise<string>;
|
|
56
|
+
//# sourceMappingURL=issuer-key-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"issuer-key-loader.d.ts","sourceRoot":"","sources":["../../src/lib/issuer-key-loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAYH,qBAAa,kBAAmB,SAAQ,KAAK;IAIzC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO;IAH1B,QAAQ,CAAC,IAAI,gCAAgC;gBAE3C,OAAO,EAAE,MAAM,EACN,KAAK,CAAC,EAAE,OAAO,YAAA;CAK3B;AAED,qBAAa,qBAAsB,SAAQ,KAAK;IAI5C,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO;IAH1B,QAAQ,CAAC,IAAI,4BAA4B;gBAEvC,OAAO,EAAE,MAAM,EACN,KAAK,CAAC,EAAE,OAAO,YAAA;CAK3B;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,UAAU,CAAC;IACvB,SAAS,EAAE,UAAU,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;;;GAMG;AACH,wBAAsB,aAAa,CACjC,SAAS,EAAE,MAAM,EACjB,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAAC,eAAe,CAAC,CAqF1B;AAED;;;;GAIG;AACH,wBAAsB,sBAAsB,CAAC,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAInF"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI observation record builder.
|
|
3
|
+
*
|
|
4
|
+
* Assembles the final `org.peacprotocol/cli-execution` observation
|
|
5
|
+
* record from the raw capture result + the flag-derived capture policy.
|
|
6
|
+
* Applies argv encoding, env filtering (captures only what the policy
|
|
7
|
+
* records; never mutates the child's execution env), cwd / binary-path
|
|
8
|
+
* encoding, and secret-scan suppression on stdout / stderr samples.
|
|
9
|
+
*
|
|
10
|
+
* Builder hard-fail invariants (mirrors of the schema invariants;
|
|
11
|
+
* surface the failure before emission so a flag-layer bug cannot
|
|
12
|
+
* produce a misleading record):
|
|
13
|
+
* - command.program is basename-only; path-bearing tokens are
|
|
14
|
+
* reduced to their basename. Path disclosure is governed by
|
|
15
|
+
* --capture-binary-path and lives only under binary.path_*.
|
|
16
|
+
* - raw argv tokens that exceed argv_max_bytes hard-fail with
|
|
17
|
+
* `cli.argv_token_too_long`; raw mode never silently truncates.
|
|
18
|
+
* - env.mode='raw' with rawEnvEnabled=false hard-fails with
|
|
19
|
+
* `cli.env_mode_inconsistent` rather than silently downgrading
|
|
20
|
+
* to hashed.
|
|
21
|
+
*/
|
|
22
|
+
export declare class CliObservationBuilderError extends Error {
|
|
23
|
+
readonly code: string;
|
|
24
|
+
constructor(code: string, message: string);
|
|
25
|
+
}
|
|
26
|
+
import { type CliExecutionObservation } from '@peac/schema';
|
|
27
|
+
import type { CaptureResult } from './capture.js';
|
|
28
|
+
export type ArgvMode = 'hashed' | 'redacted' | 'raw';
|
|
29
|
+
export type CwdMode = 'none' | 'hashed' | 'basename' | 'absolute';
|
|
30
|
+
export type BinaryPathMode = 'none' | 'hashed' | 'absolute';
|
|
31
|
+
export type EnvMode = 'hashed' | 'raw';
|
|
32
|
+
export type StdinMode = 'none' | 'length-only' | 'hashed';
|
|
33
|
+
export type ExitCodeMode = 'child' | 'record';
|
|
34
|
+
export type ExecutionMode = 'deterministic_script' | 'templated_flow' | 'agent_loop' | 'human_step' | 'hybrid';
|
|
35
|
+
export interface BuilderInput {
|
|
36
|
+
capture: CaptureResult;
|
|
37
|
+
/**
|
|
38
|
+
* The program token AS THE USER SUPPLIED IT (e.g. `node`, `./script.sh`,
|
|
39
|
+
* `/usr/bin/env`). This is what `command.program` records -- it does NOT
|
|
40
|
+
* leak the resolved absolute path. Path disclosure is governed
|
|
41
|
+
* exclusively by `--capture-binary-path` (recorded in `binary.path_*`).
|
|
42
|
+
*/
|
|
43
|
+
programToken: string;
|
|
44
|
+
/**
|
|
45
|
+
* The resolved absolute path the wrapper actually spawned. Used
|
|
46
|
+
* internally for stat metadata and content digest under
|
|
47
|
+
* `--capture-binary-path hashed|absolute` -- NEVER recorded under
|
|
48
|
+
* `command.program`.
|
|
49
|
+
*/
|
|
50
|
+
resolvedProgramPath: string;
|
|
51
|
+
/** Argv tail as supplied (post-`--`); never modified. */
|
|
52
|
+
rawArgv: string[];
|
|
53
|
+
cwd: string;
|
|
54
|
+
argvMode: ArgvMode;
|
|
55
|
+
cwdMode: CwdMode;
|
|
56
|
+
binaryPathMode: BinaryPathMode;
|
|
57
|
+
envMode: EnvMode;
|
|
58
|
+
stdinMode: StdinMode;
|
|
59
|
+
envAllowlist: string[];
|
|
60
|
+
parentEnv: NodeJS.ProcessEnv;
|
|
61
|
+
rawCaptureEnabled: boolean;
|
|
62
|
+
rawEnvEnabled: boolean;
|
|
63
|
+
secretScanEnabled: boolean;
|
|
64
|
+
secretScanDisabledUnsafely: boolean;
|
|
65
|
+
argvCaptureBytes: number;
|
|
66
|
+
stdoutSampleBytes: number;
|
|
67
|
+
stderrSampleBytes: number;
|
|
68
|
+
timeoutMs: number;
|
|
69
|
+
killGraceMs: number;
|
|
70
|
+
exitCodeMode: ExitCodeMode;
|
|
71
|
+
executionMode: ExecutionMode;
|
|
72
|
+
shellMode: boolean;
|
|
73
|
+
policyDigest?: string;
|
|
74
|
+
configDigest?: string;
|
|
75
|
+
approvalRef?: string;
|
|
76
|
+
peacCliVersion: string;
|
|
77
|
+
}
|
|
78
|
+
export declare function buildObservation(input: BuilderInput): Promise<CliExecutionObservation>;
|
|
79
|
+
//# sourceMappingURL=observation-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observation-builder.d.ts","sourceRoot":"","sources":["../../src/lib/observation-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,qBAAa,0BAA2B,SAAQ,KAAK;IACnD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBACV,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAK1C;AAcD,OAAO,EAA8B,KAAK,uBAAuB,EAAE,MAAM,cAAc,CAAC;AACxF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAKlD,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,UAAU,GAAG,KAAK,CAAC;AACrD,MAAM,MAAM,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,UAAU,GAAG,UAAU,CAAC;AAClE,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,QAAQ,GAAG,UAAU,CAAC;AAC5D,MAAM,MAAM,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;AACvC,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,aAAa,GAAG,QAAQ,CAAC;AAC1D,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,QAAQ,CAAC;AAC9C,MAAM,MAAM,aAAa,GACrB,sBAAsB,GACtB,gBAAgB,GAChB,YAAY,GACZ,YAAY,GACZ,QAAQ,CAAC;AAEb,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,aAAa,CAAC;IACvB;;;;;OAKG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,mBAAmB,EAAE,MAAM,CAAC;IAC5B,yDAAyD;IACzD,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,cAAc,CAAC;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,SAAS,CAAC;IACrB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC,UAAU,CAAC;IAC7B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,aAAa,EAAE,OAAO,CAAC;IACvB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,0BAA0B,EAAE,OAAO,CAAC;IACpC,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,YAAY,CAAC;IAC3B,aAAa,EAAE,aAAa,CAAC;IAC7B,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;CACxB;AAoOD,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAuG5F"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared CLI execution observation pipeline.
|
|
3
|
+
*
|
|
4
|
+
* Both `peac observe command` (unsigned JSON emission) and `peac
|
|
5
|
+
* record command` (Wire 0.2 JWS signing) reuse the same capture +
|
|
6
|
+
* build + validate pipeline so a record produced by one is
|
|
7
|
+
* indistinguishable from a record produced by the other (modulo the
|
|
8
|
+
* outer signing envelope). This module is the single source of truth
|
|
9
|
+
* for that shared behavior.
|
|
10
|
+
*
|
|
11
|
+
* Public surface intentionally narrow:
|
|
12
|
+
* - resolveProgramPath(token, childEnv) -- childEnv-aware PATH lookup
|
|
13
|
+
* - preflightOutputWritable(output) -- writability check before spawn
|
|
14
|
+
* - runObservationCore(opts, ...) -- capture + build + validate
|
|
15
|
+
*
|
|
16
|
+
* The pipeline is an OBSERVER, not a sandbox / permission system /
|
|
17
|
+
* shell orchestrator / process supervisor / job scheduler.
|
|
18
|
+
*/
|
|
19
|
+
import { type CliExecutionObservation } from '@peac/schema';
|
|
20
|
+
import { type CaptureResult } from './capture.js';
|
|
21
|
+
import { preflightOutputWritable as neutralPreflightOutputWritable } from './output-preflight.js';
|
|
22
|
+
import { type ArgvMode, type CwdMode, type BinaryPathMode, type EnvMode, type StdinMode, type ExitCodeMode, type ExecutionMode } from './observation-builder.js';
|
|
23
|
+
/** Capture-pipeline options shared by both subcommands. */
|
|
24
|
+
export interface CoreObservationOptions {
|
|
25
|
+
captureMode: ArgvMode;
|
|
26
|
+
unsafeAllowRawCapture: boolean;
|
|
27
|
+
captureStdinMode: StdinMode;
|
|
28
|
+
captureStdoutBytes: number;
|
|
29
|
+
captureStderrBytes: number;
|
|
30
|
+
captureArgvBytes: number;
|
|
31
|
+
envAllow: string[];
|
|
32
|
+
envMode: EnvMode;
|
|
33
|
+
unsafeAllowRawEnv: boolean;
|
|
34
|
+
captureCwdMode: CwdMode;
|
|
35
|
+
captureBinaryPath: BinaryPathMode;
|
|
36
|
+
secretScan: boolean;
|
|
37
|
+
unsafeDisableSecretScan: boolean;
|
|
38
|
+
policyDigest?: string;
|
|
39
|
+
configDigest?: string;
|
|
40
|
+
approvalRef?: string;
|
|
41
|
+
executionMode: ExecutionMode;
|
|
42
|
+
shellMode: boolean;
|
|
43
|
+
timeoutMs: number;
|
|
44
|
+
killGraceMs: number;
|
|
45
|
+
exitCodeMode: ExitCodeMode;
|
|
46
|
+
}
|
|
47
|
+
export interface CoreObservationIO {
|
|
48
|
+
/** Environment passed to the spawned child (what the child RECEIVES). */
|
|
49
|
+
childEnv: NodeJS.ProcessEnv;
|
|
50
|
+
/** Environment inspected by --env-allow for record entries. */
|
|
51
|
+
captureEnv: NodeJS.ProcessEnv;
|
|
52
|
+
cwd: string;
|
|
53
|
+
peacCliVersion: string;
|
|
54
|
+
}
|
|
55
|
+
export type CoreObservationResult = {
|
|
56
|
+
ok: true;
|
|
57
|
+
observation: CliExecutionObservation;
|
|
58
|
+
capture: CaptureResult;
|
|
59
|
+
} | {
|
|
60
|
+
ok: false;
|
|
61
|
+
code: string;
|
|
62
|
+
message: string;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Resolve a program token to its absolute path. Resolution honors the
|
|
66
|
+
* supplied `childEnv` ONLY (the environment that will be passed to
|
|
67
|
+
* spawn). The ambient `process.env` is not consulted: callers must
|
|
68
|
+
* pass `childEnv` explicitly so the execution-environment source is
|
|
69
|
+
* auditable at the call site. When no executable is found in
|
|
70
|
+
* `childEnv.PATH`, returns the token unchanged so spawn surfaces a
|
|
71
|
+
* clear ENOENT error.
|
|
72
|
+
*/
|
|
73
|
+
export declare function resolveProgramPath(token: string, childEnv: NodeJS.ProcessEnv): string;
|
|
74
|
+
/**
|
|
75
|
+
* Re-export of the neutral output-path preflight from
|
|
76
|
+
* `lib/output-preflight.ts`. Kept here so PR 2 callers
|
|
77
|
+
* (`observe command`, `record command`) and any future callers that
|
|
78
|
+
* already import this name from this module continue to work.
|
|
79
|
+
*/
|
|
80
|
+
export declare const preflightOutputWritable: typeof neutralPreflightOutputWritable;
|
|
81
|
+
/**
|
|
82
|
+
* Run the shared capture + build + validate pipeline.
|
|
83
|
+
*
|
|
84
|
+
* Returns `{ ok: true, observation, capture }` when all stages succeed
|
|
85
|
+
* (observation is the schema-validated record; capture carries the
|
|
86
|
+
* child's exit info for downstream exit-code-mode handling).
|
|
87
|
+
* Returns `{ ok: false, code, message }` for any structured failure.
|
|
88
|
+
*
|
|
89
|
+
* Stages:
|
|
90
|
+
* 1. resolveProgramPath(programToken, childEnv)
|
|
91
|
+
* 2. captureCommand(...) (raises CliSpawnFailedError)
|
|
92
|
+
* 3. buildObservation(...) (raises CliObservationBuilderError)
|
|
93
|
+
* 4. CliExecutionSchema.safeParse(observation)
|
|
94
|
+
*/
|
|
95
|
+
export declare function runObservationCore(opts: CoreObservationOptions, programToken: string, args: string[], io: CoreObservationIO): Promise<CoreObservationResult>;
|
|
96
|
+
//# sourceMappingURL=observation-pipeline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observation-pipeline.d.ts","sourceRoot":"","sources":["../../src/lib/observation-pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,OAAO,EAAsB,KAAK,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAChF,OAAO,EAAuC,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AACvF,OAAO,EAAE,uBAAuB,IAAI,8BAA8B,EAAE,MAAM,uBAAuB,CAAC;AAClG,OAAO,EAGL,KAAK,QAAQ,EACb,KAAK,OAAO,EACZ,KAAK,cAAc,EACnB,KAAK,OAAO,EACZ,KAAK,SAAS,EACd,KAAK,YAAY,EACjB,KAAK,aAAa,EACnB,MAAM,0BAA0B,CAAC;AAElC,2DAA2D;AAC3D,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,QAAQ,CAAC;IACtB,qBAAqB,EAAE,OAAO,CAAC;IAC/B,gBAAgB,EAAE,SAAS,CAAC;IAC5B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,cAAc,EAAE,OAAO,CAAC;IACxB,iBAAiB,EAAE,cAAc,CAAC;IAClC,UAAU,EAAE,OAAO,CAAC;IACpB,uBAAuB,EAAE,OAAO,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,aAAa,CAAC;IAC7B,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,YAAY,CAAC;CAC5B;AAED,MAAM,WAAW,iBAAiB;IAChC,yEAAyE;IACzE,QAAQ,EAAE,MAAM,CAAC,UAAU,CAAC;IAC5B,+DAA+D;IAC/D,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,MAAM,qBAAqB,GAC7B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,WAAW,EAAE,uBAAuB,CAAC;IAAC,OAAO,EAAE,aAAa,CAAA;CAAE,GAC1E;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjD;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAuBrF;AAED;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,uCAAiC,CAAC;AAEtE;;;;;;;;;;;;;GAaG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,sBAAsB,EAC5B,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,MAAM,EAAE,EACd,EAAE,EAAE,iBAAiB,GACpB,OAAO,CAAC,qBAAqB,CAAC,CAkFhC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Race-free output-path writability preflight (neutral, surface-agnostic).
|
|
3
|
+
*
|
|
4
|
+
* Used by every CLI surface that supports `--output <file>` to verify the
|
|
5
|
+
* target path is writable BEFORE doing any side-effecting work (spawning a
|
|
6
|
+
* child process, loading an issuer key, signing, etc.). A record-producing
|
|
7
|
+
* wrapper must never do that work only to discover the record cannot be
|
|
8
|
+
* persisted.
|
|
9
|
+
*
|
|
10
|
+
* The preflight is deliberately non-invasive on the final target path:
|
|
11
|
+
* - if the final target exists, open it for append/write check and
|
|
12
|
+
* close it; never unlink the existing target
|
|
13
|
+
* - if the final target does NOT exist, create a uniquely-named
|
|
14
|
+
* sibling temp file in the parent directory with O_EXCL and
|
|
15
|
+
* immediately unlink that temp file; the final target path is
|
|
16
|
+
* not created or touched until the actual write step
|
|
17
|
+
*
|
|
18
|
+
* Result: between preflight and the eventual write, the CLI has NOT
|
|
19
|
+
* created or modified the final output path. Concurrent observers cannot
|
|
20
|
+
* race against a transient zero-byte target file produced by the preflight.
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* Verify that `--output <file>` will be writable. Returns null on
|
|
24
|
+
* success; otherwise an error message suitable for pairing with
|
|
25
|
+
* `cli.output_write_failed`.
|
|
26
|
+
*/
|
|
27
|
+
export declare function preflightOutputWritable(output: string): string | null;
|
|
28
|
+
//# sourceMappingURL=output-preflight.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output-preflight.d.ts","sourceRoot":"","sources":["../../src/lib/output-preflight.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAMH;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiErE"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secret-scan regex set for bounded-capture samples.
|
|
3
|
+
*
|
|
4
|
+
* Secret-scan is ON by default. When raw sample emission is possible
|
|
5
|
+
* (`--capture-mode raw && --unsafe-allow-raw-capture`), the wrapper
|
|
6
|
+
* runs this regex set against each candidate sample BEFORE emission.
|
|
7
|
+
* If a token-like pattern matches, the sample is suppressed and
|
|
8
|
+
* replaced with `{ sample_suppressed_reason: "secret_pattern_detected",
|
|
9
|
+
* matched_pattern_category: <category> }`. The literal match is NEVER
|
|
10
|
+
* recorded.
|
|
11
|
+
*
|
|
12
|
+
* The regex set is intentionally small (5 named patterns). False
|
|
13
|
+
* positives are tolerated; the suppression itself is observable so a
|
|
14
|
+
* verifier can detect over-suppression.
|
|
15
|
+
*
|
|
16
|
+
* Disabling secret-scan under raw capture requires the third unsafe
|
|
17
|
+
* flag (`--unsafe-disable-secret-scan`); enforcement lives in the
|
|
18
|
+
* subcommand flag-parse layer, not here.
|
|
19
|
+
*/
|
|
20
|
+
export type SecretCategory = 'bearer-token' | 'api-key' | 'jwt' | 'aws-access-key' | 'generic-high-entropy';
|
|
21
|
+
export interface SecretMatch {
|
|
22
|
+
category: SecretCategory;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Scan a buffer or string for token-like patterns. Returns the first
|
|
26
|
+
* match (by pattern declaration order); the literal match is NEVER
|
|
27
|
+
* returned to callers.
|
|
28
|
+
*/
|
|
29
|
+
export declare function scanForSecrets(input: string | Uint8Array): SecretMatch | null;
|
|
30
|
+
/**
|
|
31
|
+
* Scan an argv element. Same shape as `scanForSecrets` but documents
|
|
32
|
+
* intent: argv elements are scanned independently of stream samples.
|
|
33
|
+
*/
|
|
34
|
+
export declare function scanArgvElement(token: string): SecretMatch | null;
|
|
35
|
+
//# sourceMappingURL=secret-scan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secret-scan.d.ts","sourceRoot":"","sources":["../../src/lib/secret-scan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,MAAM,MAAM,cAAc,GACtB,cAAc,GACd,SAAS,GACT,KAAK,GACL,gBAAgB,GAChB,sBAAsB,CAAC;AA0C3B,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,cAAc,CAAC;CAC1B;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,WAAW,GAAG,IAAI,CAQ7E;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAEjE"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@peac/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.1",
|
|
4
4
|
"description": "PEAC protocol command-line tools",
|
|
5
5
|
"main": "dist/index.cjs",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -38,13 +38,13 @@
|
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"chalk": "^4.1.2",
|
|
40
40
|
"commander": "^11.0.0",
|
|
41
|
-
"@peac/
|
|
42
|
-
"@peac/
|
|
43
|
-
"@peac/net-node": "0.
|
|
44
|
-
"@peac/crypto": "0.
|
|
45
|
-
"@peac/policy-kit": "0.
|
|
46
|
-
"@peac/
|
|
47
|
-
"@peac/
|
|
41
|
+
"@peac/audit": "0.14.1",
|
|
42
|
+
"@peac/kernel": "0.14.1",
|
|
43
|
+
"@peac/net-node": "0.14.1",
|
|
44
|
+
"@peac/crypto": "0.14.1",
|
|
45
|
+
"@peac/policy-kit": "0.14.1",
|
|
46
|
+
"@peac/protocol": "0.14.1",
|
|
47
|
+
"@peac/schema": "0.14.1"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@types/node": "^22.19.11",
|