@decionis/agent-safe-pipeline 0.1.2

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.
Files changed (72) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +4 -0
  3. package/README.md +60 -0
  4. package/dist/Index.d.ts +14 -0
  5. package/dist/Index.d.ts.map +1 -0
  6. package/dist/Index.js +14 -0
  7. package/dist/Index.js.map +1 -0
  8. package/dist/approval/PresenceApprovalCoordinator.d.ts +18 -0
  9. package/dist/approval/PresenceApprovalCoordinator.d.ts.map +1 -0
  10. package/dist/approval/PresenceApprovalCoordinator.js +105 -0
  11. package/dist/approval/PresenceApprovalCoordinator.js.map +1 -0
  12. package/dist/decision/DecionisGate.d.ts +18 -0
  13. package/dist/decision/DecionisGate.d.ts.map +1 -0
  14. package/dist/decision/DecionisGate.js +108 -0
  15. package/dist/decision/DecionisGate.js.map +1 -0
  16. package/dist/decision/DecisionAuthority.d.ts +29 -0
  17. package/dist/decision/DecisionAuthority.d.ts.map +1 -0
  18. package/dist/decision/DecisionAuthority.js +15 -0
  19. package/dist/decision/DecisionAuthority.js.map +1 -0
  20. package/dist/decision/FixtureDecisionAuthority.d.ts +32 -0
  21. package/dist/decision/FixtureDecisionAuthority.d.ts.map +1 -0
  22. package/dist/decision/FixtureDecisionAuthority.js +117 -0
  23. package/dist/decision/FixtureDecisionAuthority.js.map +1 -0
  24. package/dist/decision/ImmutableGateDecision.d.ts +3 -0
  25. package/dist/decision/ImmutableGateDecision.d.ts.map +1 -0
  26. package/dist/decision/ImmutableGateDecision.js +8 -0
  27. package/dist/decision/ImmutableGateDecision.js.map +1 -0
  28. package/dist/execution/ActionRegistry.d.ts +22 -0
  29. package/dist/execution/ActionRegistry.d.ts.map +1 -0
  30. package/dist/execution/ActionRegistry.js +41 -0
  31. package/dist/execution/ActionRegistry.js.map +1 -0
  32. package/dist/execution/AuthorizationVerifier.d.ts +28 -0
  33. package/dist/execution/AuthorizationVerifier.d.ts.map +1 -0
  34. package/dist/execution/AuthorizationVerifier.js +88 -0
  35. package/dist/execution/AuthorizationVerifier.js.map +1 -0
  36. package/dist/execution/ReplayStore.d.ts +10 -0
  37. package/dist/execution/ReplayStore.d.ts.map +1 -0
  38. package/dist/execution/ReplayStore.js +28 -0
  39. package/dist/execution/ReplayStore.js.map +1 -0
  40. package/dist/execution/SafeExecutor.d.ts +25 -0
  41. package/dist/execution/SafeExecutor.d.ts.map +1 -0
  42. package/dist/execution/SafeExecutor.js +73 -0
  43. package/dist/execution/SafeExecutor.js.map +1 -0
  44. package/dist/http/AuthorityBaseUrl.d.ts +4 -0
  45. package/dist/http/AuthorityBaseUrl.d.ts.map +1 -0
  46. package/dist/http/AuthorityBaseUrl.js +22 -0
  47. package/dist/http/AuthorityBaseUrl.js.map +1 -0
  48. package/dist/http/BoundedResponseBody.d.ts +4 -0
  49. package/dist/http/BoundedResponseBody.d.ts.map +1 -0
  50. package/dist/http/BoundedResponseBody.js +33 -0
  51. package/dist/http/BoundedResponseBody.js.map +1 -0
  52. package/dist/intent/CanonicalIntentHasher.d.ts +20 -0
  53. package/dist/intent/CanonicalIntentHasher.d.ts.map +1 -0
  54. package/dist/intent/CanonicalIntentHasher.js +162 -0
  55. package/dist/intent/CanonicalIntentHasher.js.map +1 -0
  56. package/dist/intent/ExecutionIntent.d.ts +96 -0
  57. package/dist/intent/ExecutionIntent.d.ts.map +1 -0
  58. package/dist/intent/ExecutionIntent.js +59 -0
  59. package/dist/intent/ExecutionIntent.js.map +1 -0
  60. package/dist/intent/IntentCapture.d.ts +17 -0
  61. package/dist/intent/IntentCapture.d.ts.map +1 -0
  62. package/dist/intent/IntentCapture.js +40 -0
  63. package/dist/intent/IntentCapture.js.map +1 -0
  64. package/dist/intent/JsonValue.d.ts +11 -0
  65. package/dist/intent/JsonValue.d.ts.map +1 -0
  66. package/dist/intent/JsonValue.js +11 -0
  67. package/dist/intent/JsonValue.js.map +1 -0
  68. package/dist/shadow/ShadowPipeline.d.ts +13 -0
  69. package/dist/shadow/ShadowPipeline.d.ts.map +1 -0
  70. package/dist/shadow/ShadowPipeline.js +14 -0
  71. package/dist/shadow/ShadowPipeline.js.map +1 -0
  72. package/package.json +57 -0
@@ -0,0 +1,32 @@
1
+ import { type KeyObject } from "node:crypto";
2
+ import type { CapturedIntent } from "../intent/ExecutionIntent.js";
3
+ import type { AuthorizationVerifier, VerifiedAuthorization } from "../execution/AuthorizationVerifier.js";
4
+ import type { ReplayStore } from "../execution/ReplayStore.js";
5
+ import type { DecisionAuthority, DecisionEvidence, DecisionVerdict, GateDecision } from "./DecisionAuthority.js";
6
+ export type FixtureVerdictResolver = (intent: CapturedIntent, evidence?: DecisionEvidence) => DecisionVerdict;
7
+ export interface FixtureAuthorityPair {
8
+ readonly authority: FixtureDecisionAuthority;
9
+ readonly verifier: FixtureAuthorizationVerifier;
10
+ }
11
+ export interface UnsafeFixtureAuthorityOptions {
12
+ readonly unsafeAllowDevelopmentFixture: true;
13
+ readonly privateKey?: KeyObject;
14
+ readonly keyId?: string;
15
+ readonly replayStore?: ReplayStore;
16
+ }
17
+ export declare class FixtureDecisionAuthority implements DecisionAuthority {
18
+ private readonly resolveVerdict;
19
+ private readonly privateKey;
20
+ private readonly keyId;
21
+ constructor(resolveVerdict: FixtureVerdictResolver, options: UnsafeFixtureAuthorityOptions);
22
+ publicKey(): KeyObject;
23
+ evaluate(intent: CapturedIntent, evidence?: DecisionEvidence): Promise<GateDecision>;
24
+ }
25
+ export declare class FixtureAuthorizationVerifier implements AuthorizationVerifier {
26
+ private readonly publicKey;
27
+ private readonly replayStore;
28
+ constructor(publicKey: KeyObject, replayStore: ReplayStore, unsafeAllowDevelopmentFixture: true);
29
+ verifyAndConsume(captured: CapturedIntent, decision: GateDecision): Promise<VerifiedAuthorization | null>;
30
+ }
31
+ export declare function createFixtureAuthorityPair(resolver: FixtureVerdictResolver, options: UnsafeFixtureAuthorityOptions): FixtureAuthorityPair;
32
+ //# sourceMappingURL=FixtureDecisionAuthority.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FixtureDecisionAuthority.d.ts","sourceRoot":"","sources":["../../src/decision/FixtureDecisionAuthority.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoD,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAE/F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,KAAK,EACV,qBAAqB,EACrB,qBAAqB,EACtB,MAAM,uCAAuC,CAAC;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAE/D,OAAO,KAAK,EACV,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,YAAY,EACb,MAAM,wBAAwB,CAAC;AAGhC,MAAM,MAAM,sBAAsB,GAAG,CACnC,MAAM,EAAE,cAAc,EACtB,QAAQ,CAAC,EAAE,gBAAgB,KACxB,eAAe,CAAC;AAErB,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,SAAS,EAAE,wBAAwB,CAAC;IAC7C,QAAQ,CAAC,QAAQ,EAAE,4BAA4B,CAAC;CACjD;AAED,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,6BAA6B,EAAE,IAAI,CAAC;IAC7C,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,CAAC;IAChC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC;CACpC;AAED,qBAAa,wBAAyB,YAAW,iBAAiB;IAK9D,OAAO,CAAC,QAAQ,CAAC,cAAc;IAJjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAY;IACvC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;gBAGZ,cAAc,EAAE,sBAAsB,EACvD,OAAO,EAAE,6BAA6B;IAOjC,SAAS,IAAI,SAAS;IAIhB,QAAQ,CACnB,MAAM,EAAE,cAAc,EACtB,QAAQ,CAAC,EAAE,gBAAgB,GAC1B,OAAO,CAAC,YAAY,CAAC;CA+CzB;AAED,qBAAa,4BAA6B,YAAW,qBAAqB;IAEtE,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,WAAW;gBADX,SAAS,EAAE,SAAS,EACpB,WAAW,EAAE,WAAW,EACzC,6BAA6B,EAAE,IAAI;IAKxB,gBAAgB,CAC3B,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,YAAY,GACrB,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC;CAkCzC;AAED,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,sBAAsB,EAChC,OAAO,EAAE,6BAA6B,GACrC,oBAAoB,CAUtB"}
@@ -0,0 +1,117 @@
1
+ import { createPublicKey, generateKeyPairSync, randomUUID } from "node:crypto";
2
+ import { SignJWT, jwtVerify } from "jose";
3
+ import { InMemoryReplayStore } from "../execution/ReplayStore.js";
4
+ import { immutableGateDecision } from "./ImmutableGateDecision.js";
5
+ export class FixtureDecisionAuthority {
6
+ resolveVerdict;
7
+ privateKey;
8
+ keyId;
9
+ constructor(resolveVerdict, options) {
10
+ this.resolveVerdict = resolveVerdict;
11
+ assertDevelopmentFixtureAllowed(options.unsafeAllowDevelopmentFixture);
12
+ this.privateKey = options.privateKey ?? generateKeyPairSync("ed25519").privateKey;
13
+ this.keyId = options.keyId ?? "agent-safe-fixture";
14
+ }
15
+ publicKey() {
16
+ return createPublicKey(this.privateKey);
17
+ }
18
+ async evaluate(intent, evidence) {
19
+ const verdict = this.resolveVerdict(intent, evidence);
20
+ const decisionId = `fixture_${randomUUID()}`;
21
+ const dossierId = `fixture_dossier_${randomUUID()}`;
22
+ if (verdict !== "ALLOW") {
23
+ return immutableGateDecision({
24
+ verdict,
25
+ decisionId,
26
+ dossierId,
27
+ intentHash: intent.intentHash,
28
+ reasonCodes: [`FIXTURE_${verdict}`],
29
+ authorization: null,
30
+ failClosed: false,
31
+ });
32
+ }
33
+ const issuedAt = Math.floor(Date.now() / 1_000);
34
+ const expiresAt = Math.min(issuedAt + 60, Math.floor(new Date(intent.intent.expiresAt).valueOf() / 1_000));
35
+ const token = await new SignJWT({
36
+ decision_id: decisionId,
37
+ dossier_id: dossierId,
38
+ decision: "allow",
39
+ scope: "execute",
40
+ binding: { intent_hash: intent.intentHash },
41
+ })
42
+ .setProtectedHeader({ alg: "EdDSA", kid: this.keyId, typ: "JWT" })
43
+ .setIssuer("agent-safe-fixture")
44
+ .setAudience(`${intent.intent.downstreamTarget.system}:${intent.intent.downstreamTarget.operation}`)
45
+ .setJti(randomUUID())
46
+ .setIssuedAt(issuedAt)
47
+ .setNotBefore(issuedAt)
48
+ .setExpirationTime(expiresAt)
49
+ .sign(this.privateKey);
50
+ return immutableGateDecision({
51
+ verdict,
52
+ decisionId,
53
+ dossierId,
54
+ intentHash: intent.intentHash,
55
+ reasonCodes: ["FIXTURE_ALLOW"],
56
+ authorization: { token, expiresAt: new Date(expiresAt * 1_000).toISOString() },
57
+ failClosed: false,
58
+ });
59
+ }
60
+ }
61
+ export class FixtureAuthorizationVerifier {
62
+ publicKey;
63
+ replayStore;
64
+ constructor(publicKey, replayStore, unsafeAllowDevelopmentFixture) {
65
+ this.publicKey = publicKey;
66
+ this.replayStore = replayStore;
67
+ assertDevelopmentFixtureAllowed(unsafeAllowDevelopmentFixture);
68
+ }
69
+ async verifyAndConsume(captured, decision) {
70
+ if (decision.authorization === null || decision.dossierId === null)
71
+ return null;
72
+ try {
73
+ const audience = `${captured.intent.downstreamTarget.system}:${captured.intent.downstreamTarget.operation}`;
74
+ const { payload } = await jwtVerify(decision.authorization.token, this.publicKey, {
75
+ algorithms: ["EdDSA"],
76
+ issuer: "agent-safe-fixture",
77
+ audience,
78
+ });
79
+ const binding = payload.binding;
80
+ if (payload.decision !== "allow" ||
81
+ payload.scope !== "execute" ||
82
+ payload.decision_id !== decision.decisionId ||
83
+ payload.dossier_id !== decision.dossierId ||
84
+ binding?.intent_hash !== captured.intentHash ||
85
+ typeof payload.jti !== "string" ||
86
+ typeof payload.exp !== "number") {
87
+ return null;
88
+ }
89
+ const expiresAt = new Date(payload.exp * 1_000);
90
+ if (!(await this.replayStore.claim(payload.jti, expiresAt)))
91
+ return null;
92
+ return Object.freeze({
93
+ decisionId: decision.decisionId,
94
+ dossierId: decision.dossierId,
95
+ grantId: payload.jti,
96
+ intentHash: captured.intentHash,
97
+ expiresAt: expiresAt.toISOString(),
98
+ });
99
+ }
100
+ catch {
101
+ return null;
102
+ }
103
+ }
104
+ }
105
+ export function createFixtureAuthorityPair(resolver, options) {
106
+ const authority = new FixtureDecisionAuthority(resolver, options);
107
+ return {
108
+ authority,
109
+ verifier: new FixtureAuthorizationVerifier(authority.publicKey(), options.replayStore ?? new InMemoryReplayStore(), true),
110
+ };
111
+ }
112
+ function assertDevelopmentFixtureAllowed(explicitlyAllowed) {
113
+ if (!explicitlyAllowed || process.env.NODE_ENV === "production") {
114
+ throw new Error("FIXTURE_AUTHORITY_FORBIDDEN");
115
+ }
116
+ }
117
+ //# sourceMappingURL=FixtureDecisionAuthority.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FixtureDecisionAuthority.js","sourceRoot":"","sources":["../../src/decision/FixtureDecisionAuthority.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { GateDecision } from "./DecisionAuthority.js";
2
+ export declare function immutableGateDecision(decision: GateDecision): GateDecision;
3
+ //# sourceMappingURL=ImmutableGateDecision.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ImmutableGateDecision.d.ts","sourceRoot":"","sources":["../../src/decision/ImmutableGateDecision.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE3D,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,YAAY,GAAG,YAAY,CAO1E"}
@@ -0,0 +1,8 @@
1
+ export function immutableGateDecision(decision) {
2
+ return Object.freeze({
3
+ ...decision,
4
+ reasonCodes: Object.freeze([...decision.reasonCodes]),
5
+ authorization: decision.authorization === null ? null : Object.freeze({ ...decision.authorization }),
6
+ });
7
+ }
8
+ //# sourceMappingURL=ImmutableGateDecision.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ImmutableGateDecision.js","sourceRoot":"","sources":["../../src/decision/ImmutableGateDecision.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,qBAAqB,CAAC,QAAsB;IAC1D,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,GAAG,QAAQ;QACX,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC;QACrD,aAAa,EACX,QAAQ,CAAC,aAAa,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,QAAQ,CAAC,aAAa,EAAE,CAAC;KACxF,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,22 @@
1
+ import type { z } from "zod";
2
+ import type { CapturedIntent } from "../intent/ExecutionIntent.js";
3
+ import type { VerifiedAuthorization } from "./AuthorizationVerifier.js";
4
+ export interface ActionExecutionContext<TParameters> {
5
+ readonly intent: CapturedIntent;
6
+ readonly parameters: TParameters;
7
+ readonly authorization: VerifiedAuthorization;
8
+ }
9
+ export interface ActionHandler<TParameters, TResult> {
10
+ readonly parametersSchema: z.ZodType<TParameters>;
11
+ execute(context: ActionExecutionContext<TParameters>): Promise<TResult> | TResult;
12
+ }
13
+ export declare class ActionRegistry {
14
+ private readonly actions;
15
+ private sealed;
16
+ register<TParameters, TResult>(action: string, handler: ActionHandler<TParameters, TResult>): this;
17
+ seal(): this;
18
+ has(action: string): boolean;
19
+ validate(captured: CapturedIntent): void;
20
+ execute(captured: CapturedIntent, authorization: VerifiedAuthorization): Promise<unknown>;
21
+ }
22
+ //# sourceMappingURL=ActionRegistry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ActionRegistry.d.ts","sourceRoot":"","sources":["../../src/execution/ActionRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAExE,MAAM,WAAW,sBAAsB,CAAC,WAAW;IACjD,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,UAAU,EAAE,WAAW,CAAC;IACjC,QAAQ,CAAC,aAAa,EAAE,qBAAqB,CAAC;CAC/C;AAED,MAAM,WAAW,aAAa,CAAC,WAAW,EAAE,OAAO;IACjD,QAAQ,CAAC,gBAAgB,EAAE,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAClD,OAAO,CAAC,OAAO,EAAE,sBAAsB,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;CACnF;AAOD,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuC;IAC/D,OAAO,CAAC,MAAM,CAAS;IAEhB,QAAQ,CAAC,WAAW,EAAE,OAAO,EAClC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,aAAa,CAAC,WAAW,EAAE,OAAO,CAAC,GAC3C,IAAI;IAOA,IAAI,IAAI,IAAI;IAKZ,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAI5B,QAAQ,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI;IASlC,OAAO,CAClB,QAAQ,EAAE,cAAc,EACxB,aAAa,EAAE,qBAAqB,GACnC,OAAO,CAAC,OAAO,CAAC;CAQpB"}
@@ -0,0 +1,41 @@
1
+ export class ActionRegistry {
2
+ actions = new Map();
3
+ sealed = false;
4
+ register(action, handler) {
5
+ if (this.sealed)
6
+ throw new Error("ACTION_REGISTRY_SEALED");
7
+ if (this.actions.has(action))
8
+ throw new Error("ACTION_ALREADY_REGISTERED");
9
+ this.actions.set(action, handler);
10
+ return this;
11
+ }
12
+ seal() {
13
+ this.sealed = true;
14
+ return this;
15
+ }
16
+ has(action) {
17
+ return this.actions.has(action);
18
+ }
19
+ validate(captured) {
20
+ if (!this.sealed)
21
+ throw new Error("ACTION_REGISTRY_NOT_SEALED");
22
+ const handler = this.actions.get(captured.intent.action);
23
+ if (!handler)
24
+ throw new Error("ACTION_NOT_REGISTERED");
25
+ if (!handler.parametersSchema.safeParse(captured.intent.parameters).success) {
26
+ throw new Error("ACTION_PARAMETERS_INVALID");
27
+ }
28
+ }
29
+ async execute(captured, authorization) {
30
+ if (!this.sealed)
31
+ throw new Error("ACTION_REGISTRY_NOT_SEALED");
32
+ const handler = this.actions.get(captured.intent.action);
33
+ if (!handler)
34
+ throw new Error("ACTION_NOT_REGISTERED");
35
+ const result = handler.parametersSchema.safeParse(captured.intent.parameters);
36
+ if (!result.success)
37
+ throw new Error("ACTION_PARAMETERS_INVALID");
38
+ return handler.execute({ intent: captured, parameters: result.data, authorization });
39
+ }
40
+ }
41
+ //# sourceMappingURL=ActionRegistry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ActionRegistry.js","sourceRoot":"","sources":["../../src/execution/ActionRegistry.ts"],"names":[],"mappings":"AAoBA,MAAM,OAAO,cAAc;IACR,OAAO,GAAG,IAAI,GAAG,EAA4B,CAAC;IACvD,MAAM,GAAG,KAAK,CAAC;IAEhB,QAAQ,CACb,MAAc,EACd,OAA4C;QAE5C,IAAI,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAC3D,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAC3E,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,OAA2B,CAAC,CAAC;QACtD,OAAO,IAAI,CAAC;IACd,CAAC;IAEM,IAAI;QACT,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,OAAO,IAAI,CAAC;IACd,CAAC;IAEM,GAAG,CAAC,MAAc;QACvB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAClC,CAAC;IAEM,QAAQ,CAAC,QAAwB;QACtC,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAChE,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACzD,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;QACvD,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC;YAC5E,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,OAAO,CAClB,QAAwB,EACxB,aAAoC;QAEpC,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAChE,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACzD,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;QACvD,MAAM,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAC9E,IAAI,CAAC,MAAM,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAClE,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,CAAC,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC;IACvF,CAAC;CACF"}
@@ -0,0 +1,28 @@
1
+ import type { CapturedIntent } from "../intent/ExecutionIntent.js";
2
+ import type { GateDecision } from "../decision/DecisionAuthority.js";
3
+ export interface VerifiedAuthorization {
4
+ readonly decisionId: string;
5
+ readonly dossierId: string;
6
+ readonly grantId: string;
7
+ readonly intentHash: string;
8
+ readonly expiresAt: string;
9
+ }
10
+ export interface AuthorizationVerifier {
11
+ verifyAndConsume(captured: CapturedIntent, decision: GateDecision): Promise<VerifiedAuthorization | null>;
12
+ }
13
+ export interface DecionisGrantVerifierOptions {
14
+ readonly baseUrl: string;
15
+ readonly apiKey: string;
16
+ readonly timeoutMs?: number;
17
+ readonly fetch?: typeof fetch;
18
+ readonly allowInsecureLoopback?: boolean;
19
+ }
20
+ export declare class DecionisGrantVerifier implements AuthorizationVerifier {
21
+ private readonly baseUrl;
22
+ private readonly apiKey;
23
+ private readonly timeoutMs;
24
+ private readonly fetchImpl;
25
+ constructor(options: DecionisGrantVerifierOptions);
26
+ verifyAndConsume(captured: CapturedIntent, decision: GateDecision): Promise<VerifiedAuthorization | null>;
27
+ }
28
+ //# sourceMappingURL=AuthorizationVerifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthorizationVerifier.d.ts","sourceRoot":"","sources":["../../src/execution/AuthorizationVerifier.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAErE,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,qBAAqB;IACpC,gBAAgB,CACd,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,YAAY,GACrB,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAAC;CAC1C;AAmBD,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IAC9B,QAAQ,CAAC,qBAAqB,CAAC,EAAE,OAAO,CAAC;CAC1C;AAED,qBAAa,qBAAsB,YAAW,qBAAqB;IACjE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;gBAEtB,OAAO,EAAE,4BAA4B;IAU3C,gBAAgB,CAC3B,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,YAAY,GACrB,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC;CA0DzC"}
@@ -0,0 +1,88 @@
1
+ import { z } from "zod";
2
+ import { AuthorityBaseUrl } from "../http/AuthorityBaseUrl.js";
3
+ import { BoundedResponseBody } from "../http/BoundedResponseBody.js";
4
+ import { CanonicalIntentHasher } from "../intent/CanonicalIntentHasher.js";
5
+ const ConsumeResponseSchema = z
6
+ .object({
7
+ valid: z.literal(true),
8
+ claims: z
9
+ .object({
10
+ jti: z.string().min(1).max(200),
11
+ decision_id: z.string().min(1).max(200),
12
+ dossier_id: z.string().min(1).max(200),
13
+ exp: z.number().int().positive(),
14
+ binding: z.object({ intent_hash: z.string().regex(/^sha256:[0-9a-f]{64}$/) }).strict(),
15
+ })
16
+ .strict(),
17
+ })
18
+ .strict();
19
+ const MAX_RESPONSE_BYTES = 100 * 1024;
20
+ export class DecionisGrantVerifier {
21
+ baseUrl;
22
+ apiKey;
23
+ timeoutMs;
24
+ fetchImpl;
25
+ constructor(options) {
26
+ this.baseUrl = AuthorityBaseUrl.normalize(options.baseUrl, options.allowInsecureLoopback === true);
27
+ this.apiKey = options.apiKey;
28
+ this.timeoutMs = Math.min(Math.max(options.timeoutMs ?? 4_000, 1), 15_000);
29
+ this.fetchImpl = options.fetch ?? fetch;
30
+ }
31
+ async verifyAndConsume(captured, decision) {
32
+ if (decision.verdict !== "ALLOW" ||
33
+ decision.failClosed ||
34
+ decision.authorization === null ||
35
+ decision.dossierId === null ||
36
+ decision.intentHash !== captured.intentHash) {
37
+ return null;
38
+ }
39
+ const controller = new AbortController();
40
+ const timeout = setTimeout(() => controller.abort(), this.timeoutMs);
41
+ try {
42
+ const response = await this.fetchImpl(`${this.baseUrl}/v1/execution/consume-token`, {
43
+ method: "POST",
44
+ headers: {
45
+ authorization: `Bearer ${this.apiKey}`,
46
+ "content-type": "application/json",
47
+ },
48
+ body: JSON.stringify({
49
+ execution_token: decision.authorization.token,
50
+ intent_hash: captured.intentHash,
51
+ intent: CanonicalIntentHasher.bindingOf(captured.intent),
52
+ consumed_by: captured.intent.actor.id,
53
+ }),
54
+ signal: controller.signal,
55
+ });
56
+ if (!response.ok)
57
+ return null;
58
+ const text = await BoundedResponseBody.read(response, MAX_RESPONSE_BYTES);
59
+ if (text === null)
60
+ return null;
61
+ const parsed = ConsumeResponseSchema.parse(JSON.parse(text));
62
+ const claimExpiryMs = parsed.claims.exp * 1_000;
63
+ const decisionExpirySeconds = Math.floor(Date.parse(decision.authorization.expiresAt) / 1_000);
64
+ if (parsed.claims.binding.intent_hash !== captured.intentHash ||
65
+ parsed.claims.decision_id !== decision.decisionId ||
66
+ parsed.claims.dossier_id !== decision.dossierId ||
67
+ parsed.claims.exp !== decisionExpirySeconds ||
68
+ claimExpiryMs <= Date.now() ||
69
+ claimExpiryMs > Date.parse(captured.intent.expiresAt)) {
70
+ return null;
71
+ }
72
+ return Object.freeze({
73
+ decisionId: parsed.claims.decision_id,
74
+ dossierId: parsed.claims.dossier_id,
75
+ grantId: parsed.claims.jti,
76
+ intentHash: parsed.claims.binding.intent_hash,
77
+ expiresAt: new Date(parsed.claims.exp * 1_000).toISOString(),
78
+ });
79
+ }
80
+ catch {
81
+ return null;
82
+ }
83
+ finally {
84
+ clearTimeout(timeout);
85
+ }
86
+ }
87
+ }
88
+ //# sourceMappingURL=AuthorizationVerifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthorizationVerifier.js","sourceRoot":"","sources":["../../src/execution/AuthorizationVerifier.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export interface ReplayStore {
2
+ claim(grantId: string, expiresAt: Date): Promise<boolean>;
3
+ }
4
+ export declare class InMemoryReplayStore implements ReplayStore {
5
+ private readonly maxEntries;
6
+ private readonly claims;
7
+ constructor(maxEntries?: number);
8
+ claim(grantId: string, expiresAt: Date): Promise<boolean>;
9
+ }
10
+ //# sourceMappingURL=ReplayStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReplayStore.d.ts","sourceRoot":"","sources":["../../src/execution/ReplayStore.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC3D;AAED,qBAAa,mBAAoB,YAAW,WAAW;IAGlC,OAAO,CAAC,QAAQ,CAAC,UAAU;IAF9C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA6B;gBAEhB,UAAU,SAAS;IAM1C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC;CAcvE"}
@@ -0,0 +1,28 @@
1
+ export class InMemoryReplayStore {
2
+ maxEntries;
3
+ claims = new Map();
4
+ constructor(maxEntries = 10_000) {
5
+ this.maxEntries = maxEntries;
6
+ if (!Number.isSafeInteger(maxEntries) || maxEntries < 1) {
7
+ throw new Error("REPLAY_STORE_CAPACITY_INVALID");
8
+ }
9
+ }
10
+ async claim(grantId, expiresAt) {
11
+ const now = Date.now();
12
+ const expiry = expiresAt.valueOf();
13
+ if (grantId.length === 0 || grantId.length > 200 || !Number.isFinite(expiry) || expiry <= now) {
14
+ return false;
15
+ }
16
+ for (const [key, expiry] of this.claims) {
17
+ if (expiry <= now)
18
+ this.claims.delete(key);
19
+ }
20
+ if (this.claims.has(grantId))
21
+ return false;
22
+ if (this.claims.size >= this.maxEntries)
23
+ throw new Error("REPLAY_STORE_CAPACITY_EXCEEDED");
24
+ this.claims.set(grantId, expiry);
25
+ return true;
26
+ }
27
+ }
28
+ //# sourceMappingURL=ReplayStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReplayStore.js","sourceRoot":"","sources":["../../src/execution/ReplayStore.ts"],"names":[],"mappings":"AAIA,MAAM,OAAO,mBAAmB;IAGM;IAFnB,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IAEpD,YAAoC,aAAa,MAAM;QAAnB,eAAU,GAAV,UAAU,CAAS;QACrD,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;YACxD,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,KAAK,CAAC,OAAe,EAAE,SAAe;QACjD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC;QACnC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,IAAI,GAAG,EAAE,CAAC;YAC9F,OAAO,KAAK,CAAC;QACf,CAAC;QACD,KAAK,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YACxC,IAAI,MAAM,IAAI,GAAG;gBAAE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7C,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC;YAAE,OAAO,KAAK,CAAC;QAC3C,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,UAAU;YAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;QAC3F,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACjC,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
@@ -0,0 +1,25 @@
1
+ import type { GateDecision } from "../decision/DecisionAuthority.js";
2
+ import type { CapturedIntent } from "../intent/ExecutionIntent.js";
3
+ import type { ActionRegistry } from "./ActionRegistry.js";
4
+ import type { AuthorizationVerifier, VerifiedAuthorization } from "./AuthorizationVerifier.js";
5
+ export type ExecutionBlockReason = "DECISION_NOT_ALLOW" | "INTENT_BINDING_MISMATCH" | "INTENT_CONFORMANCE_FAILED" | "AUTHORIZATION_MISSING" | "AUTHORIZATION_INVALID";
6
+ export type SafeExecutionResult<TResult = unknown> = {
7
+ readonly executed: true;
8
+ readonly result: TResult;
9
+ readonly authorization: VerifiedAuthorization;
10
+ } | {
11
+ readonly executed: false;
12
+ readonly reason: ExecutionBlockReason;
13
+ readonly result: null;
14
+ readonly authorization: null;
15
+ };
16
+ export declare class SafeExecutor {
17
+ private readonly registry;
18
+ private readonly verifier;
19
+ private readonly hasher;
20
+ constructor(registry: ActionRegistry, verifier: AuthorizationVerifier);
21
+ run<TResult = unknown>(captured: CapturedIntent, decision: GateDecision): Promise<SafeExecutionResult<TResult>>;
22
+ private intentConforms;
23
+ private static blocked;
24
+ }
25
+ //# sourceMappingURL=SafeExecutor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SafeExecutor.d.ts","sourceRoot":"","sources":["../../src/execution/SafeExecutor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAErE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAE/F,MAAM,MAAM,oBAAoB,GAC5B,oBAAoB,GACpB,yBAAyB,GACzB,2BAA2B,GAC3B,uBAAuB,GACvB,uBAAuB,CAAC;AAE5B,MAAM,MAAM,mBAAmB,CAAC,OAAO,GAAG,OAAO,IAC7C;IACE,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,aAAa,EAAE,qBAAqB,CAAC;CAC/C,GACD;IACE,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,oBAAoB,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;IACtB,QAAQ,CAAC,aAAa,EAAE,IAAI,CAAC;CAC9B,CAAC;AAEN,qBAAa,YAAY;IAIrB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAJ3B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA+B;gBAGnC,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,qBAAqB;IAGrC,GAAG,CAAC,OAAO,GAAG,OAAO,EAChC,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,YAAY,GACrB,OAAO,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC;IA8CxC,OAAO,CAAC,cAAc;IAetB,OAAO,CAAC,MAAM,CAAC,OAAO;CAGvB"}
@@ -0,0 +1,73 @@
1
+ import { CanonicalIntentHasher } from "../intent/CanonicalIntentHasher.js";
2
+ export class SafeExecutor {
3
+ registry;
4
+ verifier;
5
+ hasher = new CanonicalIntentHasher();
6
+ constructor(registry, verifier) {
7
+ this.registry = registry;
8
+ this.verifier = verifier;
9
+ }
10
+ async run(captured, decision) {
11
+ if (decision.verdict !== "ALLOW" || decision.failClosed) {
12
+ return SafeExecutor.blocked("DECISION_NOT_ALLOW");
13
+ }
14
+ if (decision.intentHash !== captured.intentHash) {
15
+ return SafeExecutor.blocked("INTENT_BINDING_MISMATCH");
16
+ }
17
+ if (decision.authorization === null) {
18
+ return SafeExecutor.blocked("AUTHORIZATION_MISSING");
19
+ }
20
+ if (!this.intentConforms(captured)) {
21
+ return SafeExecutor.blocked("INTENT_CONFORMANCE_FAILED");
22
+ }
23
+ this.registry.validate(captured);
24
+ let authorization;
25
+ try {
26
+ authorization = await this.verifier.verifyAndConsume(captured, decision);
27
+ }
28
+ catch {
29
+ return SafeExecutor.blocked("AUTHORIZATION_INVALID");
30
+ }
31
+ if (authorization === null)
32
+ return SafeExecutor.blocked("AUTHORIZATION_INVALID");
33
+ const authorizationExpiry = Date.parse(authorization.expiresAt);
34
+ if (authorization.decisionId !== decision.decisionId ||
35
+ authorization.dossierId !== decision.dossierId ||
36
+ authorization.grantId.length === 0 ||
37
+ authorization.intentHash !== captured.intentHash ||
38
+ Math.floor(authorizationExpiry / 1_000) !==
39
+ Math.floor(Date.parse(decision.authorization.expiresAt) / 1_000) ||
40
+ authorizationExpiry <= Date.now() ||
41
+ authorizationExpiry > Date.parse(captured.intent.expiresAt)) {
42
+ return SafeExecutor.blocked("AUTHORIZATION_INVALID");
43
+ }
44
+ if (!this.intentConforms(captured)) {
45
+ return SafeExecutor.blocked("INTENT_CONFORMANCE_FAILED");
46
+ }
47
+ let result;
48
+ try {
49
+ result = (await this.registry.execute(captured, authorization));
50
+ }
51
+ catch {
52
+ throw new Error("ACTION_EXECUTION_FAILED");
53
+ }
54
+ return { executed: true, result, authorization };
55
+ }
56
+ intentConforms(captured) {
57
+ let recomputed = null;
58
+ try {
59
+ recomputed = this.hasher.capture(captured.intent);
60
+ }
61
+ catch {
62
+ // Malformed runtime objects are non-conformant.
63
+ }
64
+ return (recomputed !== null &&
65
+ recomputed.intentHash === captured.intentHash &&
66
+ recomputed.canonicalIntent === captured.canonicalIntent &&
67
+ recomputed.byteLength === captured.byteLength);
68
+ }
69
+ static blocked(reason) {
70
+ return { executed: false, reason, result: null, authorization: null };
71
+ }
72
+ }
73
+ //# sourceMappingURL=SafeExecutor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SafeExecutor.js","sourceRoot":"","sources":["../../src/execution/SafeExecutor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare class AuthorityBaseUrl {
2
+ static normalize(value: string, allowInsecureLoopback?: boolean): string;
3
+ }
4
+ //# sourceMappingURL=AuthorityBaseUrl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthorityBaseUrl.d.ts","sourceRoot":"","sources":["../../src/http/AuthorityBaseUrl.ts"],"names":[],"mappings":"AAAA,qBAAa,gBAAgB;WACb,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,qBAAqB,UAAQ,GAAG,MAAM;CAsB9E"}
@@ -0,0 +1,22 @@
1
+ export class AuthorityBaseUrl {
2
+ static normalize(value, allowInsecureLoopback = false) {
3
+ const normalizedValue = value.trim();
4
+ const url = new URL(normalizedValue);
5
+ const loopback = url.hostname === "127.0.0.1" || url.hostname === "localhost" || url.hostname === "[::1]";
6
+ if (url.username || url.password) {
7
+ throw new Error("DECIONIS_URL_MUST_NOT_CONTAIN_CREDENTIALS");
8
+ }
9
+ if (url.search || url.hash) {
10
+ throw new Error("DECIONIS_URL_MUST_NOT_CONTAIN_QUERY_OR_FRAGMENT");
11
+ }
12
+ if (url.protocol !== "https:" && !(allowInsecureLoopback && loopback)) {
13
+ throw new Error("DECIONIS_URL_MUST_USE_HTTPS");
14
+ }
15
+ let end = normalizedValue.length;
16
+ while (end > 0 && normalizedValue.charCodeAt(end - 1) === 47) {
17
+ end -= 1;
18
+ }
19
+ return normalizedValue.slice(0, end);
20
+ }
21
+ }
22
+ //# sourceMappingURL=AuthorityBaseUrl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthorityBaseUrl.js","sourceRoot":"","sources":["../../src/http/AuthorityBaseUrl.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,gBAAgB;IACpB,MAAM,CAAC,SAAS,CAAC,KAAa,EAAE,qBAAqB,GAAG,KAAK;QAClE,MAAM,eAAe,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,eAAe,CAAC,CAAC;QACrC,MAAM,QAAQ,GACZ,GAAG,CAAC,QAAQ,KAAK,WAAW,IAAI,GAAG,CAAC,QAAQ,KAAK,WAAW,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO,CAAC;QAE3F,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC/D,CAAC;QACD,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;QACrE,CAAC;QACD,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,CAAC,qBAAqB,IAAI,QAAQ,CAAC,EAAE,CAAC;YACtE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;QACjD,CAAC;QAED,IAAI,GAAG,GAAG,eAAe,CAAC,MAAM,CAAC;QACjC,OAAO,GAAG,GAAG,CAAC,IAAI,eAAe,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC;YAC7D,GAAG,IAAI,CAAC,CAAC;QACX,CAAC;QACD,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACvC,CAAC;CACF"}
@@ -0,0 +1,4 @@
1
+ export declare class BoundedResponseBody {
2
+ static read(response: Response, maxBytes: number): Promise<string | null>;
3
+ }
4
+ //# sourceMappingURL=BoundedResponseBody.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BoundedResponseBody.d.ts","sourceRoot":"","sources":["../../src/http/BoundedResponseBody.ts"],"names":[],"mappings":"AAAA,qBAAa,mBAAmB;WACV,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;CA6BvF"}
@@ -0,0 +1,33 @@
1
+ export class BoundedResponseBody {
2
+ static async read(response, maxBytes) {
3
+ if (response.body === null)
4
+ return "";
5
+ const reader = response.body.getReader();
6
+ const chunks = [];
7
+ let byteLength = 0;
8
+ try {
9
+ while (true) {
10
+ const { done, value } = await reader.read();
11
+ if (done)
12
+ break;
13
+ byteLength += value.byteLength;
14
+ if (byteLength > maxBytes) {
15
+ await reader.cancel().catch(() => undefined);
16
+ return null;
17
+ }
18
+ chunks.push(value);
19
+ }
20
+ }
21
+ finally {
22
+ reader.releaseLock();
23
+ }
24
+ const body = new Uint8Array(byteLength);
25
+ let offset = 0;
26
+ for (const chunk of chunks) {
27
+ body.set(chunk, offset);
28
+ offset += chunk.byteLength;
29
+ }
30
+ return new TextDecoder("utf-8", { fatal: true }).decode(body);
31
+ }
32
+ }
33
+ //# sourceMappingURL=BoundedResponseBody.js.map