@jterrats/open-orchestra 1.0.17 → 1.0.18
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/CHANGELOG.md +44 -0
- package/CLAUDE.md +1 -0
- package/dist/active-runtime-store.d.ts +18 -0
- package/dist/active-runtime-store.js +75 -0
- package/dist/active-runtime-store.js.map +1 -0
- package/dist/chat-api-errors.d.ts +7 -0
- package/dist/chat-api-errors.js +15 -0
- package/dist/chat-api-errors.js.map +1 -0
- package/dist/chat-api-message-persistence.d.ts +12 -0
- package/dist/chat-api-message-persistence.js +125 -0
- package/dist/chat-api-message-persistence.js.map +1 -0
- package/dist/chat-api-records.d.ts +35 -0
- package/dist/chat-api-records.js +94 -0
- package/dist/chat-api-records.js.map +1 -0
- package/dist/chat-api-service.d.ts +32 -0
- package/dist/chat-api-service.js +120 -0
- package/dist/chat-api-service.js.map +1 -0
- package/dist/chat-api-storage.d.ts +1 -0
- package/dist/chat-api-storage.js +14 -0
- package/dist/chat-api-storage.js.map +1 -0
- package/dist/chat-api-types.d.ts +81 -0
- package/dist/chat-api-types.js +2 -0
- package/dist/chat-api-types.js.map +1 -0
- package/dist/chat-compliance-service.d.ts +60 -0
- package/dist/chat-compliance-service.js +241 -0
- package/dist/chat-compliance-service.js.map +1 -0
- package/dist/chat-event-stream.d.ts +13 -0
- package/dist/chat-event-stream.js +124 -0
- package/dist/chat-event-stream.js.map +1 -0
- package/dist/chat-pagination.d.ts +6 -0
- package/dist/chat-pagination.js +64 -0
- package/dist/chat-pagination.js.map +1 -0
- package/dist/chat-storage-actor-validation.d.ts +4 -0
- package/dist/chat-storage-actor-validation.js +65 -0
- package/dist/chat-storage-actor-validation.js.map +1 -0
- package/dist/chat-storage-content-policy.d.ts +6 -0
- package/dist/chat-storage-content-policy.js +84 -0
- package/dist/chat-storage-content-policy.js.map +1 -0
- package/dist/chat-storage-errors.d.ts +20 -0
- package/dist/chat-storage-errors.js +17 -0
- package/dist/chat-storage-errors.js.map +1 -0
- package/dist/chat-storage-local-files.d.ts +17 -0
- package/dist/chat-storage-local-files.js +78 -0
- package/dist/chat-storage-local-files.js.map +1 -0
- package/dist/chat-storage-local-paths.d.ts +6 -0
- package/dist/chat-storage-local-paths.js +124 -0
- package/dist/chat-storage-local-paths.js.map +1 -0
- package/dist/chat-storage-local-projection.d.ts +10 -0
- package/dist/chat-storage-local-projection.js +55 -0
- package/dist/chat-storage-local-projection.js.map +1 -0
- package/dist/chat-storage-local-records.d.ts +13 -0
- package/dist/chat-storage-local-records.js +56 -0
- package/dist/chat-storage-local-records.js.map +1 -0
- package/dist/chat-storage-local.d.ts +6 -0
- package/dist/chat-storage-local.js +114 -0
- package/dist/chat-storage-local.js.map +1 -0
- package/dist/chat-storage-validation.d.ts +10 -0
- package/dist/chat-storage-validation.js +100 -0
- package/dist/chat-storage-validation.js.map +1 -0
- package/dist/chat-storage.d.ts +16 -0
- package/dist/chat-storage.js +4 -0
- package/dist/chat-storage.js.map +1 -0
- package/dist/chat-workflow-timeline.d.ts +17 -0
- package/dist/chat-workflow-timeline.js +210 -0
- package/dist/chat-workflow-timeline.js.map +1 -0
- package/dist/{workspace-claude-settings.d.ts → claude-settings.d.ts} +22 -3
- package/dist/{workspace-claude-settings.js → claude-settings.js} +28 -9
- package/dist/claude-settings.js.map +1 -0
- package/dist/command-init.d.ts +2 -0
- package/dist/command-init.js +150 -0
- package/dist/command-init.js.map +1 -0
- package/dist/command-manifest.js +1 -1
- package/dist/command-manifest.js.map +1 -1
- package/dist/commands.d.ts +1 -1
- package/dist/commands.js +1 -140
- package/dist/commands.js.map +1 -1
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +1 -0
- package/dist/constants.js.map +1 -1
- package/dist/context-runtime-preprocessor.d.ts +41 -0
- package/dist/context-runtime-preprocessor.js +199 -0
- package/dist/context-runtime-preprocessor.js.map +1 -0
- package/dist/cursor-settings.d.ts +25 -0
- package/dist/cursor-settings.js +72 -0
- package/dist/cursor-settings.js.map +1 -0
- package/dist/health-commands.js +43 -3
- package/dist/health-commands.js.map +1 -1
- package/dist/model-aliases.d.ts +5 -0
- package/dist/model-aliases.js +37 -0
- package/dist/model-aliases.js.map +1 -0
- package/dist/ollama-provider.js +25 -0
- package/dist/ollama-provider.js.map +1 -1
- package/dist/phase-playbooks.js +11 -0
- package/dist/phase-playbooks.js.map +1 -1
- package/dist/provider-agent-wrapper.js +14 -0
- package/dist/provider-agent-wrapper.js.map +1 -1
- package/dist/runtime-adapters.js +56 -0
- package/dist/runtime-adapters.js.map +1 -1
- package/dist/runtime-bootstrap.js +20 -22
- package/dist/runtime-bootstrap.js.map +1 -1
- package/dist/runtime-child-prompt.js +8 -0
- package/dist/runtime-child-prompt.js.map +1 -1
- package/dist/runtime-context-manifest.d.ts +4 -1
- package/dist/runtime-context-manifest.js +59 -3
- package/dist/runtime-context-manifest.js.map +1 -1
- package/dist/runtime-execution-adapters.js +19 -0
- package/dist/runtime-execution-adapters.js.map +1 -1
- package/dist/runtime-execution-renderer.js +4 -0
- package/dist/runtime-execution-renderer.js.map +1 -1
- package/dist/runtime-execution.js +13 -82
- package/dist/runtime-execution.js.map +1 -1
- package/dist/runtime-hooks.d.ts +46 -0
- package/dist/runtime-hooks.js +95 -0
- package/dist/runtime-hooks.js.map +1 -0
- package/dist/runtime-parent-actions.js +5 -0
- package/dist/runtime-parent-actions.js.map +1 -1
- package/dist/runtime-spawn-bridge.js +1 -0
- package/dist/runtime-spawn-bridge.js.map +1 -1
- package/dist/runtime-spawn-guidance.js +15 -61
- package/dist/runtime-spawn-guidance.js.map +1 -1
- package/dist/security/chat-guardrail-policy.d.ts +7 -0
- package/dist/security/chat-guardrail-policy.js +61 -0
- package/dist/security/chat-guardrail-policy.js.map +1 -0
- package/dist/security/chat-guardrail-types.d.ts +65 -0
- package/dist/security/chat-guardrail-types.js +2 -0
- package/dist/security/chat-guardrail-types.js.map +1 -0
- package/dist/security/chat-guardrail-validation.d.ts +9 -0
- package/dist/security/chat-guardrail-validation.js +64 -0
- package/dist/security/chat-guardrail-validation.js.map +1 -0
- package/dist/security/chat-guardrails.d.ts +3 -0
- package/dist/security/chat-guardrails.js +136 -0
- package/dist/security/chat-guardrails.js.map +1 -0
- package/dist/security/content-classifier.js +33 -1
- package/dist/security/content-classifier.js.map +1 -1
- package/dist/security/payment-card-detection.d.ts +3 -0
- package/dist/security/payment-card-detection.js +48 -0
- package/dist/security/payment-card-detection.js.map +1 -0
- package/dist/security/policy-types.d.ts +1 -1
- package/dist/security/provider-egress-policy.d.ts +27 -0
- package/dist/security/provider-egress-policy.js +72 -0
- package/dist/security/provider-egress-policy.js.map +1 -0
- package/dist/security/public-api-auth.d.ts +20 -0
- package/dist/security/public-api-auth.js +55 -0
- package/dist/security/public-api-auth.js.map +1 -0
- package/dist/security/public-api-policy.d.ts +8 -0
- package/dist/security/public-api-policy.js +40 -0
- package/dist/security/public-api-policy.js.map +1 -0
- package/dist/security/redaction.js +44 -13
- package/dist/security/redaction.js.map +1 -1
- package/dist/security/restricted-content-quarantine.d.ts +17 -0
- package/dist/security/restricted-content-quarantine.js +50 -0
- package/dist/security/restricted-content-quarantine.js.map +1 -0
- package/dist/security/restricted-data-classifier.d.ts +9 -0
- package/dist/security/restricted-data-classifier.js +254 -0
- package/dist/security/restricted-data-classifier.js.map +1 -0
- package/dist/skills-render.js +7 -14
- package/dist/skills-render.js.map +1 -1
- package/dist/telemetry-redaction.d.ts +2 -0
- package/dist/telemetry-redaction.js +25 -2
- package/dist/telemetry-redaction.js.map +1 -1
- package/dist/types/chat.d.ts +203 -0
- package/dist/types/chat.js +10 -0
- package/dist/types/chat.js.map +1 -0
- package/dist/types/model-config.d.ts +4 -0
- package/dist/types/public-api.d.ts +75 -0
- package/dist/types/public-api.js +2 -0
- package/dist/types/public-api.js.map +1 -0
- package/dist/types/restricted-data.d.ts +69 -0
- package/dist/types/restricted-data.js +8 -0
- package/dist/types/restricted-data.js.map +1 -0
- package/dist/types/restricted-fragment.d.ts +82 -0
- package/dist/types/restricted-fragment.js +14 -0
- package/dist/types/restricted-fragment.js.map +1 -0
- package/dist/types/runtime.d.ts +12 -0
- package/dist/types.d.ts +6 -0
- package/dist/types.js.map +1 -1
- package/dist/web-api.js +24 -0
- package/dist/web-api.js.map +1 -1
- package/dist/web-artifact-parsers.d.ts +6 -0
- package/dist/web-artifact-parsers.js +244 -0
- package/dist/web-artifact-parsers.js.map +1 -0
- package/dist/web-artifact-types.d.ts +76 -0
- package/dist/web-artifact-types.js +2 -0
- package/dist/web-artifact-types.js.map +1 -0
- package/dist/web-artifacts.d.ts +2 -43
- package/dist/web-artifacts.js +73 -58
- package/dist/web-artifacts.js.map +1 -1
- package/dist/web-chat-route-inputs.d.ts +11 -0
- package/dist/web-chat-route-inputs.js +156 -0
- package/dist/web-chat-route-inputs.js.map +1 -0
- package/dist/web-chat-routes.d.ts +7 -0
- package/dist/web-chat-routes.js +213 -0
- package/dist/web-chat-routes.js.map +1 -0
- package/dist/web-console/assets/index-CJup1cIA.css +1 -0
- package/dist/web-console/assets/index-CVDOfipu.js +11 -0
- package/dist/web-console/index.html +2 -2
- package/dist/web-evidence.d.ts +1 -1
- package/dist/web-evidence.js +9 -2
- package/dist/web-evidence.js.map +1 -1
- package/dist/web-public-route-inputs.d.ts +14 -0
- package/dist/web-public-route-inputs.js +136 -0
- package/dist/web-public-route-inputs.js.map +1 -0
- package/dist/web-public-routes.d.ts +6 -0
- package/dist/web-public-routes.js +194 -0
- package/dist/web-public-routes.js.map +1 -0
- package/dist/web-public-service.d.ts +16 -0
- package/dist/web-public-service.js +154 -0
- package/dist/web-public-service.js.map +1 -0
- package/dist/workflow-services.js +5 -0
- package/dist/workflow-services.js.map +1 -1
- package/dist/workspace-runtime-bootstrap.js +15 -4
- package/dist/workspace-runtime-bootstrap.js.map +1 -1
- package/docs/chat-audit-retention.md +76 -0
- package/docs/chat-provider-provenance-ledger.md +75 -0
- package/docs/context-runtime-preprocessing.md +37 -0
- package/docs/orchestra-mvp.md +8 -2
- package/docs/public-api-contract.md +43 -0
- package/docs/release-test-matrix.md +14 -14
- package/docs/restricted-fragment-storage-contract.md +147 -0
- package/docs/runtime-adapters.md +40 -7
- package/docs/site-manifest.json +128 -30
- package/package.json +5 -2
- package/site/dist/_headers +9 -0
- package/site/dist/_redirects +2 -0
- package/site/dist/architecture.mmd +61 -0
- package/site/dist/assets/index-Bi8l6tCE.js +10 -0
- package/site/dist/assets/index-BsCLqY__.css +1 -0
- package/site/dist/favicon.svg +19 -0
- package/site/dist/index.html +28 -0
- package/site/package.json +19 -0
- package/dist/web-console/assets/index-BHs7OIv8.css +0 -1
- package/dist/web-console/assets/index-BJuVTqfQ.js +0 -11
- package/dist/workspace-claude-settings.js.map +0 -1
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export function chatOutcomeForPolicy(outcome) {
|
|
2
|
+
if (outcome === "allow")
|
|
3
|
+
return "allow";
|
|
4
|
+
if (outcome === "deny")
|
|
5
|
+
return "block";
|
|
6
|
+
return "defer";
|
|
7
|
+
}
|
|
8
|
+
export function policySubjectFor(request) {
|
|
9
|
+
return {
|
|
10
|
+
id: request.actor.id,
|
|
11
|
+
subjectType: request.actor.actorType,
|
|
12
|
+
tenantId: request.tenantId,
|
|
13
|
+
workspaceId: request.workspaceId,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export function policyResourceFor(resource) {
|
|
17
|
+
return {
|
|
18
|
+
resourceType: policyResourceTypeFor(resource.resourceType),
|
|
19
|
+
summary: resource.summary,
|
|
20
|
+
tenantId: resource.tenantId,
|
|
21
|
+
workspaceId: resource.workspaceId,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export function policyActionFor(action, resource) {
|
|
25
|
+
if (action === "providerMessage")
|
|
26
|
+
return "provider.message";
|
|
27
|
+
if (action === "evidenceWrite")
|
|
28
|
+
return "evidence.write";
|
|
29
|
+
if (action === "toolRequest") {
|
|
30
|
+
if (resource.resourceType === "url")
|
|
31
|
+
return "url.fetch";
|
|
32
|
+
if (resource.resourceType === "file")
|
|
33
|
+
return "file.write";
|
|
34
|
+
return "command.execute";
|
|
35
|
+
}
|
|
36
|
+
return "content.ingest";
|
|
37
|
+
}
|
|
38
|
+
export function highestClassification(segments) {
|
|
39
|
+
if (segments.some((segment) => segment.classification.classification === "restricted")) {
|
|
40
|
+
return "restricted";
|
|
41
|
+
}
|
|
42
|
+
if (segments.some((segment) => segment.classification.classification === "unknown")) {
|
|
43
|
+
return "unknown";
|
|
44
|
+
}
|
|
45
|
+
if (segments.some((segment) => segment.classification.classification === "internal")) {
|
|
46
|
+
return "internal";
|
|
47
|
+
}
|
|
48
|
+
return "public";
|
|
49
|
+
}
|
|
50
|
+
function policyResourceTypeFor(resourceType) {
|
|
51
|
+
if (resourceType === "command")
|
|
52
|
+
return "command";
|
|
53
|
+
if (resourceType === "evidence")
|
|
54
|
+
return "evidence";
|
|
55
|
+
if (resourceType === "file")
|
|
56
|
+
return "file";
|
|
57
|
+
if (resourceType === "url")
|
|
58
|
+
return "url";
|
|
59
|
+
return "prompt";
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=chat-guardrail-policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-guardrail-policy.js","sourceRoot":"","sources":["../../src/security/chat-guardrail-policy.ts"],"names":[],"mappings":"AAeA,MAAM,UAAU,oBAAoB,CAClC,OAA8B;IAE9B,IAAI,OAAO,KAAK,OAAO;QAAE,OAAO,OAAO,CAAC;IACxC,IAAI,OAAO,KAAK,MAAM;QAAE,OAAO,OAAO,CAAC;IACvC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,OAA6B;IAC5D,OAAO;QACL,EAAE,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE;QACpB,WAAW,EAAE,OAAO,CAAC,KAAK,CAAC,SAAS;QACpC,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,WAAW,EAAE,OAAO,CAAC,WAAW;KACjC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,QAA0C;IAE1C,OAAO;QACL,YAAY,EAAE,qBAAqB,CAAC,QAAQ,CAAC,YAAY,CAAC;QAC1D,OAAO,EAAE,QAAQ,CAAC,OAAO;QACzB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;QAC3B,WAAW,EAAE,QAAQ,CAAC,WAAW;KAClC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,MAA2B,EAC3B,QAA0C;IAE1C,IAAI,MAAM,KAAK,iBAAiB;QAAE,OAAO,kBAAkB,CAAC;IAC5D,IAAI,MAAM,KAAK,eAAe;QAAE,OAAO,gBAAgB,CAAC;IACxD,IAAI,MAAM,KAAK,aAAa,EAAE,CAAC;QAC7B,IAAI,QAAQ,CAAC,YAAY,KAAK,KAAK;YAAE,OAAO,WAAW,CAAC;QACxD,IAAI,QAAQ,CAAC,YAAY,KAAK,MAAM;YAAE,OAAO,YAAY,CAAC;QAC1D,OAAO,iBAAiB,CAAC;IAC3B,CAAC;IACD,OAAO,gBAAgB,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,QAAyB;IAEzB,IACE,QAAQ,CAAC,IAAI,CACX,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,cAAc,CAAC,cAAc,KAAK,YAAY,CACpE,EACD,CAAC;QACD,OAAO,YAAY,CAAC;IACtB,CAAC;IACD,IACE,QAAQ,CAAC,IAAI,CACX,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,cAAc,CAAC,cAAc,KAAK,SAAS,CACjE,EACD,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IACE,QAAQ,CAAC,IAAI,CACX,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,cAAc,CAAC,cAAc,KAAK,UAAU,CAClE,EACD,CAAC;QACD,OAAO,UAAU,CAAC;IACpB,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,qBAAqB,CAC5B,YAAuC;IAEvC,IAAI,YAAY,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACjD,IAAI,YAAY,KAAK,UAAU;QAAE,OAAO,UAAU,CAAC;IACnD,IAAI,YAAY,KAAK,MAAM;QAAE,OAAO,MAAM,CAAC;IAC3C,IAAI,YAAY,KAAK,KAAK;QAAE,OAAO,KAAK,CAAC;IACzC,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { PolicyDecisionOutcome, PolicySink, PromptSegment, RedactedSegment, RedactionReport, RedactionStatus } from "./policy-types.js";
|
|
2
|
+
import type { PromptSegmentInput } from "./prompt-intake.js";
|
|
3
|
+
export declare const chatGuardrailOutcomes: readonly ["allow", "block", "defer"];
|
|
4
|
+
export type ChatGuardrailOutcome = (typeof chatGuardrailOutcomes)[number];
|
|
5
|
+
export type ChatGuardrailAction = "providerMessage" | "toolRequest" | "subagentRequest" | "messagePersist" | "evidenceWrite" | "outputRender";
|
|
6
|
+
export type ChatGuardrailActorType = "human" | "runtime" | "system" | "tool";
|
|
7
|
+
export type ChatGuardrailResourceType = "artifact" | "command" | "evidence" | "file" | "message" | "prompt" | "subagent" | "thread" | "url";
|
|
8
|
+
export interface ChatGuardrailActor {
|
|
9
|
+
id: string;
|
|
10
|
+
actorType: ChatGuardrailActorType;
|
|
11
|
+
tenantId: string;
|
|
12
|
+
workspaceId: string;
|
|
13
|
+
}
|
|
14
|
+
export interface ChatGuardrailResource {
|
|
15
|
+
resourceType: ChatGuardrailResourceType;
|
|
16
|
+
summary: string;
|
|
17
|
+
tenantId: string;
|
|
18
|
+
workspaceId: string;
|
|
19
|
+
}
|
|
20
|
+
export interface ChatGuardrailSink {
|
|
21
|
+
kind: PolicySink;
|
|
22
|
+
}
|
|
23
|
+
export interface ChatGuardrailRequest {
|
|
24
|
+
requestId: string;
|
|
25
|
+
tenantId: string;
|
|
26
|
+
workspaceId: string;
|
|
27
|
+
taskId?: string;
|
|
28
|
+
runId?: string;
|
|
29
|
+
threadId?: string;
|
|
30
|
+
messageId?: string;
|
|
31
|
+
actor: ChatGuardrailActor;
|
|
32
|
+
action: ChatGuardrailAction;
|
|
33
|
+
sink: ChatGuardrailSink;
|
|
34
|
+
resource: ChatGuardrailResource;
|
|
35
|
+
segments: PromptSegmentInput[];
|
|
36
|
+
redactionReportOverride?: RedactionReport;
|
|
37
|
+
}
|
|
38
|
+
export interface ChatGuardrailScope {
|
|
39
|
+
tenantId: string;
|
|
40
|
+
workspaceId: string;
|
|
41
|
+
resourceTenantId: string;
|
|
42
|
+
resourceWorkspaceId: string;
|
|
43
|
+
}
|
|
44
|
+
export interface ChatHumanReviewMetadata {
|
|
45
|
+
required: true;
|
|
46
|
+
reason: string;
|
|
47
|
+
decisionId: string;
|
|
48
|
+
matchedRuleIds: string[];
|
|
49
|
+
redactionStatus: RedactionStatus;
|
|
50
|
+
scope: ChatGuardrailScope;
|
|
51
|
+
}
|
|
52
|
+
export interface ChatGuardrailDecision {
|
|
53
|
+
requestId: string;
|
|
54
|
+
outcome: ChatGuardrailOutcome;
|
|
55
|
+
policyOutcome: PolicyDecisionOutcome;
|
|
56
|
+
matchedRuleIds: string[];
|
|
57
|
+
redactionStatus: RedactionStatus;
|
|
58
|
+
redactedSegments: RedactedSegment[];
|
|
59
|
+
sanitizedReasons: string[];
|
|
60
|
+
evidenceSummary: string;
|
|
61
|
+
humanReview?: ChatHumanReviewMetadata;
|
|
62
|
+
scope: ChatGuardrailScope;
|
|
63
|
+
canProceed: boolean;
|
|
64
|
+
policySegments: PromptSegment[];
|
|
65
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-guardrail-types.js","sourceRoot":"","sources":["../../src/security/chat-guardrail-types.ts"],"names":[],"mappings":"AAUA,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAU,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ChatGuardrailRequest, ChatGuardrailScope } from "./chat-guardrail-types.js";
|
|
2
|
+
export interface ChatGuardrailRule {
|
|
3
|
+
ruleId: string;
|
|
4
|
+
reason: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function validateChatRequestShape(request: Partial<ChatGuardrailRequest>): ChatGuardrailRule[];
|
|
7
|
+
export declare function validateScope(request: ChatGuardrailRequest): ChatGuardrailRule[];
|
|
8
|
+
export declare function scopeFor(request: ChatGuardrailRequest): ChatGuardrailScope;
|
|
9
|
+
export declare function emptyScope(): ChatGuardrailScope;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
export function validateChatRequestShape(request) {
|
|
2
|
+
return [
|
|
3
|
+
requiredRule("chat.input.request-id", "request id", request.requestId),
|
|
4
|
+
requiredRule("chat.input.tenant-id", "tenant id", request.tenantId),
|
|
5
|
+
requiredRule("chat.input.workspace-id", "workspace id", request.workspaceId),
|
|
6
|
+
requiredRule("chat.input.actor", "actor", request.actor),
|
|
7
|
+
requiredRule("chat.input.action", "action", request.action),
|
|
8
|
+
requiredRule("chat.input.sink", "sink", request.sink),
|
|
9
|
+
requiredRule("chat.input.sink-kind", "sink kind", request.sink?.kind),
|
|
10
|
+
requiredRule("chat.input.resource", "resource", request.resource),
|
|
11
|
+
requiredRule("chat.input.segments", "segments", request.segments),
|
|
12
|
+
].filter((rule) => rule !== null);
|
|
13
|
+
}
|
|
14
|
+
export function validateScope(request) {
|
|
15
|
+
const rules = [
|
|
16
|
+
requiredRule("chat.scope.actor-tenant", "actor tenant id", request.actor.tenantId),
|
|
17
|
+
requiredRule("chat.scope.actor-workspace", "actor workspace id", request.actor.workspaceId),
|
|
18
|
+
requiredRule("chat.scope.resource-tenant", "resource tenant id", request.resource.tenantId),
|
|
19
|
+
requiredRule("chat.scope.resource-workspace", "resource workspace id", request.resource.workspaceId),
|
|
20
|
+
].filter((rule) => rule !== null);
|
|
21
|
+
if (rules.length > 0)
|
|
22
|
+
return rules;
|
|
23
|
+
if (request.tenantId !== request.actor.tenantId ||
|
|
24
|
+
request.tenantId !== request.resource.tenantId) {
|
|
25
|
+
return [
|
|
26
|
+
{
|
|
27
|
+
ruleId: "chat.scope.tenant-mismatch",
|
|
28
|
+
reason: "request scope is not authorized for this tenant",
|
|
29
|
+
},
|
|
30
|
+
];
|
|
31
|
+
}
|
|
32
|
+
if (request.workspaceId !== request.actor.workspaceId ||
|
|
33
|
+
request.workspaceId !== request.resource.workspaceId) {
|
|
34
|
+
return [
|
|
35
|
+
{
|
|
36
|
+
ruleId: "chat.scope.workspace-mismatch",
|
|
37
|
+
reason: "request scope is not authorized for this workspace",
|
|
38
|
+
},
|
|
39
|
+
];
|
|
40
|
+
}
|
|
41
|
+
return [];
|
|
42
|
+
}
|
|
43
|
+
export function scopeFor(request) {
|
|
44
|
+
return {
|
|
45
|
+
tenantId: request.tenantId,
|
|
46
|
+
workspaceId: request.workspaceId,
|
|
47
|
+
resourceTenantId: request.resource.tenantId,
|
|
48
|
+
resourceWorkspaceId: request.resource.workspaceId,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
export function emptyScope() {
|
|
52
|
+
return {
|
|
53
|
+
tenantId: "unknown",
|
|
54
|
+
workspaceId: "unknown",
|
|
55
|
+
resourceTenantId: "unknown",
|
|
56
|
+
resourceWorkspaceId: "unknown",
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
function requiredRule(ruleId, label, value) {
|
|
60
|
+
if (value)
|
|
61
|
+
return null;
|
|
62
|
+
return { ruleId, reason: `missing ${label}` };
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=chat-guardrail-validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-guardrail-validation.js","sourceRoot":"","sources":["../../src/security/chat-guardrail-validation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { evaluateSecurityPolicy } from "./policy-engine.js";
|
|
2
|
+
import { intakePromptPacket } from "./prompt-intake.js";
|
|
3
|
+
import { redactPromptSegments } from "./redaction.js";
|
|
4
|
+
import { chatOutcomeForPolicy, highestClassification, policyActionFor, policyResourceFor, policySubjectFor, } from "./chat-guardrail-policy.js";
|
|
5
|
+
import { emptyScope, scopeFor, validateChatRequestShape, validateScope, } from "./chat-guardrail-validation.js";
|
|
6
|
+
export { chatOutcomeForPolicy } from "./chat-guardrail-policy.js";
|
|
7
|
+
const unsafeToolFindingKinds = [
|
|
8
|
+
"pathTraversal",
|
|
9
|
+
"shellLike",
|
|
10
|
+
"unsafeUrl",
|
|
11
|
+
];
|
|
12
|
+
export function evaluateChatGuardrail(request) {
|
|
13
|
+
const shapeRules = validateChatRequestShape(request);
|
|
14
|
+
if (shapeRules.length > 0) {
|
|
15
|
+
return chatDecisionFromRules(request.requestId, shapeRules);
|
|
16
|
+
}
|
|
17
|
+
const scopedRequest = request;
|
|
18
|
+
const scopeRules = validateScope(scopedRequest);
|
|
19
|
+
const scope = scopeFor(scopedRequest);
|
|
20
|
+
if (scopeRules.length > 0) {
|
|
21
|
+
return chatDecisionFromRules(scopedRequest.requestId, scopeRules, scope);
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
const rawSegments = intakePromptPacket({
|
|
25
|
+
segments: scopedRequest.segments,
|
|
26
|
+
});
|
|
27
|
+
const redactionReport = scopedRequest.redactionReportOverride ??
|
|
28
|
+
redactPromptSegments(rawSegments);
|
|
29
|
+
const policySegments = policySegmentsFor(scopedRequest, rawSegments, redactionReport);
|
|
30
|
+
const unsafeToolRules = unsafeToolRequestRules(scopedRequest.action, rawSegments);
|
|
31
|
+
if (unsafeToolRules.length > 0) {
|
|
32
|
+
return chatDecisionFromRules(scopedRequest.requestId, unsafeToolRules, scope, redactionReport, policySegments);
|
|
33
|
+
}
|
|
34
|
+
const policyDecision = evaluateSecurityPolicy({
|
|
35
|
+
requestId: scopedRequest.requestId,
|
|
36
|
+
subject: policySubjectFor(scopedRequest),
|
|
37
|
+
action: policyActionFor(scopedRequest.action, scopedRequest.resource),
|
|
38
|
+
resource: policyResourceFor(scopedRequest.resource),
|
|
39
|
+
sink: scopedRequest.sink.kind,
|
|
40
|
+
dataClassification: highestClassification(policySegments),
|
|
41
|
+
segments: policySegments,
|
|
42
|
+
redactionReport,
|
|
43
|
+
});
|
|
44
|
+
return chatDecisionFromPolicy(scopedRequest, scope, policyDecision, redactionReport, policySegments);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return chatDecisionFromRules(scopedRequest.requestId, [
|
|
48
|
+
{
|
|
49
|
+
ruleId: "chat.guardrail.exception",
|
|
50
|
+
reason: "chat guardrail failed closed",
|
|
51
|
+
},
|
|
52
|
+
], scope);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function unsafeToolRequestRules(action, segments) {
|
|
56
|
+
if (action !== "toolRequest")
|
|
57
|
+
return [];
|
|
58
|
+
return segments.flatMap((segment) => segment.classification.findings
|
|
59
|
+
.filter((finding) => isUnsafeToolFinding(finding.kind))
|
|
60
|
+
.map((finding) => ({
|
|
61
|
+
ruleId: `chat.tool.block.${finding.kind}`,
|
|
62
|
+
reason: `segment ${segment.id} matched unsafe tool request content`,
|
|
63
|
+
})));
|
|
64
|
+
}
|
|
65
|
+
function isUnsafeToolFinding(kind) {
|
|
66
|
+
return unsafeToolFindingKinds.some((unsafeKind) => unsafeKind === kind);
|
|
67
|
+
}
|
|
68
|
+
function policySegmentsFor(request, rawSegments, redactionReport) {
|
|
69
|
+
return redactionReport.redactedSegments.map((redactedSegment, index) => {
|
|
70
|
+
const rawSegment = rawSegments[index];
|
|
71
|
+
return intakePromptPacket({
|
|
72
|
+
segments: [
|
|
73
|
+
{
|
|
74
|
+
id: redactedSegment.id,
|
|
75
|
+
kind: rawSegment?.kind ?? "unknown",
|
|
76
|
+
provenance: rawSegment?.provenance ?? "unknown",
|
|
77
|
+
sink: request.sink.kind,
|
|
78
|
+
text: redactedSegment.text,
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
})[0];
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
function chatDecisionFromPolicy(request, scope, policyDecision, redactionReport, policySegments) {
|
|
85
|
+
const outcome = chatOutcomeForPolicy(policyDecision.outcome);
|
|
86
|
+
const decision = {
|
|
87
|
+
requestId: request.requestId,
|
|
88
|
+
outcome,
|
|
89
|
+
policyOutcome: policyDecision.outcome,
|
|
90
|
+
matchedRuleIds: policyDecision.matchedRuleIds,
|
|
91
|
+
redactionStatus: policyDecision.redactionStatus,
|
|
92
|
+
redactedSegments: redactionReport.redactedSegments,
|
|
93
|
+
sanitizedReasons: [
|
|
94
|
+
...policyDecision.sanitizedReasons,
|
|
95
|
+
...redactionReport.sanitizedReasons,
|
|
96
|
+
],
|
|
97
|
+
evidenceSummary: `${outcome}: chat guardrail mapped ${policyDecision.outcome}`,
|
|
98
|
+
scope,
|
|
99
|
+
canProceed: outcome === "allow",
|
|
100
|
+
policySegments,
|
|
101
|
+
};
|
|
102
|
+
if (outcome === "defer") {
|
|
103
|
+
decision.humanReview = {
|
|
104
|
+
required: true,
|
|
105
|
+
reason: policyDecision.sanitizedReasons[0] ?? "human review required",
|
|
106
|
+
decisionId: request.requestId,
|
|
107
|
+
matchedRuleIds: policyDecision.matchedRuleIds,
|
|
108
|
+
redactionStatus: policyDecision.redactionStatus,
|
|
109
|
+
scope,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
return decision;
|
|
113
|
+
}
|
|
114
|
+
function chatDecisionFromRules(requestId, rules, scope = emptyScope(), redactionReport = emptyRedactionReport(), policySegments = []) {
|
|
115
|
+
return {
|
|
116
|
+
requestId: requestId ?? "unknown",
|
|
117
|
+
outcome: "block",
|
|
118
|
+
policyOutcome: "deny",
|
|
119
|
+
matchedRuleIds: rules.map((rule) => rule.ruleId),
|
|
120
|
+
redactionStatus: redactionReport.status,
|
|
121
|
+
redactedSegments: redactionReport.redactedSegments,
|
|
122
|
+
sanitizedReasons: rules.map((rule) => rule.reason),
|
|
123
|
+
evidenceSummary: "block: chat guardrail failed closed",
|
|
124
|
+
scope,
|
|
125
|
+
canProceed: false,
|
|
126
|
+
policySegments,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
function emptyRedactionReport() {
|
|
130
|
+
return {
|
|
131
|
+
status: "unsafeUnredacted",
|
|
132
|
+
redactedSegments: [],
|
|
133
|
+
sanitizedReasons: ["redaction unavailable"],
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=chat-guardrails.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-guardrails.js","sourceRoot":"","sources":["../../src/security/chat-guardrails.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { hasPaymentCardLikeValue } from "./payment-card-detection.js";
|
|
1
2
|
const promptInjectionPhrases = [
|
|
2
3
|
"ignore previous instructions",
|
|
3
4
|
"ignore all previous instructions",
|
|
@@ -37,6 +38,36 @@ const privateHostPatterns = [
|
|
|
37
38
|
"172.31.",
|
|
38
39
|
"[::1]",
|
|
39
40
|
];
|
|
41
|
+
const piiRules = [
|
|
42
|
+
{
|
|
43
|
+
kind: "piiEmail",
|
|
44
|
+
ruleId: "content.pii.email",
|
|
45
|
+
severity: "high",
|
|
46
|
+
summary: "content contains an email address",
|
|
47
|
+
matches: (value) => /\b[a-z0-9._%+-]+@[a-z0-9.-]+[.][a-z]{2,}\b/i.test(value),
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
kind: "piiPhone",
|
|
51
|
+
ruleId: "content.pii.phone",
|
|
52
|
+
severity: "high",
|
|
53
|
+
summary: "content contains a phone-number-like value",
|
|
54
|
+
matches: (value) => /(?:\+?1[\s.-]?)?(?:[(]\d{3}[)]|\b\d{3})[\s.-]?\d{3}[\s.-]?\d{4}\b/.test(value),
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
kind: "piiSsn",
|
|
58
|
+
ruleId: "content.pii.ssn",
|
|
59
|
+
severity: "critical",
|
|
60
|
+
summary: "content contains an SSN-like identifier",
|
|
61
|
+
matches: (value) => /\b\d{3}-\d{2}-\d{4}\b/.test(value),
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
kind: "piiPaymentCard",
|
|
65
|
+
ruleId: "content.pii.payment-card",
|
|
66
|
+
severity: "critical",
|
|
67
|
+
summary: "content contains a payment-card-like value",
|
|
68
|
+
matches: hasPaymentCardLikeValue,
|
|
69
|
+
},
|
|
70
|
+
];
|
|
40
71
|
const contentRules = [
|
|
41
72
|
{
|
|
42
73
|
kind: "promptInjection",
|
|
@@ -98,6 +129,7 @@ const contentRules = [
|
|
|
98
129
|
matches: (value) => /\bbearer\s+[a-z0-9._-]{12,}/i.test(value) ||
|
|
99
130
|
/\b(api[_-]?key|password|secret|token)\s*[:=]\s*[^\s"']{12,}/i.test(value),
|
|
100
131
|
},
|
|
132
|
+
...piiRules,
|
|
101
133
|
];
|
|
102
134
|
export function classifyContent(text) {
|
|
103
135
|
const findings = contentRules
|
|
@@ -117,7 +149,7 @@ function toFinding(rule) {
|
|
|
117
149
|
};
|
|
118
150
|
}
|
|
119
151
|
function classificationForFindings(findings) {
|
|
120
|
-
if (findings.some((finding) => finding.kind === "secretShaped")) {
|
|
152
|
+
if (findings.some((finding) => finding.kind === "secretShaped" || finding.kind.startsWith("pii"))) {
|
|
121
153
|
return "restricted";
|
|
122
154
|
}
|
|
123
155
|
if (findings.length > 0) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content-classifier.js","sourceRoot":"","sources":["../../src/security/content-classifier.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"content-classifier.js","sourceRoot":"","sources":["../../src/security/content-classifier.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
const paymentCardCandidatePattern = /\b\d(?:[ -]?\d){12,18}\b/g;
|
|
2
|
+
export function hasPaymentCardLikeValue(value) {
|
|
3
|
+
return paymentCardCandidates(value).some(isPaymentCardLikeValue);
|
|
4
|
+
}
|
|
5
|
+
export function redactPaymentCardLikeValues(value, replacement) {
|
|
6
|
+
return value.replace(paymentCardCandidatePattern, (match, offset) => isPaymentCardLikeCandidate(value, match, offset) ? replacement : match);
|
|
7
|
+
}
|
|
8
|
+
export function isPaymentCardLikeValue(value) {
|
|
9
|
+
const digits = value.replace(/[ -]/g, "");
|
|
10
|
+
if (digits.length < 13 || digits.length > 19)
|
|
11
|
+
return false;
|
|
12
|
+
return luhnChecksum(digits);
|
|
13
|
+
}
|
|
14
|
+
function paymentCardCandidates(value) {
|
|
15
|
+
paymentCardCandidatePattern.lastIndex = 0;
|
|
16
|
+
return [...value.matchAll(paymentCardCandidatePattern)]
|
|
17
|
+
.filter((match) => isPaymentCardLikeCandidate(value, match[0], match.index ?? 0))
|
|
18
|
+
.map((match) => match[0]);
|
|
19
|
+
}
|
|
20
|
+
function isPaymentCardLikeCandidate(source, value, offset) {
|
|
21
|
+
if (!isPaymentCardLikeValue(value))
|
|
22
|
+
return false;
|
|
23
|
+
const before = source[offset - 1] ?? "";
|
|
24
|
+
const after = source[offset + value.length] ?? "";
|
|
25
|
+
return !isIdentifierBoundary(before) && !isIdentifierBoundary(after);
|
|
26
|
+
}
|
|
27
|
+
function isIdentifierBoundary(value) {
|
|
28
|
+
return /[A-Za-z0-9_-]/.test(value);
|
|
29
|
+
}
|
|
30
|
+
function luhnChecksum(value) {
|
|
31
|
+
let sum = 0;
|
|
32
|
+
let shouldDouble = false;
|
|
33
|
+
for (let index = value.length - 1; index >= 0; index -= 1) {
|
|
34
|
+
const digit = Number(value[index]);
|
|
35
|
+
if (!Number.isInteger(digit))
|
|
36
|
+
return false;
|
|
37
|
+
let contribution = digit;
|
|
38
|
+
if (shouldDouble) {
|
|
39
|
+
contribution = digit * 2;
|
|
40
|
+
if (contribution > 9)
|
|
41
|
+
contribution -= 9;
|
|
42
|
+
}
|
|
43
|
+
sum += contribution;
|
|
44
|
+
shouldDouble = !shouldDouble;
|
|
45
|
+
}
|
|
46
|
+
return sum > 0 && sum % 10 === 0;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=payment-card-detection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payment-card-detection.js","sourceRoot":"","sources":["../../src/security/payment-card-detection.ts"],"names":[],"mappings":"AAAA,MAAM,2BAA2B,GAAG,2BAA2B,CAAC;AAEhE,MAAM,UAAU,uBAAuB,CAAC,KAAa;IACnD,OAAO,qBAAqB,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;AACnE,CAAC;AAED,MAAM,UAAU,2BAA2B,CACzC,KAAa,EACb,WAAmB;IAEnB,OAAO,KAAK,CAAC,OAAO,CAAC,2BAA2B,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAClE,0BAA0B,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CACvE,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,KAAa;IAClD,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAC1C,IAAI,MAAM,CAAC,MAAM,GAAG,EAAE,IAAI,MAAM,CAAC,MAAM,GAAG,EAAE;QAAE,OAAO,KAAK,CAAC;IAC3D,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC;AAC9B,CAAC;AAED,SAAS,qBAAqB,CAAC,KAAa;IAC1C,2BAA2B,CAAC,SAAS,GAAG,CAAC,CAAC;IAC1C,OAAO,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,2BAA2B,CAAC,CAAC;SACpD,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAChB,0BAA0B,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC,CAC9D;SACA,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9B,CAAC;AAED,SAAS,0BAA0B,CACjC,MAAc,EACd,KAAa,EACb,MAAc;IAEd,IAAI,CAAC,sBAAsB,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACjD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACxC,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IAClD,OAAO,CAAC,oBAAoB,CAAC,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC;AACvE,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAa;IACzC,OAAO,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,YAAY,CAAC,KAAa;IACjC,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB,KAAK,IAAI,KAAK,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QAC1D,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;QACnC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;QAC3C,IAAI,YAAY,GAAG,KAAK,CAAC;QACzB,IAAI,YAAY,EAAE,CAAC;YACjB,YAAY,GAAG,KAAK,GAAG,CAAC,CAAC;YACzB,IAAI,YAAY,GAAG,CAAC;gBAAE,YAAY,IAAI,CAAC,CAAC;QAC1C,CAAC;QACD,GAAG,IAAI,YAAY,CAAC;QACpB,YAAY,GAAG,CAAC,YAAY,CAAC;IAC/B,CAAC;IACD,OAAO,GAAG,GAAG,CAAC,IAAI,GAAG,GAAG,EAAE,KAAK,CAAC,CAAC;AACnC,CAAC"}
|
|
@@ -5,7 +5,7 @@ export type PolicySink = "evidence" | "htmlText" | "json" | "log" | "markdown" |
|
|
|
5
5
|
export type SegmentKind = "data" | "evidence" | "instruction" | "providerResponse" | "toolInput" | "toolOutput" | "unknown";
|
|
6
6
|
export type DataClassification = "public" | "internal" | "restricted" | "unknown";
|
|
7
7
|
export type FindingSeverity = "low" | "medium" | "high" | "critical";
|
|
8
|
-
export type ContentFindingKind = "indirectPromptInjection" | "noSqlLike" | "pathTraversal" | "promptInjection" | "secretShaped" | "shellLike" | "sqlLike" | "unsafeUrl";
|
|
8
|
+
export type ContentFindingKind = "indirectPromptInjection" | "noSqlLike" | "pathTraversal" | "piiEmail" | "piiPaymentCard" | "piiPhone" | "piiSsn" | "promptInjection" | "secretShaped" | "shellLike" | "sqlLike" | "unsafeUrl";
|
|
9
9
|
export interface ContentFinding {
|
|
10
10
|
kind: ContentFindingKind;
|
|
11
11
|
ruleId: string;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ContentClassification, DataClassification, PolicyDecision } from "./policy-types.js";
|
|
2
|
+
import type { ModelMessage } from "../types/model-config.js";
|
|
3
|
+
export interface ProviderEgressClassification {
|
|
4
|
+
classification: DataClassification;
|
|
5
|
+
findings: ContentClassification["findings"];
|
|
6
|
+
}
|
|
7
|
+
export interface ProviderEgressClassifier {
|
|
8
|
+
classify(text: string): ProviderEgressClassification;
|
|
9
|
+
}
|
|
10
|
+
export interface ProviderEgressPolicyInput {
|
|
11
|
+
requestId?: string;
|
|
12
|
+
taskId: string;
|
|
13
|
+
role: string;
|
|
14
|
+
actor: string;
|
|
15
|
+
providerId: string;
|
|
16
|
+
messages: ModelMessage[];
|
|
17
|
+
classifier?: ProviderEgressClassifier;
|
|
18
|
+
}
|
|
19
|
+
export interface ProviderEgressPolicyDecision {
|
|
20
|
+
allowed: boolean;
|
|
21
|
+
requestId: string;
|
|
22
|
+
outcome: PolicyDecision["outcome"];
|
|
23
|
+
safeMessage?: string;
|
|
24
|
+
matchedRuleIds: string[];
|
|
25
|
+
redactionStatus: PolicyDecision["redactionStatus"];
|
|
26
|
+
}
|
|
27
|
+
export declare function evaluateProviderEgressPolicy(input: ProviderEgressPolicyInput): ProviderEgressPolicyDecision;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { evaluateSecurityPolicy } from "./policy-engine.js";
|
|
3
|
+
import { intakePromptSegment } from "./prompt-intake.js";
|
|
4
|
+
import { redactPromptSegments } from "./redaction.js";
|
|
5
|
+
export function evaluateProviderEgressPolicy(input) {
|
|
6
|
+
const requestId = input.requestId ?? `provider-egress-${randomUUID()}`;
|
|
7
|
+
const segments = input.messages.map((message, index) => providerPromptSegment(message, index, input.classifier));
|
|
8
|
+
const redactionReport = redactPromptSegments(segments);
|
|
9
|
+
const decision = evaluateSecurityPolicy({
|
|
10
|
+
requestId,
|
|
11
|
+
subject: {
|
|
12
|
+
id: input.actor,
|
|
13
|
+
subjectType: "runtime",
|
|
14
|
+
workspaceId: input.taskId,
|
|
15
|
+
},
|
|
16
|
+
action: "provider.message",
|
|
17
|
+
resource: {
|
|
18
|
+
resourceType: "prompt",
|
|
19
|
+
summary: `provider egress to ${input.providerId}`,
|
|
20
|
+
workspaceId: input.taskId,
|
|
21
|
+
},
|
|
22
|
+
sink: "provider",
|
|
23
|
+
dataClassification: highestDataClassification(segments),
|
|
24
|
+
segments,
|
|
25
|
+
redactionReport,
|
|
26
|
+
});
|
|
27
|
+
const allowed = redactionReport.status === "notRequired" &&
|
|
28
|
+
!hasRestrictedClassification(segments);
|
|
29
|
+
return {
|
|
30
|
+
allowed,
|
|
31
|
+
requestId,
|
|
32
|
+
outcome: decision.outcome,
|
|
33
|
+
matchedRuleIds: decision.matchedRuleIds,
|
|
34
|
+
redactionStatus: decision.redactionStatus,
|
|
35
|
+
...(allowed
|
|
36
|
+
? {}
|
|
37
|
+
: {
|
|
38
|
+
safeMessage: "provider egress blocked by restricted-content policy before provider execution",
|
|
39
|
+
}),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function hasRestrictedClassification(segments) {
|
|
43
|
+
return segments.some((segment) => segment.classification.classification === "restricted");
|
|
44
|
+
}
|
|
45
|
+
function providerPromptSegment(message, index, classifier) {
|
|
46
|
+
const segment = intakePromptSegment({
|
|
47
|
+
id: `message-${index + 1}`,
|
|
48
|
+
kind: message.role === "tool" ? "toolOutput" : "instruction",
|
|
49
|
+
provenance: `model-message:${message.role}`,
|
|
50
|
+
sink: "provider",
|
|
51
|
+
text: message.content,
|
|
52
|
+
}, `message-${index + 1}`);
|
|
53
|
+
if (!classifier)
|
|
54
|
+
return segment;
|
|
55
|
+
return {
|
|
56
|
+
...segment,
|
|
57
|
+
classification: classifier.classify(message.content),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function highestDataClassification(segments) {
|
|
61
|
+
if (segments.some((segment) => segment.classification.classification === "restricted")) {
|
|
62
|
+
return "restricted";
|
|
63
|
+
}
|
|
64
|
+
if (segments.some((segment) => segment.classification.classification === "unknown")) {
|
|
65
|
+
return "unknown";
|
|
66
|
+
}
|
|
67
|
+
if (segments.some((segment) => segment.classification.classification === "internal")) {
|
|
68
|
+
return "internal";
|
|
69
|
+
}
|
|
70
|
+
return "public";
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=provider-egress-policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-egress-policy.js","sourceRoot":"","sources":["../../src/security/provider-egress-policy.ts"],"names":[],"mappings":"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"}
|