fullcourtdefense-cli 1.27.0 → 1.27.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/hook.d.ts +8 -0
- package/dist/commands/hook.js +18 -3
- package/dist/version.json +1 -1
- package/package.json +1 -1
package/dist/commands/hook.d.ts
CHANGED
|
@@ -114,6 +114,14 @@ export interface HookIo {
|
|
|
114
114
|
write(text: string): void;
|
|
115
115
|
writeErr(text: string): void;
|
|
116
116
|
exit(code: number): never;
|
|
117
|
+
/**
|
|
118
|
+
* True when `exit` really ends the process (standalone hook: CI runners,
|
|
119
|
+
* containers, a workstation whose daemon is down). Fire-and-forget network
|
|
120
|
+
* work started before `respond()` dies with the process, so audit reports
|
|
121
|
+
* must go through the spool + detached flusher instead. False in daemon
|
|
122
|
+
* mode, where `exit` only unwinds the evaluation and the process lives on.
|
|
123
|
+
*/
|
|
124
|
+
exitsProcess: boolean;
|
|
117
125
|
}
|
|
118
126
|
/**
|
|
119
127
|
* Daemon-side entry: evaluate one hook request in-process and return the
|
package/dist/commands/hook.js
CHANGED
|
@@ -785,6 +785,7 @@ function processIo(stdin, stdinErr) {
|
|
|
785
785
|
write: (text) => { process.stdout.write(text); },
|
|
786
786
|
writeErr: (text) => { process.stderr.write(text); },
|
|
787
787
|
exit: (code) => process.exit(code),
|
|
788
|
+
exitsProcess: true,
|
|
788
789
|
};
|
|
789
790
|
}
|
|
790
791
|
/**
|
|
@@ -804,6 +805,7 @@ async function evaluateHookRequest(args, stdinRaw, config) {
|
|
|
804
805
|
write: (text) => { out += text; },
|
|
805
806
|
writeErr: (text) => { errOut += text; },
|
|
806
807
|
exit: (code) => { throw new HookExitSignal(code); },
|
|
808
|
+
exitsProcess: false,
|
|
807
809
|
};
|
|
808
810
|
try {
|
|
809
811
|
await hookCommandInner(args, config, io);
|
|
@@ -1195,7 +1197,7 @@ async function hookCommandInner(args, config, io) {
|
|
|
1195
1197
|
await enforceActionPolicy({
|
|
1196
1198
|
event, payload, apiUrl: apiUrl, shieldId: shieldId, shieldKey,
|
|
1197
1199
|
shadow, failClosed, timeoutMs, approvalMode, approvalTimeoutMs, approvalPollMs, respond, deferLocalWarnings,
|
|
1198
|
-
effectivePolicyHash, localPolicies, client,
|
|
1200
|
+
effectivePolicyHash, localPolicies, client, exitsProcess: io.exitsProcess,
|
|
1199
1201
|
});
|
|
1200
1202
|
return;
|
|
1201
1203
|
}
|
|
@@ -1450,8 +1452,21 @@ async function enforceActionPolicy(ctx) {
|
|
|
1450
1452
|
const localVerdict = (0, actionPolicyEngine_1.evaluateActionPolicies)(ctx.localPolicies, call.toolName, localOp, localCtx, (0, actionPolicyEngine_1.deriveToolOperations)(call.toolName));
|
|
1451
1453
|
(0, hookIo_1.dbg)({ phase: 'policy_local_first', event, tool: call.toolName, operation: localOp, verdict: localVerdict.verdict, policyName: localVerdict.policyName });
|
|
1452
1454
|
if (localVerdict.verdict === 'allow') {
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
+
if (ctx.exitsProcess) {
|
|
1456
|
+
// Standalone hook (CI runner, container, daemon down): respond() ends
|
|
1457
|
+
// the process, so a fire-and-forget gate report would die in flight and
|
|
1458
|
+
// the allowed action would never reach the fleet — the machine would
|
|
1459
|
+
// read "N blocked of N recent" with every allow missing. Same delivery
|
|
1460
|
+
// as a block: spool (sync file append) + detached flusher that outlives
|
|
1461
|
+
// this process. The IDE is not kept waiting on the network.
|
|
1462
|
+
spoolCallEvent(call, { decision: 'allow', reason: 'local policy allow (block mode, local-first)' });
|
|
1463
|
+
(0, telemetry_1.triggerFlush)(true);
|
|
1464
|
+
respond(false);
|
|
1465
|
+
return;
|
|
1466
|
+
}
|
|
1467
|
+
// Daemon-evaluated: the process lives on, so the audit rides async — the
|
|
1468
|
+
// server records the action + its own verdict; if it is unreachable the
|
|
1469
|
+
// spool keeps the trail (idempotent on eventId).
|
|
1455
1470
|
void fetch(gateUrl, { method: 'POST', headers, body: gateBody, signal: AbortSignal.timeout(4000) })
|
|
1456
1471
|
.then(() => (0, policyGateHealth_1.recordGateSuccess)())
|
|
1457
1472
|
.catch(() => {
|
package/dist/version.json
CHANGED