@secure-ai/guard 0.1.0 → 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.
- package/dist/index.d.ts +17 -0
- package/dist/index.js +27 -4
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -246,6 +246,23 @@ export declare class SecureAI {
|
|
|
246
246
|
* check would make protection opt-in at every site, which is the thing this
|
|
247
247
|
* exists to stop.
|
|
248
248
|
*/
|
|
249
|
+
/**
|
|
250
|
+
* What to hand the wrapped function.
|
|
251
|
+
*
|
|
252
|
+
* The API omits `input` only on a block, so on any other decision it is
|
|
253
|
+
* there. The question is what to do if it is not, and the answer is not
|
|
254
|
+
* "send what the caller had".
|
|
255
|
+
*
|
|
256
|
+
* On a redact, the caller's input is the one thing that must not go: it
|
|
257
|
+
* still contains the values the decision just said to replace. Falling
|
|
258
|
+
* back to it turns a missing field into the product doing the exact
|
|
259
|
+
* opposite of its purpose, silently, with the audit trail recording a
|
|
260
|
+
* redaction that did not happen. So a redact with nothing to send throws.
|
|
261
|
+
*
|
|
262
|
+
* On an allow, nothing was rewritten and the caller's own input is the
|
|
263
|
+
* correct thing to pass, so the fallback is right there and stays.
|
|
264
|
+
*/
|
|
265
|
+
private sendable;
|
|
249
266
|
guard<A, R>(tool: string, fn: (input: A) => Promise<R> | R, opts?: {
|
|
250
267
|
direction?: Direction;
|
|
251
268
|
agent?: string;
|
package/dist/index.js
CHANGED
|
@@ -231,6 +231,31 @@ export class SecureAI {
|
|
|
231
231
|
* check would make protection opt-in at every site, which is the thing this
|
|
232
232
|
* exists to stop.
|
|
233
233
|
*/
|
|
234
|
+
/**
|
|
235
|
+
* What to hand the wrapped function.
|
|
236
|
+
*
|
|
237
|
+
* The API omits `input` only on a block, so on any other decision it is
|
|
238
|
+
* there. The question is what to do if it is not, and the answer is not
|
|
239
|
+
* "send what the caller had".
|
|
240
|
+
*
|
|
241
|
+
* On a redact, the caller's input is the one thing that must not go: it
|
|
242
|
+
* still contains the values the decision just said to replace. Falling
|
|
243
|
+
* back to it turns a missing field into the product doing the exact
|
|
244
|
+
* opposite of its purpose, silently, with the audit trail recording a
|
|
245
|
+
* redaction that did not happen. So a redact with nothing to send throws.
|
|
246
|
+
*
|
|
247
|
+
* On an allow, nothing was rewritten and the caller's own input is the
|
|
248
|
+
* correct thing to pass, so the fallback is right there and stays.
|
|
249
|
+
*/
|
|
250
|
+
sendable(tool, verdict, original) {
|
|
251
|
+
if (verdict.input !== undefined)
|
|
252
|
+
return verdict.input;
|
|
253
|
+
if (verdict.decision === "redact") {
|
|
254
|
+
throw new SecureAIError(`Secure AI decided to redact ${tool} but returned nothing to send. ` +
|
|
255
|
+
`The original was not sent: it still holds the values that decision was about.`, 502, "missing_rewritten_input");
|
|
256
|
+
}
|
|
257
|
+
return original;
|
|
258
|
+
}
|
|
234
259
|
guard(tool, fn, opts) {
|
|
235
260
|
return async (input) => {
|
|
236
261
|
let verdict;
|
|
@@ -280,11 +305,9 @@ export class SecureAI {
|
|
|
280
305
|
});
|
|
281
306
|
if (after.decision === "block")
|
|
282
307
|
throw new ActionBlocked(tool, after);
|
|
283
|
-
return await fn((after
|
|
308
|
+
return await fn(this.sendable(tool, after, input));
|
|
284
309
|
}
|
|
285
|
-
|
|
286
|
-
// belt and braces against a future field being dropped.
|
|
287
|
-
return await fn((verdict.input ?? input));
|
|
310
|
+
return await fn(this.sendable(tool, verdict, input));
|
|
288
311
|
};
|
|
289
312
|
}
|
|
290
313
|
/**
|