@decionis/agent-safe-pipeline 0.1.3 → 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/README.md +477 -16
- package/dist/Index.d.ts +9 -0
- package/dist/Index.d.ts.map +1 -1
- package/dist/Index.js +8 -0
- package/dist/Index.js.map +1 -1
- package/dist/approval/PresenceApprovalCoordinator.d.ts +25 -0
- package/dist/approval/PresenceApprovalCoordinator.d.ts.map +1 -1
- package/dist/approval/PresenceApprovalCoordinator.js +54 -6
- package/dist/approval/PresenceApprovalCoordinator.js.map +1 -1
- package/dist/audit/AuditRecorder.d.ts +122 -0
- package/dist/audit/AuditRecorder.d.ts.map +1 -0
- package/dist/audit/AuditRecorder.js +312 -0
- package/dist/audit/AuditRecorder.js.map +1 -0
- package/dist/decision/CreateGate.d.ts +123 -0
- package/dist/decision/CreateGate.d.ts.map +1 -0
- package/dist/decision/CreateGate.js +211 -0
- package/dist/decision/CreateGate.js.map +1 -0
- package/dist/decision/DecionisGate.d.ts +109 -3
- package/dist/decision/DecionisGate.d.ts.map +1 -1
- package/dist/decision/DecionisGate.js +823 -46
- package/dist/decision/DecionisGate.js.map +1 -1
- package/dist/decision/DecisionAuthority.d.ts +76 -1
- package/dist/decision/DecisionAuthority.d.ts.map +1 -1
- package/dist/decision/DecisionAuthority.js.map +1 -1
- package/dist/decision/FixtureDecisionAuthority.d.ts +27 -1
- package/dist/decision/FixtureDecisionAuthority.d.ts.map +1 -1
- package/dist/decision/FixtureDecisionAuthority.js +47 -0
- package/dist/decision/FixtureDecisionAuthority.js.map +1 -1
- package/dist/decision/ImmutableGateDecision.d.ts.map +1 -1
- package/dist/decision/ImmutableGateDecision.js +26 -0
- package/dist/decision/ImmutableGateDecision.js.map +1 -1
- package/dist/decision/Provision.d.ts +33 -0
- package/dist/decision/Provision.d.ts.map +1 -0
- package/dist/decision/Provision.js +116 -0
- package/dist/decision/Provision.js.map +1 -0
- package/dist/decision/ShadowGate.d.ts +31 -0
- package/dist/decision/ShadowGate.d.ts.map +1 -0
- package/dist/decision/ShadowGate.js +79 -0
- package/dist/decision/ShadowGate.js.map +1 -0
- package/dist/execution/ActionRegistry.d.ts +66 -0
- package/dist/execution/ActionRegistry.d.ts.map +1 -1
- package/dist/execution/ActionRegistry.js +110 -1
- package/dist/execution/ActionRegistry.js.map +1 -1
- package/dist/execution/AuthorizationVerifier.d.ts +149 -1
- package/dist/execution/AuthorizationVerifier.d.ts.map +1 -1
- package/dist/execution/AuthorizationVerifier.js +302 -27
- package/dist/execution/AuthorizationVerifier.js.map +1 -1
- package/dist/execution/SafeExecutor.d.ts +102 -7
- package/dist/execution/SafeExecutor.d.ts.map +1 -1
- package/dist/execution/SafeExecutor.js +288 -17
- package/dist/execution/SafeExecutor.js.map +1 -1
- package/dist/http/ClientIdentification.d.ts +22 -0
- package/dist/http/ClientIdentification.d.ts.map +1 -0
- package/dist/http/ClientIdentification.js +44 -0
- package/dist/http/ClientIdentification.js.map +1 -0
- package/dist/http/Credential.d.ts +17 -0
- package/dist/http/Credential.d.ts.map +1 -0
- package/dist/http/Credential.js +5 -0
- package/dist/http/Credential.js.map +1 -0
- package/dist/http/StoredCredentials.d.ts +34 -0
- package/dist/http/StoredCredentials.d.ts.map +1 -0
- package/dist/http/StoredCredentials.js +85 -0
- package/dist/http/StoredCredentials.js.map +1 -0
- package/dist/intent/CanonicalIntentHasher.d.ts +1 -1
- package/dist/intent/CanonicalIntentHasher.d.ts.map +1 -1
- package/dist/intent/CanonicalIntentHasher.js +9 -2
- package/dist/intent/CanonicalIntentHasher.js.map +1 -1
- package/dist/intent/ExecutionIntent.d.ts +26 -2
- package/dist/intent/ExecutionIntent.d.ts.map +1 -1
- package/dist/intent/ExecutionIntent.js +11 -0
- package/dist/intent/ExecutionIntent.js.map +1 -1
- package/dist/intent/IntentCapture.d.ts +5 -0
- package/dist/intent/IntentCapture.d.ts.map +1 -1
- package/dist/intent/IntentCapture.js +15 -1
- package/dist/intent/IntentCapture.js.map +1 -1
- package/dist/report/DecisionReport.d.ts +22 -0
- package/dist/report/DecisionReport.d.ts.map +1 -0
- package/dist/report/DecisionReport.js +37 -0
- package/dist/report/DecisionReport.js.map +1 -0
- package/dist/report/DossierReport.d.ts +43 -0
- package/dist/report/DossierReport.d.ts.map +1 -0
- package/dist/report/DossierReport.js +130 -0
- package/dist/report/DossierReport.js.map +1 -0
- package/dist/report/HostedOutcome.d.ts +18 -0
- package/dist/report/HostedOutcome.d.ts.map +1 -0
- package/dist/report/HostedOutcome.js +24 -0
- package/dist/report/HostedOutcome.js.map +1 -0
- package/dist/shadow/ShadowPipeline.d.ts +75 -5
- package/dist/shadow/ShadowPipeline.d.ts.map +1 -1
- package/dist/shadow/ShadowPipeline.js +157 -7
- package/dist/shadow/ShadowPipeline.js.map +1 -1
- package/dist/testing/Index.d.ts +12 -0
- package/dist/testing/Index.d.ts.map +1 -0
- package/dist/testing/Index.js +12 -0
- package/dist/testing/Index.js.map +1 -0
- package/dist/testing/LocalAuthority.d.ts +292 -0
- package/dist/testing/LocalAuthority.d.ts.map +1 -0
- package/dist/testing/LocalAuthority.js +1124 -0
- package/dist/testing/LocalAuthority.js.map +1 -0
- package/dist/testing/LocalPresence.d.ts +210 -0
- package/dist/testing/LocalPresence.d.ts.map +1 -0
- package/dist/testing/LocalPresence.js +473 -0
- package/dist/testing/LocalPresence.js.map +1 -0
- package/package.json +40 -4
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
+
import { RESERVED_CONTEXT_IDEMPOTENCY_KEY, } from "./ExecutionIntent.js";
|
|
2
3
|
const FORBIDDEN_KEYS = new Set(["__proto__", "constructor", "prototype"]);
|
|
3
4
|
export class CanonicalIntentHasher {
|
|
4
5
|
limits;
|
|
@@ -85,7 +86,6 @@ export class CanonicalIntentHasher {
|
|
|
85
86
|
protocol_version: intent.version,
|
|
86
87
|
tenant_id: intent.tenantId,
|
|
87
88
|
intent_id: intent.intentId,
|
|
88
|
-
idempotency_key: intent.idempotencyKey,
|
|
89
89
|
captured_at: intent.capturedAt,
|
|
90
90
|
expires_at: intent.expiresAt,
|
|
91
91
|
actor: {
|
|
@@ -99,14 +99,21 @@ export class CanonicalIntentHasher {
|
|
|
99
99
|
resource: intent.target,
|
|
100
100
|
parameters: intent.parameters,
|
|
101
101
|
},
|
|
102
|
-
context
|
|
102
|
+
// The idempotency key stays hash-bound by riding in the trusted context.
|
|
103
|
+
context: { ...intent.context, [RESERVED_CONTEXT_IDEMPOTENCY_KEY]: intent.idempotencyKey },
|
|
103
104
|
downstream_target: {
|
|
104
105
|
system: intent.downstreamTarget.system,
|
|
105
106
|
operation: intent.downstreamTarget.operation,
|
|
107
|
+
...(intent.downstreamTarget.environment === undefined
|
|
108
|
+
? {}
|
|
109
|
+
: { environment: intent.downstreamTarget.environment }),
|
|
106
110
|
...(intent.downstreamTarget.endpoint === undefined
|
|
107
111
|
? {}
|
|
108
112
|
: { endpoint: intent.downstreamTarget.endpoint }),
|
|
109
113
|
},
|
|
114
|
+
...(intent.expectedEffectDigest === undefined
|
|
115
|
+
? {}
|
|
116
|
+
: { expected_effect_digest: intent.expectedEffectDigest }),
|
|
110
117
|
};
|
|
111
118
|
}
|
|
112
119
|
static stringify(value) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CanonicalIntentHasher.js","sourceRoot":"","sources":["../../src/intent/CanonicalIntentHasher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"CanonicalIntentHasher.js","sourceRoot":"","sources":["../../src/intent/CanonicalIntentHasher.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,8 +14,15 @@ export declare const IntentActorSchema: z.ZodObject<{
|
|
|
14
14
|
export declare const DownstreamTargetSchema: z.ZodObject<{
|
|
15
15
|
system: z.ZodString;
|
|
16
16
|
operation: z.ZodString;
|
|
17
|
+
environment: z.ZodOptional<z.ZodString>;
|
|
17
18
|
endpoint: z.ZodOptional<z.ZodString>;
|
|
18
19
|
}, z.core.$strict>;
|
|
20
|
+
/**
|
|
21
|
+
* The trusted idempotency key travels inside the hashed wire `context` under
|
|
22
|
+
* this reserved key, because the Decionis `ExecutionIntentBinding` contract
|
|
23
|
+
* has no top-level idempotency field and rejects unknown properties.
|
|
24
|
+
*/
|
|
25
|
+
export declare const RESERVED_CONTEXT_IDEMPOTENCY_KEY = "idempotency_key";
|
|
19
26
|
export declare const TrustedIntentContextSchema: z.ZodObject<{
|
|
20
27
|
tenantId: z.ZodString;
|
|
21
28
|
actor: z.ZodObject<{
|
|
@@ -27,10 +34,12 @@ export declare const TrustedIntentContextSchema: z.ZodObject<{
|
|
|
27
34
|
downstreamTarget: z.ZodObject<{
|
|
28
35
|
system: z.ZodString;
|
|
29
36
|
operation: z.ZodString;
|
|
37
|
+
environment: z.ZodOptional<z.ZodString>;
|
|
30
38
|
endpoint: z.ZodOptional<z.ZodString>;
|
|
31
39
|
}, z.core.$strict>;
|
|
32
40
|
context: z.ZodDefault<z.ZodType<JsonObject, unknown, z.core.$ZodTypeInternals<JsonObject, unknown>>>;
|
|
33
41
|
correlationId: z.ZodOptional<z.ZodString>;
|
|
42
|
+
expectedEffectDigest: z.ZodOptional<z.ZodString>;
|
|
34
43
|
idempotencyKey: z.ZodString;
|
|
35
44
|
}, z.core.$strict>;
|
|
36
45
|
export declare const ExecutionIntentSchema: z.ZodObject<{
|
|
@@ -51,10 +60,12 @@ export declare const ExecutionIntentSchema: z.ZodObject<{
|
|
|
51
60
|
downstreamTarget: z.ZodObject<{
|
|
52
61
|
system: z.ZodString;
|
|
53
62
|
operation: z.ZodString;
|
|
63
|
+
environment: z.ZodOptional<z.ZodString>;
|
|
54
64
|
endpoint: z.ZodOptional<z.ZodString>;
|
|
55
65
|
}, z.core.$strict>;
|
|
56
66
|
context: z.ZodType<JsonObject, unknown, z.core.$ZodTypeInternals<JsonObject, unknown>>;
|
|
57
67
|
correlationId: z.ZodOptional<z.ZodString>;
|
|
68
|
+
expectedEffectDigest: z.ZodOptional<z.ZodString>;
|
|
58
69
|
idempotencyKey: z.ZodString;
|
|
59
70
|
}, z.core.$strict>;
|
|
60
71
|
export type AgentProposal = z.infer<typeof AgentProposalSchema>;
|
|
@@ -68,11 +79,14 @@ export interface CapturedIntent {
|
|
|
68
79
|
readonly intentHash: `sha256:${string}`;
|
|
69
80
|
readonly byteLength: number;
|
|
70
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* Wire shape of the Decionis `ExecutionIntentBinding` contract, less the
|
|
84
|
+
* optional `policy_projection` this package does not produce.
|
|
85
|
+
*/
|
|
71
86
|
export interface AuthorityIntentBinding {
|
|
72
87
|
readonly protocol_version: "agent-safe.intent/1";
|
|
73
88
|
readonly tenant_id: string;
|
|
74
89
|
readonly intent_id: string;
|
|
75
|
-
readonly idempotency_key: string;
|
|
76
90
|
readonly captured_at: string;
|
|
77
91
|
readonly expires_at: string;
|
|
78
92
|
readonly actor: {
|
|
@@ -86,11 +100,21 @@ export interface AuthorityIntentBinding {
|
|
|
86
100
|
readonly resource: string;
|
|
87
101
|
readonly parameters: JsonObject;
|
|
88
102
|
};
|
|
89
|
-
readonly context: JsonObject
|
|
103
|
+
readonly context: JsonObject & {
|
|
104
|
+
readonly idempotency_key: string;
|
|
105
|
+
};
|
|
90
106
|
readonly downstream_target: {
|
|
91
107
|
readonly system: string;
|
|
92
108
|
readonly operation: string;
|
|
109
|
+
readonly environment?: string;
|
|
93
110
|
readonly endpoint?: string;
|
|
94
111
|
};
|
|
112
|
+
/**
|
|
113
|
+
* Digest-only commitment to the downstream state predicted before dispatch.
|
|
114
|
+
* Absent unless the trusted runtime supplied one, so an intent that does not
|
|
115
|
+
* use it produces exactly the binding, canonical JSON, and hash it produced
|
|
116
|
+
* before this property existed.
|
|
117
|
+
*/
|
|
118
|
+
readonly expected_effect_digest?: string;
|
|
95
119
|
}
|
|
96
120
|
//# sourceMappingURL=ExecutionIntent.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExecutionIntent.d.ts","sourceRoot":"","sources":["../../src/intent/ExecutionIntent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"ExecutionIntent.d.ts","sourceRoot":"","sources":["../../src/intent/ExecutionIntent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAYnE,eAAO,MAAM,mBAAmB;;;;kBAMrB,CAAC;AAEZ,eAAO,MAAM,iBAAiB;;;;;kBAOnB,CAAC;AAEZ,eAAO,MAAM,sBAAsB;;;;;kBAOxB,CAAC;AAEZ;;;;GAIG;AACH,eAAO,MAAM,gCAAgC,oBAAoB,CAAC;AAElE,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;kBAU5B,CAAC;AAEZ,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;kBAiBvB,CAAC;AAEZ,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAChE,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC5D,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AACtE,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAC9E,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,eAAe,CAAC,CAAC;IAC3C,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,UAAU,EAAE,UAAU,MAAM,EAAE,CAAC;IACxC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,gBAAgB,EAAE,qBAAqB,CAAC;IACjD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE;QACd,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;KAC/B,CAAC;IACF,QAAQ,CAAC,MAAM,EAAE;QACf,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;KACjC,CAAC;IACF,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG;QAAE,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;KAAE,CAAC;IACpE,QAAQ,CAAC,iBAAiB,EAAE;QAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAC3B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAC9B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;KAC5B,CAAC;IACF;;;;;OAKG;IACH,QAAQ,CAAC,sBAAsB,CAAC,EAAE,MAAM,CAAC;CAC1C"}
|
|
@@ -7,6 +7,8 @@ const actionName = z
|
|
|
7
7
|
.min(1)
|
|
8
8
|
.max(120)
|
|
9
9
|
.regex(/^[a-z][a-z0-9._:-]*$/);
|
|
10
|
+
/** The Decionis contract's digest form, verbatim: `sha256:` and 64 lowercase hex. */
|
|
11
|
+
const sha256Digest = z.string().regex(/^sha256:[0-9a-f]{64}$/);
|
|
10
12
|
export const AgentProposalSchema = z
|
|
11
13
|
.object({
|
|
12
14
|
action: actionName,
|
|
@@ -26,9 +28,16 @@ export const DownstreamTargetSchema = z
|
|
|
26
28
|
.object({
|
|
27
29
|
system: boundedId,
|
|
28
30
|
operation: boundedId,
|
|
31
|
+
environment: boundedId.optional(),
|
|
29
32
|
endpoint: z.string().trim().min(1).max(500).optional(),
|
|
30
33
|
})
|
|
31
34
|
.strict();
|
|
35
|
+
/**
|
|
36
|
+
* The trusted idempotency key travels inside the hashed wire `context` under
|
|
37
|
+
* this reserved key, because the Decionis `ExecutionIntentBinding` contract
|
|
38
|
+
* has no top-level idempotency field and rejects unknown properties.
|
|
39
|
+
*/
|
|
40
|
+
export const RESERVED_CONTEXT_IDEMPOTENCY_KEY = "idempotency_key";
|
|
32
41
|
export const TrustedIntentContextSchema = z
|
|
33
42
|
.object({
|
|
34
43
|
tenantId: z.string().uuid(),
|
|
@@ -36,6 +45,7 @@ export const TrustedIntentContextSchema = z
|
|
|
36
45
|
downstreamTarget: DownstreamTargetSchema,
|
|
37
46
|
context: JsonObjectSchema.default({}),
|
|
38
47
|
correlationId: boundedId.optional(),
|
|
48
|
+
expectedEffectDigest: sha256Digest.optional(),
|
|
39
49
|
idempotencyKey: z.string().trim().min(1).max(180),
|
|
40
50
|
})
|
|
41
51
|
.strict();
|
|
@@ -53,6 +63,7 @@ export const ExecutionIntentSchema = z
|
|
|
53
63
|
downstreamTarget: DownstreamTargetSchema,
|
|
54
64
|
context: JsonObjectSchema,
|
|
55
65
|
correlationId: boundedId.optional(),
|
|
66
|
+
expectedEffectDigest: sha256Digest.optional(),
|
|
56
67
|
idempotencyKey: z.string().trim().min(1).max(180),
|
|
57
68
|
})
|
|
58
69
|
.strict();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExecutionIntent.js","sourceRoot":"","sources":["../../src/intent/ExecutionIntent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAmB,MAAM,gBAAgB,CAAC;AAEnE,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACpD,MAAM,UAAU,GAAG,CAAC;KACjB,MAAM,EAAE;KACR,IAAI,EAAE;KACN,GAAG,CAAC,CAAC,CAAC;KACN,GAAG,CAAC,GAAG,CAAC;KACR,KAAK,CAAC,sBAAsB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"ExecutionIntent.js","sourceRoot":"","sources":["../../src/intent/ExecutionIntent.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import type { AuditRecorder } from "../audit/AuditRecorder.js";
|
|
1
2
|
import { type AgentProposal, type CapturedIntent, type TrustedIntentContext } from "./ExecutionIntent.js";
|
|
2
3
|
import { CanonicalIntentHasher } from "./CanonicalIntentHasher.js";
|
|
3
4
|
export interface IntentCaptureOptions {
|
|
5
|
+
readonly audit?: AuditRecorder;
|
|
4
6
|
readonly hasher?: CanonicalIntentHasher;
|
|
5
7
|
readonly clock?: () => Date;
|
|
6
8
|
readonly createId?: () => string;
|
|
@@ -11,7 +13,10 @@ export declare class IntentCapture {
|
|
|
11
13
|
private readonly clock;
|
|
12
14
|
private readonly createId;
|
|
13
15
|
private readonly ttlSeconds;
|
|
16
|
+
private readonly audit;
|
|
14
17
|
constructor(options?: IntentCaptureOptions);
|
|
15
18
|
capture(proposalInput: AgentProposal, trustedInput: TrustedIntentContext): CapturedIntent;
|
|
19
|
+
/** Captures an intent and waits for the optional bounded audit sink once. */
|
|
20
|
+
captureAndAudit(proposalInput: AgentProposal, trustedInput: TrustedIntentContext): Promise<CapturedIntent>;
|
|
16
21
|
}
|
|
17
22
|
//# sourceMappingURL=IntentCapture.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IntentCapture.d.ts","sourceRoot":"","sources":["../../src/intent/IntentCapture.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"IntentCapture.d.ts","sourceRoot":"","sources":["../../src/intent/IntentCapture.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAKL,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,oBAAoB,EAC1B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC;IAC/B,QAAQ,CAAC,MAAM,CAAC,EAAE,qBAAqB,CAAC;IACxC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,MAAM,CAAC;IACjC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwB;IAC/C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAa;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAe;IACxC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA4B;gBAE/B,OAAO,CAAC,EAAE,oBAAoB;IAQ1C,OAAO,CAAC,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,oBAAoB,GAAG,cAAc;IA+BhG,6EAA6E;IAChE,eAAe,CAC1B,aAAa,EAAE,aAAa,EAC5B,YAAY,EAAE,oBAAoB,GACjC,OAAO,CAAC,cAAc,CAAC;CAK3B"}
|
|
@@ -1,22 +1,27 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
|
-
import { AgentProposalSchema, ExecutionIntentSchema, TrustedIntentContextSchema, } from "./ExecutionIntent.js";
|
|
2
|
+
import { AgentProposalSchema, ExecutionIntentSchema, RESERVED_CONTEXT_IDEMPOTENCY_KEY, TrustedIntentContextSchema, } from "./ExecutionIntent.js";
|
|
3
3
|
import { CanonicalIntentHasher } from "./CanonicalIntentHasher.js";
|
|
4
4
|
export class IntentCapture {
|
|
5
5
|
hasher;
|
|
6
6
|
clock;
|
|
7
7
|
createId;
|
|
8
8
|
ttlSeconds;
|
|
9
|
+
audit;
|
|
9
10
|
constructor(options) {
|
|
10
11
|
this.hasher = options?.hasher ?? new CanonicalIntentHasher();
|
|
11
12
|
this.clock = options?.clock ?? (() => new Date());
|
|
12
13
|
this.createId = options?.createId ?? randomUUID;
|
|
13
14
|
this.ttlSeconds = Math.min(Math.max(options?.ttlSeconds ?? 60, 1), 300);
|
|
15
|
+
this.audit = options?.audit;
|
|
14
16
|
}
|
|
15
17
|
capture(proposalInput, trustedInput) {
|
|
16
18
|
this.hasher.assertInputBounded(proposalInput);
|
|
17
19
|
this.hasher.assertInputBounded(trustedInput);
|
|
18
20
|
const proposal = AgentProposalSchema.parse(proposalInput);
|
|
19
21
|
const trusted = TrustedIntentContextSchema.parse(trustedInput);
|
|
22
|
+
if (Object.hasOwn(trusted.context, RESERVED_CONTEXT_IDEMPOTENCY_KEY)) {
|
|
23
|
+
throw new Error("INTENT_CONTEXT_KEY_RESERVED");
|
|
24
|
+
}
|
|
20
25
|
const capturedAt = this.clock();
|
|
21
26
|
const expiresAt = new Date(capturedAt.valueOf() + this.ttlSeconds * 1_000);
|
|
22
27
|
const intent = ExecutionIntentSchema.parse({
|
|
@@ -32,9 +37,18 @@ export class IntentCapture {
|
|
|
32
37
|
downstreamTarget: trusted.downstreamTarget,
|
|
33
38
|
context: trusted.context,
|
|
34
39
|
...(trusted.correlationId === undefined ? {} : { correlationId: trusted.correlationId }),
|
|
40
|
+
...(trusted.expectedEffectDigest === undefined
|
|
41
|
+
? {}
|
|
42
|
+
: { expectedEffectDigest: trusted.expectedEffectDigest }),
|
|
35
43
|
idempotencyKey: trusted.idempotencyKey,
|
|
36
44
|
});
|
|
37
45
|
return this.hasher.capture(intent);
|
|
38
46
|
}
|
|
47
|
+
/** Captures an intent and waits for the optional bounded audit sink once. */
|
|
48
|
+
async captureAndAudit(proposalInput, trustedInput) {
|
|
49
|
+
const captured = this.capture(proposalInput, trustedInput);
|
|
50
|
+
await this.audit?.record({ eventType: "INTENT_CAPTURED", captured });
|
|
51
|
+
return captured;
|
|
52
|
+
}
|
|
39
53
|
}
|
|
40
54
|
//# sourceMappingURL=IntentCapture.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IntentCapture.js","sourceRoot":"","sources":["../../src/intent/IntentCapture.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"IntentCapture.js","sourceRoot":"","sources":["../../src/intent/IntentCapture.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { GateDecision } from "../decision/DecisionAuthority.js";
|
|
2
|
+
export interface DecisionReportOptions {
|
|
3
|
+
/** Where the lines go. Defaults to `process.stdout`; a stdio MCP server passes `process.stderr`. */
|
|
4
|
+
readonly out?: {
|
|
5
|
+
write(chunk: string): unknown;
|
|
6
|
+
};
|
|
7
|
+
/** The command that fetches the record and verifies it; defaults to this repository's script. */
|
|
8
|
+
readonly verifyCommand?: (dossierId: string) => string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Prints what Decionis said about a decision, when it was asked. A decision
|
|
12
|
+
* with no `hosted` evaluation prints nothing, so a caller that never set a
|
|
13
|
+
* key sees exactly the output it saw before.
|
|
14
|
+
*
|
|
15
|
+
* The verify lines name the record by identifier only. The page, when the
|
|
16
|
+
* authority attached one, verifies it for anyone who opens it; the command
|
|
17
|
+
* needs the signed record, fetched with the caller's key, and the public
|
|
18
|
+
* JWKS, fetched by anyone; the signature check itself runs offline and needs
|
|
19
|
+
* no account.
|
|
20
|
+
*/
|
|
21
|
+
export declare function printDecision(decision: GateDecision, options?: DecisionReportOptions): void;
|
|
22
|
+
//# sourceMappingURL=DecisionReport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DecisionReport.d.ts","sourceRoot":"","sources":["../../src/report/DecisionReport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,kCAAkC,CAAC;AAEvF,MAAM,WAAW,qBAAqB;IACpC,oGAAoG;IACpG,QAAQ,CAAC,GAAG,CAAC,EAAE;QAAE,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IACjD,iGAAiG;IACjG,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC;CACxD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,YAAY,EAAE,OAAO,GAAE,qBAA0B,GAAG,IAAI,CAmB/F"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prints what Decionis said about a decision, when it was asked. A decision
|
|
3
|
+
* with no `hosted` evaluation prints nothing, so a caller that never set a
|
|
4
|
+
* key sees exactly the output it saw before.
|
|
5
|
+
*
|
|
6
|
+
* The verify lines name the record by identifier only. The page, when the
|
|
7
|
+
* authority attached one, verifies it for anyone who opens it; the command
|
|
8
|
+
* needs the signed record, fetched with the caller's key, and the public
|
|
9
|
+
* JWKS, fetched by anyone; the signature check itself runs offline and needs
|
|
10
|
+
* no account.
|
|
11
|
+
*/
|
|
12
|
+
export function printDecision(decision, options = {}) {
|
|
13
|
+
const hosted = decision.hosted;
|
|
14
|
+
if (hosted === undefined)
|
|
15
|
+
return;
|
|
16
|
+
const out = options.out ?? process.stdout;
|
|
17
|
+
const verifyCommand = options.verifyCommand ?? ((dossierId) => `pnpm decionis:verify ${dossierId}`);
|
|
18
|
+
out.write(`verdict: ${decision.verdict}\n`);
|
|
19
|
+
out.write(`decionis: ${hosted.verdict} (${hosted.mode}, ${standing(hosted)})\n`);
|
|
20
|
+
for (const code of hosted.reasonCodes)
|
|
21
|
+
out.write(` - ${code}\n`);
|
|
22
|
+
if (hosted.dossierId === null) {
|
|
23
|
+
out.write("dossier: none\n");
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
out.write(`dossier: ${hosted.dossierId}\n`);
|
|
27
|
+
if (hosted.verificationUrl !== null) {
|
|
28
|
+
out.write(`verify it in a browser, no account needed: ${hosted.verificationUrl}\n`);
|
|
29
|
+
}
|
|
30
|
+
out.write(`verify it yourself, no account needed: ${verifyCommand(hosted.dossierId)}\n`);
|
|
31
|
+
}
|
|
32
|
+
function standing(hosted) {
|
|
33
|
+
if (hosted.failClosed)
|
|
34
|
+
return "failed closed";
|
|
35
|
+
return hosted.governs ? "governs" : "recorded beside the local verdict";
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=DecisionReport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DecisionReport.js","sourceRoot":"","sources":["../../src/report/DecisionReport.ts"],"names":[],"mappings":"AASA;;;;;;;;;;GAUG;AACH,MAAM,UAAU,aAAa,CAAC,QAAsB,EAAE,UAAiC,EAAE;IACvF,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;IAC/B,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO;IACjC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;IAC1C,MAAM,aAAa,GACjB,OAAO,CAAC,aAAa,IAAI,CAAC,CAAC,SAAiB,EAAU,EAAE,CAAC,wBAAwB,SAAS,EAAE,CAAC,CAAC;IAEhG,GAAG,CAAC,KAAK,CAAC,YAAY,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;IAC5C,GAAG,CAAC,KAAK,CAAC,aAAa,MAAM,CAAC,OAAO,KAAK,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACjF,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,WAAW;QAAE,GAAG,CAAC,KAAK,CAAC,OAAO,IAAI,IAAI,CAAC,CAAC;IAClE,IAAI,MAAM,CAAC,SAAS,KAAK,IAAI,EAAE,CAAC;QAC9B,GAAG,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;QAC7B,OAAO;IACT,CAAC;IACD,GAAG,CAAC,KAAK,CAAC,YAAY,MAAM,CAAC,SAAS,IAAI,CAAC,CAAC;IAC5C,IAAI,MAAM,CAAC,eAAe,KAAK,IAAI,EAAE,CAAC;QACpC,GAAG,CAAC,KAAK,CAAC,8CAA8C,MAAM,CAAC,eAAe,IAAI,CAAC,CAAC;IACtF,CAAC;IACD,GAAG,CAAC,KAAK,CAAC,0CAA0C,aAAa,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;AAC3F,CAAC;AAED,SAAS,QAAQ,CAAC,MAAwB;IACxC,IAAI,MAAM,CAAC,UAAU;QAAE,OAAO,eAAe,CAAC;IAC9C,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,mCAAmC,CAAC;AAC1E,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { type ClientSource } from "../http/ClientIdentification.js";
|
|
2
|
+
export interface DossierFetchOptions {
|
|
3
|
+
readonly baseUrl: string;
|
|
4
|
+
readonly apiKey: string;
|
|
5
|
+
readonly tenantId: string;
|
|
6
|
+
readonly dossierId: string;
|
|
7
|
+
readonly allowInsecureLoopback?: boolean;
|
|
8
|
+
readonly fetch?: typeof fetch;
|
|
9
|
+
readonly timeoutMs?: number;
|
|
10
|
+
readonly source?: ClientSource;
|
|
11
|
+
}
|
|
12
|
+
/** What the proof bundle says about the record, for a person to read. */
|
|
13
|
+
export interface SignedDossierSummary {
|
|
14
|
+
readonly dossierId: string;
|
|
15
|
+
readonly outcome: string | null;
|
|
16
|
+
readonly generatedAt: string | null;
|
|
17
|
+
readonly algorithm: string | null;
|
|
18
|
+
readonly keyId: string | null;
|
|
19
|
+
readonly issuedAt: string | null;
|
|
20
|
+
readonly artifacts: number;
|
|
21
|
+
/** The issuer tier the record carries, `provisional_anonymous` for a workspace without an account. */
|
|
22
|
+
readonly issuerTier: string | null;
|
|
23
|
+
readonly bytes: number;
|
|
24
|
+
}
|
|
25
|
+
export declare class DossierFetchError extends Error {
|
|
26
|
+
readonly code: "DOSSIER_UNAVAILABLE" | "DOSSIER_REFUSED" | "DOSSIER_NOT_FOUND" | "DOSSIER_RESPONSE_INVALID" | "DOSSIER_TIMED_OUT";
|
|
27
|
+
readonly status: number | null;
|
|
28
|
+
constructor(code: "DOSSIER_UNAVAILABLE" | "DOSSIER_REFUSED" | "DOSSIER_NOT_FOUND" | "DOSSIER_RESPONSE_INVALID" | "DOSSIER_TIMED_OUT", status: number | null);
|
|
29
|
+
}
|
|
30
|
+
/** The summary of one `GET /v1/protocol/dossiers/{id}` body; null when it holds no signed payload. */
|
|
31
|
+
export declare function summarizeDossier(body: unknown, bytes: number): SignedDossierSummary | null;
|
|
32
|
+
/** Fetches the signed record with the caller's key and summarizes its proof. */
|
|
33
|
+
export declare function fetchSignedDossier(options: DossierFetchOptions): Promise<{
|
|
34
|
+
readonly summary: SignedDossierSummary;
|
|
35
|
+
readonly body: unknown;
|
|
36
|
+
}>;
|
|
37
|
+
/** The signed record, in three lines a person can read. */
|
|
38
|
+
export declare function printSignedDossier(summary: SignedDossierSummary, options?: {
|
|
39
|
+
readonly out?: {
|
|
40
|
+
write(chunk: string): unknown;
|
|
41
|
+
};
|
|
42
|
+
}): void;
|
|
43
|
+
//# sourceMappingURL=DossierReport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DossierReport.d.ts","sourceRoot":"","sources":["../../src/report/DossierReport.ts"],"names":[],"mappings":"AAYA,OAAO,EAAa,KAAK,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAE/E,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IACzC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IAC9B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC;CAChC;AAED,yEAAyE;AACzE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,sGAAsG;IACtG,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,qBAAa,iBAAkB,SAAQ,KAAK;aAExB,IAAI,EAChB,qBAAqB,GACrB,iBAAiB,GACjB,mBAAmB,GACnB,0BAA0B,GAC1B,mBAAmB;aACP,MAAM,EAAE,MAAM,GAAG,IAAI;gBANrB,IAAI,EAChB,qBAAqB,GACrB,iBAAiB,GACjB,mBAAmB,GACnB,0BAA0B,GAC1B,mBAAmB,EACP,MAAM,EAAE,MAAM,GAAG,IAAI;CAKxC;AAmBD,sGAAsG;AACtG,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,oBAAoB,GAAG,IAAI,CAqB1F;AAED,gFAAgF;AAChF,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC;IAAE,QAAQ,CAAC,OAAO,EAAE,oBAAoB,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC,CAwD7E;AAED,2DAA2D;AAC3D,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,oBAAoB,EAC7B,OAAO,GAAE;IAAE,QAAQ,CAAC,GAAG,CAAC,EAAE;QAAE,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAA;CAAO,GACjE,IAAI,CAaN"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The signed record itself, at the end of a run. `enforce-and-bind` names
|
|
3
|
+
* the Decision Dossier it left; this fetches that record with the caller's
|
|
4
|
+
* key from `GET /v1/protocol/dossiers/{id}`, reads the proof bundle it
|
|
5
|
+
* carries, and prints what a person needs to know it is signed: the
|
|
6
|
+
* algorithm, the key, when it was issued, how many artifacts it covers and
|
|
7
|
+
* under which issuer tier. The signature check itself is `@decionis/verify`'s
|
|
8
|
+
* (the `decionis:verify` script, or the public page); this shows the proof,
|
|
9
|
+
* it does not re-implement it.
|
|
10
|
+
*/
|
|
11
|
+
import { AuthorityBaseUrl } from "../http/AuthorityBaseUrl.js";
|
|
12
|
+
import { BoundedResponseBody } from "../http/BoundedResponseBody.js";
|
|
13
|
+
import { userAgent } from "../http/ClientIdentification.js";
|
|
14
|
+
export class DossierFetchError extends Error {
|
|
15
|
+
code;
|
|
16
|
+
status;
|
|
17
|
+
constructor(code, status) {
|
|
18
|
+
super(code);
|
|
19
|
+
this.code = code;
|
|
20
|
+
this.status = status;
|
|
21
|
+
this.name = "DossierFetchError";
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/** A signed record with its inputs snapshot can be large; the reader's own bound. */
|
|
25
|
+
const MAX_RESPONSE_BYTES = 2 * 1024 * 1024;
|
|
26
|
+
const DEFAULT_TIMEOUT_MS = 10_000;
|
|
27
|
+
const DOSSIER_ID_PATTERN = /^[\w-]{1,200}$/;
|
|
28
|
+
function record(value) {
|
|
29
|
+
return typeof value === "object" && value !== null && !Array.isArray(value)
|
|
30
|
+
? value
|
|
31
|
+
: null;
|
|
32
|
+
}
|
|
33
|
+
function text(value) {
|
|
34
|
+
return typeof value === "string" && value.length > 0 && value.length <= 500 ? value : null;
|
|
35
|
+
}
|
|
36
|
+
/** The summary of one `GET /v1/protocol/dossiers/{id}` body; null when it holds no signed payload. */
|
|
37
|
+
export function summarizeDossier(body, bytes) {
|
|
38
|
+
const payload = record(record(record(body)?.["dossier"])?.["dossier_payload"]);
|
|
39
|
+
if (payload === null)
|
|
40
|
+
return null;
|
|
41
|
+
const dossierId = text(payload["dossier_id"]);
|
|
42
|
+
if (dossierId === null)
|
|
43
|
+
return null;
|
|
44
|
+
const routing = record(payload["routing_decision"]);
|
|
45
|
+
const bundle = record(record(payload["integrity"])?.["proof_bundle"]);
|
|
46
|
+
const artifacts = bundle?.["artifacts"];
|
|
47
|
+
const portable = record(payload["portable_artifact"]);
|
|
48
|
+
const issuer = record(portable?.["issuer_context"]) ?? record(payload["issuer_context"]) ?? null;
|
|
49
|
+
return {
|
|
50
|
+
dossierId,
|
|
51
|
+
outcome: text(routing?.["outcome"]),
|
|
52
|
+
generatedAt: text(payload["generated_at"]),
|
|
53
|
+
algorithm: text(bundle?.["algorithm"]),
|
|
54
|
+
keyId: text(bundle?.["key_id"]),
|
|
55
|
+
issuedAt: text(bundle?.["issued_at"]),
|
|
56
|
+
artifacts: Array.isArray(artifacts) ? artifacts.length : 0,
|
|
57
|
+
issuerTier: text(issuer?.["tier"]),
|
|
58
|
+
bytes,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/** Fetches the signed record with the caller's key and summarizes its proof. */
|
|
62
|
+
export async function fetchSignedDossier(options) {
|
|
63
|
+
if (!DOSSIER_ID_PATTERN.test(options.dossierId)) {
|
|
64
|
+
throw new DossierFetchError("DOSSIER_RESPONSE_INVALID", null);
|
|
65
|
+
}
|
|
66
|
+
const baseUrl = AuthorityBaseUrl.normalize(options.baseUrl, options.allowInsecureLoopback ?? false);
|
|
67
|
+
const url = `${baseUrl}/v1/protocol/dossiers/${encodeURIComponent(options.dossierId)}?org_id=${encodeURIComponent(options.tenantId)}`;
|
|
68
|
+
const doFetch = options.fetch ?? fetch;
|
|
69
|
+
const controller = new AbortController();
|
|
70
|
+
const timer = setTimeout(() => controller.abort(), options.timeoutMs ?? DEFAULT_TIMEOUT_MS);
|
|
71
|
+
let response;
|
|
72
|
+
try {
|
|
73
|
+
response = await doFetch(url, {
|
|
74
|
+
method: "GET",
|
|
75
|
+
headers: {
|
|
76
|
+
accept: "application/json",
|
|
77
|
+
authorization: `Bearer ${options.apiKey}`,
|
|
78
|
+
"user-agent": userAgent(options.source),
|
|
79
|
+
},
|
|
80
|
+
redirect: "error",
|
|
81
|
+
signal: controller.signal,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
clearTimeout(timer);
|
|
86
|
+
throw new DossierFetchError(controller.signal.aborted ? "DOSSIER_TIMED_OUT" : "DOSSIER_UNAVAILABLE", null);
|
|
87
|
+
}
|
|
88
|
+
let raw;
|
|
89
|
+
try {
|
|
90
|
+
raw = await BoundedResponseBody.read(response, MAX_RESPONSE_BYTES);
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
raw = null;
|
|
94
|
+
}
|
|
95
|
+
finally {
|
|
96
|
+
clearTimeout(timer);
|
|
97
|
+
}
|
|
98
|
+
if (response.status === 404)
|
|
99
|
+
throw new DossierFetchError("DOSSIER_NOT_FOUND", 404);
|
|
100
|
+
if (response.status === 401 || response.status === 403) {
|
|
101
|
+
throw new DossierFetchError("DOSSIER_REFUSED", response.status);
|
|
102
|
+
}
|
|
103
|
+
if (response.status >= 500)
|
|
104
|
+
throw new DossierFetchError("DOSSIER_UNAVAILABLE", response.status);
|
|
105
|
+
if (response.status !== 200 || raw === null) {
|
|
106
|
+
throw new DossierFetchError("DOSSIER_RESPONSE_INVALID", response.status);
|
|
107
|
+
}
|
|
108
|
+
let body;
|
|
109
|
+
try {
|
|
110
|
+
body = JSON.parse(raw);
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
throw new DossierFetchError("DOSSIER_RESPONSE_INVALID", response.status);
|
|
114
|
+
}
|
|
115
|
+
const summary = summarizeDossier(body, Buffer.byteLength(raw, "utf8"));
|
|
116
|
+
if (summary === null)
|
|
117
|
+
throw new DossierFetchError("DOSSIER_RESPONSE_INVALID", response.status);
|
|
118
|
+
return { summary, body };
|
|
119
|
+
}
|
|
120
|
+
/** The signed record, in three lines a person can read. */
|
|
121
|
+
export function printSignedDossier(summary, options = {}) {
|
|
122
|
+
const out = options.out ?? process.stdout;
|
|
123
|
+
const signed = summary.keyId === null
|
|
124
|
+
? "unsigned record"
|
|
125
|
+
: `${summary.algorithm ?? "signed"} by key ${summary.keyId}${summary.issuedAt === null ? "" : ` at ${summary.issuedAt}`}`;
|
|
126
|
+
out.write(`signed dossier: ${summary.dossierId} (${String(summary.bytes)} bytes${summary.outcome === null ? "" : `, ${summary.outcome}`})\n`);
|
|
127
|
+
out.write(` ${signed}, ${String(summary.artifacts)} signed artifact(s)\n`);
|
|
128
|
+
out.write(` issuer: ${summary.issuerTier ?? "not stated"}${summary.issuerTier === "provisional_anonymous" ? " (a workspace without an account; claim it to keep it)" : ""}\n`);
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=DossierReport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DossierReport.js","sourceRoot":"","sources":["../../src/report/DossierReport.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How an example ends. A local run ends with its verdict and one line that
|
|
3
|
+
* says what the hosted path adds. A hosted run ends with what Decionis
|
|
4
|
+
* decided, the Decision Dossier it left, the page that verifies it (when
|
|
5
|
+
* the authority attached one), the command that verifies it offline, and
|
|
6
|
+
* the signed record itself, fetched with the run's own key and shown by its
|
|
7
|
+
* proof: the thing the local path cannot produce.
|
|
8
|
+
*/
|
|
9
|
+
import type { HostedGate } from "../decision/CreateGate.js";
|
|
10
|
+
import type { GateDecision } from "../decision/DecisionAuthority.js";
|
|
11
|
+
import { type DecisionReportOptions } from "./DecisionReport.js";
|
|
12
|
+
export interface HostedOutcomeOptions extends DecisionReportOptions {
|
|
13
|
+
/** Whether a local run prints the line about the hosted path; on by default. */
|
|
14
|
+
readonly hint?: boolean;
|
|
15
|
+
}
|
|
16
|
+
export declare const HOSTED_HINT = "hint: DECIONIS_HOSTED=1 has Decionis evaluate the same intent and sign a Decision Dossier; no account, no card, one variable";
|
|
17
|
+
export declare function printHostedOutcome(gate: HostedGate, decision: GateDecision, options?: HostedOutcomeOptions): Promise<void>;
|
|
18
|
+
//# sourceMappingURL=HostedOutcome.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HostedOutcome.d.ts","sourceRoot":"","sources":["../../src/report/HostedOutcome.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAiB,KAAK,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAGhF,MAAM,WAAW,oBAAqB,SAAQ,qBAAqB;IACjE,gFAAgF;IAChF,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,eAAO,MAAM,WAAW,iIACwG,CAAC;AAEjI,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,UAAU,EAChB,QAAQ,EAAE,YAAY,EACtB,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,IAAI,CAAC,CAgBf"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { printDecision } from "./DecisionReport.js";
|
|
2
|
+
import { DossierFetchError, printSignedDossier } from "./DossierReport.js";
|
|
3
|
+
export const HOSTED_HINT = "hint: DECIONIS_HOSTED=1 has Decionis evaluate the same intent and sign a Decision Dossier; no account, no card, one variable";
|
|
4
|
+
export async function printHostedOutcome(gate, decision, options = {}) {
|
|
5
|
+
const out = options.out ?? process.stdout;
|
|
6
|
+
if (gate.credentials === null || gate.fetchDossier === null) {
|
|
7
|
+
if (options.hint !== false)
|
|
8
|
+
out.write(`${HOSTED_HINT}\n`);
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
printDecision(decision, options);
|
|
12
|
+
const dossierId = decision.hosted?.dossierId ?? null;
|
|
13
|
+
if (dossierId === null)
|
|
14
|
+
return;
|
|
15
|
+
try {
|
|
16
|
+
const { summary } = await gate.fetchDossier(dossierId);
|
|
17
|
+
printSignedDossier(summary, { out });
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
const code = error instanceof DossierFetchError ? error.code : "DOSSIER_UNAVAILABLE";
|
|
21
|
+
out.write(`signed dossier: not fetched (${code}); the record is still there under your key\n`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=HostedOutcome.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HostedOutcome.js","sourceRoot":"","sources":["../../src/report/HostedOutcome.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,aAAa,EAA8B,MAAM,qBAAqB,CAAC;AAChF,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAO3E,MAAM,CAAC,MAAM,WAAW,GACtB,8HAA8H,CAAC;AAEjI,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,IAAgB,EAChB,QAAsB,EACtB,UAAgC,EAAE;IAElC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;IAC1C,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI,IAAI,IAAI,CAAC,YAAY,KAAK,IAAI,EAAE,CAAC;QAC5D,IAAI,OAAO,CAAC,IAAI,KAAK,KAAK;YAAE,GAAG,CAAC,KAAK,CAAC,GAAG,WAAW,IAAI,CAAC,CAAC;QAC1D,OAAO;IACT,CAAC;IACD,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACjC,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,EAAE,SAAS,IAAI,IAAI,CAAC;IACrD,IAAI,SAAS,KAAK,IAAI;QAAE,OAAO;IAC/B,IAAI,CAAC;QACH,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;QACvD,kBAAkB,CAAC,OAAO,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;IACvC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,GAAG,KAAK,YAAY,iBAAiB,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,qBAAqB,CAAC;QACrF,GAAG,CAAC,KAAK,CAAC,gCAAgC,IAAI,+CAA+C,CAAC,CAAC;IACjG,CAAC;AACH,CAAC"}
|