@loomwork/effect-runtime 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/NOTICE +8 -0
- package/README.md +65 -2
- package/dist/EffectRuntime.d.ts +121 -0
- package/dist/EffectRuntime.d.ts.map +1 -0
- package/dist/EffectRuntime.js +422 -0
- package/dist/EffectRuntime.js.map +1 -0
- package/dist/authz.d.ts +228 -0
- package/dist/authz.d.ts.map +1 -0
- package/dist/authz.js +281 -0
- package/dist/authz.js.map +1 -0
- package/dist/effects/A2AEffect.d.ts +14 -0
- package/dist/effects/A2AEffect.d.ts.map +1 -0
- package/dist/effects/A2AEffect.js +21 -0
- package/dist/effects/A2AEffect.js.map +1 -0
- package/dist/effects/HumanEffect.d.ts +13 -0
- package/dist/effects/HumanEffect.d.ts.map +1 -0
- package/dist/effects/HumanEffect.js +21 -0
- package/dist/effects/HumanEffect.js.map +1 -0
- package/dist/effects/LazyEffect.d.ts +10 -0
- package/dist/effects/LazyEffect.d.ts.map +1 -0
- package/dist/effects/LazyEffect.js +28 -0
- package/dist/effects/LazyEffect.js.map +1 -0
- package/dist/effects/LlmEffect.d.ts +27 -0
- package/dist/effects/LlmEffect.d.ts.map +1 -0
- package/dist/effects/LlmEffect.js +27 -0
- package/dist/effects/LlmEffect.js.map +1 -0
- package/dist/effects/ToolEffect.d.ts +38 -0
- package/dist/effects/ToolEffect.d.ts.map +1 -0
- package/dist/effects/ToolEffect.js +31 -0
- package/dist/effects/ToolEffect.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/dist/policy.d.ts +76 -0
- package/dist/policy.d.ts.map +1 -0
- package/dist/policy.js +212 -0
- package/dist/policy.js.map +1 -0
- package/dist/types.d.ts +416 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +28 -0
- package/dist/types.js.map +1 -0
- package/package.json +56 -3
- package/src/EffectRuntime.ts +484 -0
- package/src/authz.ts +424 -0
- package/src/effects/HumanEffect.ts +25 -0
- package/src/effects/LazyEffect.ts +25 -0
- package/src/effects/LlmEffect.ts +39 -0
- package/src/effects/ToolEffect.ts +59 -0
- package/src/index.ts +48 -0
- package/src/policy.ts +296 -0
- package/src/types.ts +428 -0
package/dist/authz.d.ts
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* K12.1 — an authenticated principal chain, populated at the trust boundary
|
|
3
|
+
* (A2A server / resume API) and propagated immutably through dispatch. The
|
|
4
|
+
* KERNEL CARRIES IT OPAQUELY and never interprets it — authorizers, budget
|
|
5
|
+
* scopes, and stores do. Keeping the kernel free of a tenant model is what keeps
|
|
6
|
+
* Loom a generic execution kernel (P10). Extra fields are allowed; a
|
|
7
|
+
* `delegation` (K12.4) rides here.
|
|
8
|
+
*/
|
|
9
|
+
export interface PrincipalChain {
|
|
10
|
+
/** The tenant boundary — an opaque, pseudonymous id (never human PII; see K10). */
|
|
11
|
+
tenant?: string;
|
|
12
|
+
/** The acting identity. */
|
|
13
|
+
actor?: string;
|
|
14
|
+
/** The identity this action is performed on behalf of (delegation origin). */
|
|
15
|
+
onBehalfOf?: string;
|
|
16
|
+
/** K12.4 — a verifiable attenuated-delegation token, checked at the callee. */
|
|
17
|
+
delegation?: DelegatedGrant;
|
|
18
|
+
/**
|
|
19
|
+
* R3k (ADR 0111 D2/D4) — set ONLY by the kernel's principal resolver, never by a caller: the
|
|
20
|
+
* execution's recorded principal carried a delegation (this is its digest id) that no codec or
|
|
21
|
+
* resolver could restore. The effect seam refuses every effect of such a principal BEFORE any
|
|
22
|
+
* authorizer is consulted ({@link principalBlocked}); it never falls back to a broader identity.
|
|
23
|
+
*/
|
|
24
|
+
delegationUnresolved?: string;
|
|
25
|
+
/** R3k — the recorded principal was crypto-shredded: every effect is denied (never the resumer's). */
|
|
26
|
+
principalShredded?: true;
|
|
27
|
+
/** R3k — the recorded principal could not be rehydrated (a `ref` with no codec, an unknown record version). */
|
|
28
|
+
principalUnresolved?: string;
|
|
29
|
+
[key: string]: unknown;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* R3k (ADR 0111 D4) — why the KERNEL refuses every effect of this principal before any
|
|
33
|
+
* authorizer is asked, or `undefined` when it does not. A `PolicyAuthorizer`, a `GrantTable` or a
|
|
34
|
+
* 3P authorizer would otherwise judge a chain whose delegation could not be restored on its own
|
|
35
|
+
* terms (an unattenuated child after a crash is the privilege escalation this closes).
|
|
36
|
+
*/
|
|
37
|
+
export declare function principalBlocked(principal: PrincipalChain | undefined): string | undefined;
|
|
38
|
+
export interface CapabilityRequest {
|
|
39
|
+
toolId: string;
|
|
40
|
+
/**
|
|
41
|
+
* R12 — the sub-resource this call targets, when the effect declares one
|
|
42
|
+
* (`Effect.resourceOf`): e.g. `"<server>/<tool>"` for `mcp.invoke`. A grant naming
|
|
43
|
+
* {@link capabilityIds | `<toolId>:<resource>`} authorizes exactly that resource; a grant on
|
|
44
|
+
* the bare `toolId` still authorizes every resource of the effect (unchanged behaviour).
|
|
45
|
+
*/
|
|
46
|
+
resource?: string;
|
|
47
|
+
executionId: string;
|
|
48
|
+
workflowId: string;
|
|
49
|
+
stepId: string;
|
|
50
|
+
/** K12.1 — the authenticated principal chain, if one was established. */
|
|
51
|
+
principal?: PrincipalChain;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* R12 — the capability ids a request is authorized under: the effect id (covers every resource
|
|
55
|
+
* of the effect — the legacy, coarse grant) and, when the call names a resource, the qualified
|
|
56
|
+
* `<toolId>:<resource>` id (covers just that resource).
|
|
57
|
+
*/
|
|
58
|
+
export declare function capabilityId(req: CapabilityRequest): string;
|
|
59
|
+
export declare function capabilityIds(req: CapabilityRequest): readonly string[];
|
|
60
|
+
export interface CapabilityDecision {
|
|
61
|
+
allowed: boolean;
|
|
62
|
+
reason?: string;
|
|
63
|
+
}
|
|
64
|
+
export interface CapabilityAuthorizer {
|
|
65
|
+
authorize(req: CapabilityRequest): CapabilityDecision;
|
|
66
|
+
}
|
|
67
|
+
export declare class CapabilityDeniedError extends Error {
|
|
68
|
+
readonly toolId: string;
|
|
69
|
+
readonly reason: string;
|
|
70
|
+
constructor(toolId: string, reason: string);
|
|
71
|
+
}
|
|
72
|
+
export interface GrantTableOptions {
|
|
73
|
+
/**
|
|
74
|
+
* Which field identifies the "principal" whose grants apply. Default: the
|
|
75
|
+
* workflowId (a flow is the unit of authority). Return `executionId` for
|
|
76
|
+
* per-execution grants, or read a grant-set id from the request.
|
|
77
|
+
*/
|
|
78
|
+
principal?: (req: CapabilityRequest) => string;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* The least-privilege authorizer: a static table mapping a principal to the set of
|
|
82
|
+
* effect ids it may invoke (`"*"` grants all). Anything not explicitly granted is
|
|
83
|
+
* denied. Grants are declared at boot and cannot be mutated at runtime, so authority
|
|
84
|
+
* is fixed and auditable.
|
|
85
|
+
*/
|
|
86
|
+
export declare class GrantTable implements CapabilityAuthorizer {
|
|
87
|
+
private readonly grants;
|
|
88
|
+
private readonly principalOf;
|
|
89
|
+
constructor(grants: Record<string, readonly string[]>, options?: GrantTableOptions);
|
|
90
|
+
authorize(req: CapabilityRequest): CapabilityDecision;
|
|
91
|
+
/**
|
|
92
|
+
* A read-only projection of the static grants — principal → granted effect ids,
|
|
93
|
+
* or `"*"` when all effects are granted. For pre-flight tooling (e.g. `@loomwork/verify`)
|
|
94
|
+
* that needs to inspect authority without a live {@link CapabilityRequest}.
|
|
95
|
+
*/
|
|
96
|
+
view(): Record<string, readonly string[] | "*">;
|
|
97
|
+
}
|
|
98
|
+
export interface DelegationAuthorizerOptions {
|
|
99
|
+
/**
|
|
100
|
+
* Shared secret used to verify delegation signatures at this trust boundary.
|
|
101
|
+
*
|
|
102
|
+
* NOTE this is SYMMETRIC: a party that can verify a token can also mint one.
|
|
103
|
+
* That is why {@link DelegationAuthorizerOptions.base} is required — see below.
|
|
104
|
+
*/
|
|
105
|
+
secret: string;
|
|
106
|
+
/**
|
|
107
|
+
* The callee's OWN authority — an effect is allowed only if it is in BOTH the
|
|
108
|
+
* verified delegated set AND the callee's own grants (never ambient escalation).
|
|
109
|
+
*
|
|
110
|
+
* REQUIRED, and it is load-bearing for security rather than a convenience.
|
|
111
|
+
* Because `secret` is symmetric, the verifier is also a valid minter: a callee
|
|
112
|
+
* can always sign itself a token granting `"*"`, and that token is
|
|
113
|
+
* cryptographically indistinguishable from a genuine one. The delegation check
|
|
114
|
+
* therefore cannot bound a callee's authority on its own — only the
|
|
115
|
+
* intersection with `base` can. With `base` set, minting a token gains a callee
|
|
116
|
+
* nothing it did not already hold, which is what makes the symmetric secret
|
|
117
|
+
* safe here.
|
|
118
|
+
*
|
|
119
|
+
* This option used to be optional, documented as "omit to allow the full
|
|
120
|
+
* verified delegated set (the callee delegates all of its authority decisions
|
|
121
|
+
* upstream)". That mode could not deliver what it claimed: upstream cannot
|
|
122
|
+
* retain authority over a callee that holds the minting key. Delegating
|
|
123
|
+
* authority ACROSS a trust boundary needs asymmetric signatures (the verifier
|
|
124
|
+
* must not be able to mint), which this primitive does not implement.
|
|
125
|
+
*/
|
|
126
|
+
base: CapabilityAuthorizer;
|
|
127
|
+
/** Clock for token-expiry checks (epoch ms). Injectable for tests; defaults to `Date.now`. */
|
|
128
|
+
now?: () => number;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* K12.4 — authorizes an effect against a VERIFIED attenuated delegation carried
|
|
132
|
+
* in `req.principal.delegation`. The token's signature is checked first (a
|
|
133
|
+
* forged or tampered delegation is denied outright), then the effect must be in
|
|
134
|
+
* the **intersection** of the delegated grants and the callee's own authority
|
|
135
|
+
* (`base`) — a delegate can never invoke an effect the delegator lacked, nor one
|
|
136
|
+
* the callee itself lacks. No delegation present ⇒ falls through to `base`.
|
|
137
|
+
*
|
|
138
|
+
* TRUST MODEL — delegator and callee share one secret, so they are one trust
|
|
139
|
+
* domain. The signature stops a THIRD party (a caller, a middlebox) forging or
|
|
140
|
+
* tampering with a grant set in transit; it does not, and cannot, stop the
|
|
141
|
+
* verifier minting its own. Authority over the callee comes from `base`, never
|
|
142
|
+
* from the token. Cross-organisation delegation, where the verifier must not be
|
|
143
|
+
* able to mint, is out of scope for this primitive and needs asymmetric
|
|
144
|
+
* signatures. See ADR 0024.
|
|
145
|
+
*/
|
|
146
|
+
export declare class DelegationAuthorizer implements CapabilityAuthorizer {
|
|
147
|
+
private readonly options;
|
|
148
|
+
constructor(options: DelegationAuthorizerOptions);
|
|
149
|
+
authorize(req: CapabilityRequest): CapabilityDecision;
|
|
150
|
+
}
|
|
151
|
+
/** A signed delegation: the grant subset a delegator conferred, HMAC-bound. */
|
|
152
|
+
export interface DelegatedGrant {
|
|
153
|
+
/** The delegated capability ids (effect ids the callee may invoke on the caller's behalf). */
|
|
154
|
+
grants: string[];
|
|
155
|
+
/** The principal this token was issued to (bound into the signature). */
|
|
156
|
+
issuedTo: string;
|
|
157
|
+
/** Optional absolute expiry (epoch ms), bound into the signature; rejected once past. */
|
|
158
|
+
exp?: number;
|
|
159
|
+
/** HMAC-SHA256 over `${issuedTo}\n${sorted grants}[\nexp=…]` with the shared delegation secret. */
|
|
160
|
+
sig: string;
|
|
161
|
+
}
|
|
162
|
+
/** Mint a delegation token: the delegator signs the subset it confers on `issuedTo`. */
|
|
163
|
+
export declare function signDelegation(secret: string, issuedTo: string, grants: string[], exp?: number): DelegatedGrant;
|
|
164
|
+
/**
|
|
165
|
+
* R3k (ADR 0111 D1) — a stable, NON-bearer identifier of a token, for the durable principal
|
|
166
|
+
* record: SHA-256 over the signature, so the log can say which delegation an execution held
|
|
167
|
+
* without holding anything that can be presented. The token itself is never written.
|
|
168
|
+
*/
|
|
169
|
+
export declare function delegationDigest(token: DelegatedGrant): string;
|
|
170
|
+
/** Verify a delegation's signature (constant-time). A forged/tampered token fails. */
|
|
171
|
+
export declare function verifyDelegation(secret: string, token: DelegatedGrant): boolean;
|
|
172
|
+
/**
|
|
173
|
+
* Attenuate a delegation to a narrower subset, re-signed for a new holder — only
|
|
174
|
+
* capabilities already in the token survive, and the parent's expiry is inherited.
|
|
175
|
+
* Requires the shared secret (the delegator/mint authority performs it); a
|
|
176
|
+
* pure-holder chained-HMAC variant is a future option.
|
|
177
|
+
*
|
|
178
|
+
* "Never broadening" is enforced on BOTH axes:
|
|
179
|
+
*
|
|
180
|
+
* - **Grants.** A capability absent from the parent cannot appear in the child. A parent
|
|
181
|
+
* holding `"*"` may attenuate to any concrete subset (that is narrowing) — previously
|
|
182
|
+
* such a subset was filtered against the literal `["*"]` array and came back EMPTY, so a
|
|
183
|
+
* wildcard delegator could not attenuate at all.
|
|
184
|
+
* - **Expiry.** The parent's `exp` is inherited, and `exp` may only be brought EARLIER.
|
|
185
|
+
* This was the important one: `exp` used not to be propagated, so attenuating a token
|
|
186
|
+
* that expired in an hour produced a child that **never expired** — narrowing the grant
|
|
187
|
+
* set while silently making the token immortal.
|
|
188
|
+
*
|
|
189
|
+
* Throws on an unverifiable parent. The signature is what makes the grant set trustworthy,
|
|
190
|
+
* and this function holds the secret — so attenuating an unchecked token would launder a
|
|
191
|
+
* forged one into a validly signed child. The old contract merely *documented* that the
|
|
192
|
+
* caller must pass a verified token; a security primitive should not depend on that.
|
|
193
|
+
*/
|
|
194
|
+
export declare function attenuateDelegation(secret: string, token: DelegatedGrant, issuedTo: string, subset: string[], exp?: number): DelegatedGrant;
|
|
195
|
+
import type { Scheduler } from "@loomwork/scheduler";
|
|
196
|
+
import type { Warmer } from "./types";
|
|
197
|
+
export interface EffectRuntimeOptions {
|
|
198
|
+
/** When set, every effect is authorized against it; ungranted effects are denied (K2). */
|
|
199
|
+
authorizer?: CapabilityAuthorizer;
|
|
200
|
+
/**
|
|
201
|
+
* When set, effects run through this scheduler (M6) — bounded concurrency + priority
|
|
202
|
+
* ordering across all of a runtime's effects (admission control). Omit for the
|
|
203
|
+
* zero-overhead direct path.
|
|
204
|
+
*/
|
|
205
|
+
scheduler?: Scheduler;
|
|
206
|
+
/** Advisory pre-warm hook, invoked off-log before each effect (M6). */
|
|
207
|
+
warmer?: Warmer;
|
|
208
|
+
/** ADR 0119 — where a swallowed delta-sink throw is reported. Defaults to `console.warn`. */
|
|
209
|
+
onWarn?: (message: string) => void;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* R16 / R17 — THE identity key: `[tenant, actor, onBehalfOf]`, one string, shared by everything that
|
|
213
|
+
* scopes state to "who" (a conversation's owner, a goal's owner). Two principals are the same identity
|
|
214
|
+
* iff all three fields are equal (an absent field equals only an absent field), so a delegate acting
|
|
215
|
+
* `onBehalfOf` someone is a DIFFERENT identity from that someone. A credential (a delegation token)
|
|
216
|
+
* is not part of identity. Keep one definition: two keys for one idea is how a scope check drifts.
|
|
217
|
+
*/
|
|
218
|
+
export declare function identityKeyOf(i: {
|
|
219
|
+
tenant?: string;
|
|
220
|
+
actor: string;
|
|
221
|
+
onBehalfOf?: string;
|
|
222
|
+
}): string;
|
|
223
|
+
/**
|
|
224
|
+
* The identity key of a principal, or `undefined` when it names no actor (it can own nothing) or the
|
|
225
|
+
* kernel marked it unusable ({@link principalBlocked}: shredded, delegation or record unresolved).
|
|
226
|
+
*/
|
|
227
|
+
export declare function principalIdentityKey(principal: PrincipalChain | undefined): string | undefined;
|
|
228
|
+
//# sourceMappingURL=authz.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authz.d.ts","sourceRoot":"","sources":["../src/authz.ts"],"names":[],"mappings":"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"}
|
package/dist/authz.js
ADDED
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ── Capability protection (Loom 2.0 K2) — the kernel's authority ring ─────────
|
|
3
|
+
//
|
|
4
|
+
// Every side effect flows through EffectRuntime.execute, so that is the one boundary
|
|
5
|
+
// a library CAN enforce (unlike hardware memory protection). A CapabilityAuthorizer
|
|
6
|
+
// decides, per invocation, whether the calling execution holds the authority to run
|
|
7
|
+
// the effect. Grants are unforgeable: an execution cannot grant itself a capability —
|
|
8
|
+
// grants live only in the authorizer, wired statically at boot (P5). A denied effect
|
|
9
|
+
// never runs; the denial is emitted as a durable EFFECT_DENIED fact (P9) and fails
|
|
10
|
+
// the step. Enforcement is opt-in: no authorizer ⇒ today's permissive behaviour.
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.DelegationAuthorizer = exports.GrantTable = exports.CapabilityDeniedError = void 0;
|
|
13
|
+
exports.principalBlocked = principalBlocked;
|
|
14
|
+
exports.capabilityId = capabilityId;
|
|
15
|
+
exports.capabilityIds = capabilityIds;
|
|
16
|
+
exports.signDelegation = signDelegation;
|
|
17
|
+
exports.delegationDigest = delegationDigest;
|
|
18
|
+
exports.verifyDelegation = verifyDelegation;
|
|
19
|
+
exports.attenuateDelegation = attenuateDelegation;
|
|
20
|
+
exports.identityKeyOf = identityKeyOf;
|
|
21
|
+
exports.principalIdentityKey = principalIdentityKey;
|
|
22
|
+
/**
|
|
23
|
+
* R3k (ADR 0111 D4) — why the KERNEL refuses every effect of this principal before any
|
|
24
|
+
* authorizer is asked, or `undefined` when it does not. A `PolicyAuthorizer`, a `GrantTable` or a
|
|
25
|
+
* 3P authorizer would otherwise judge a chain whose delegation could not be restored on its own
|
|
26
|
+
* terms (an unattenuated child after a crash is the privilege escalation this closes).
|
|
27
|
+
*/
|
|
28
|
+
function principalBlocked(principal) {
|
|
29
|
+
if (principal === undefined)
|
|
30
|
+
return undefined;
|
|
31
|
+
if (principal.principalShredded === true) {
|
|
32
|
+
return "the execution's recorded principal was crypto-shredded";
|
|
33
|
+
}
|
|
34
|
+
if (principal.delegationUnresolved !== undefined) {
|
|
35
|
+
return `the execution's recorded delegation "${String(principal.delegationUnresolved)}" could not be restored (no principalCodec/resolver)`;
|
|
36
|
+
}
|
|
37
|
+
if (principal.principalUnresolved !== undefined) {
|
|
38
|
+
return `the execution's recorded principal could not be restored: ${String(principal.principalUnresolved)}`;
|
|
39
|
+
}
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* R12 — the capability ids a request is authorized under: the effect id (covers every resource
|
|
44
|
+
* of the effect — the legacy, coarse grant) and, when the call names a resource, the qualified
|
|
45
|
+
* `<toolId>:<resource>` id (covers just that resource).
|
|
46
|
+
*/
|
|
47
|
+
function capabilityId(req) {
|
|
48
|
+
return req.resource === undefined ? req.toolId : `${req.toolId}:${req.resource}`;
|
|
49
|
+
}
|
|
50
|
+
function capabilityIds(req) {
|
|
51
|
+
return req.resource === undefined ? [req.toolId] : [req.toolId, `${req.toolId}:${req.resource}`];
|
|
52
|
+
}
|
|
53
|
+
class CapabilityDeniedError extends Error {
|
|
54
|
+
toolId;
|
|
55
|
+
reason;
|
|
56
|
+
constructor(toolId, reason) {
|
|
57
|
+
super(`Capability denied: effect "${toolId}" — ${reason}`);
|
|
58
|
+
this.name = "CapabilityDeniedError";
|
|
59
|
+
this.toolId = toolId;
|
|
60
|
+
this.reason = reason;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
exports.CapabilityDeniedError = CapabilityDeniedError;
|
|
64
|
+
/**
|
|
65
|
+
* The least-privilege authorizer: a static table mapping a principal to the set of
|
|
66
|
+
* effect ids it may invoke (`"*"` grants all). Anything not explicitly granted is
|
|
67
|
+
* denied. Grants are declared at boot and cannot be mutated at runtime, so authority
|
|
68
|
+
* is fixed and auditable.
|
|
69
|
+
*/
|
|
70
|
+
class GrantTable {
|
|
71
|
+
grants;
|
|
72
|
+
principalOf;
|
|
73
|
+
constructor(grants, options = {}) {
|
|
74
|
+
this.grants = new Map(Object.entries(grants).map(([k, v]) => [k, new Set(v)]));
|
|
75
|
+
this.principalOf = options.principal ?? ((req) => req.workflowId);
|
|
76
|
+
}
|
|
77
|
+
authorize(req) {
|
|
78
|
+
const principal = this.principalOf(req);
|
|
79
|
+
const granted = this.grants.get(principal);
|
|
80
|
+
if (granted === undefined) {
|
|
81
|
+
return { allowed: false, reason: `principal "${principal}" has no grants` };
|
|
82
|
+
}
|
|
83
|
+
if (granted.has("*") || capabilityIds(req).some((id) => granted.has(id))) {
|
|
84
|
+
return { allowed: true };
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
allowed: false,
|
|
88
|
+
reason: `effect "${capabilityId(req)}" not granted to "${principal}"`,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* A read-only projection of the static grants — principal → granted effect ids,
|
|
93
|
+
* or `"*"` when all effects are granted. For pre-flight tooling (e.g. `@loomwork/verify`)
|
|
94
|
+
* that needs to inspect authority without a live {@link CapabilityRequest}.
|
|
95
|
+
*/
|
|
96
|
+
view() {
|
|
97
|
+
const out = {};
|
|
98
|
+
for (const [principal, set] of this.grants) {
|
|
99
|
+
out[principal] = set.has("*") ? "*" : [...set];
|
|
100
|
+
}
|
|
101
|
+
return out;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
exports.GrantTable = GrantTable;
|
|
105
|
+
/**
|
|
106
|
+
* K12.4 — authorizes an effect against a VERIFIED attenuated delegation carried
|
|
107
|
+
* in `req.principal.delegation`. The token's signature is checked first (a
|
|
108
|
+
* forged or tampered delegation is denied outright), then the effect must be in
|
|
109
|
+
* the **intersection** of the delegated grants and the callee's own authority
|
|
110
|
+
* (`base`) — a delegate can never invoke an effect the delegator lacked, nor one
|
|
111
|
+
* the callee itself lacks. No delegation present ⇒ falls through to `base`.
|
|
112
|
+
*
|
|
113
|
+
* TRUST MODEL — delegator and callee share one secret, so they are one trust
|
|
114
|
+
* domain. The signature stops a THIRD party (a caller, a middlebox) forging or
|
|
115
|
+
* tampering with a grant set in transit; it does not, and cannot, stop the
|
|
116
|
+
* verifier minting its own. Authority over the callee comes from `base`, never
|
|
117
|
+
* from the token. Cross-organisation delegation, where the verifier must not be
|
|
118
|
+
* able to mint, is out of scope for this primitive and needs asymmetric
|
|
119
|
+
* signatures. See ADR 0024.
|
|
120
|
+
*/
|
|
121
|
+
class DelegationAuthorizer {
|
|
122
|
+
options;
|
|
123
|
+
constructor(options) {
|
|
124
|
+
this.options = options;
|
|
125
|
+
// The type alone is not the enforcement — JS callers and `as any` bypass it,
|
|
126
|
+
// and an absent `base` silently turns the intersection into a no-op, which
|
|
127
|
+
// reads as a working gate while bounding nothing.
|
|
128
|
+
if (options.base === undefined || options.base === null) {
|
|
129
|
+
throw new Error("DelegationAuthorizer: `base` is required — the delegation secret is symmetric, so a " +
|
|
130
|
+
"verified token cannot bound a callee's authority on its own (see ADR 0024).");
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
authorize(req) {
|
|
134
|
+
// Defence in depth: the kernel already refuses these before any authorizer (principalBlocked).
|
|
135
|
+
const blocked = principalBlocked(req.principal);
|
|
136
|
+
if (blocked !== undefined)
|
|
137
|
+
return { allowed: false, reason: blocked };
|
|
138
|
+
const token = req.principal?.delegation;
|
|
139
|
+
if (token === undefined) {
|
|
140
|
+
return this.options.base.authorize(req);
|
|
141
|
+
}
|
|
142
|
+
if (!verifyDelegation(this.options.secret, token)) {
|
|
143
|
+
return { allowed: false, reason: "delegation signature invalid (forged or tampered)" };
|
|
144
|
+
}
|
|
145
|
+
// Reject expired tokens (exp is signature-bound, so it can't be extended). A token
|
|
146
|
+
// without exp never expires — the same as before this field existed.
|
|
147
|
+
if (token.exp !== undefined && (this.options.now?.() ?? Date.now()) >= token.exp) {
|
|
148
|
+
return { allowed: false, reason: `delegation expired at ${token.exp}` };
|
|
149
|
+
}
|
|
150
|
+
// K12.4 — bind the token to its intended holder. A delegation minted for
|
|
151
|
+
// `issuedTo` may only be presented BY that principal (`req.principal.actor`).
|
|
152
|
+
// The signature proves authenticity, not that the bearer is the intended
|
|
153
|
+
// holder — without this check a captured/misrouted token is a confused deputy,
|
|
154
|
+
// usable by whoever holds it.
|
|
155
|
+
if (req.principal?.actor !== token.issuedTo) {
|
|
156
|
+
return {
|
|
157
|
+
allowed: false,
|
|
158
|
+
reason: `delegation issued to "${token.issuedTo}" but presented by "${req.principal?.actor ?? "(none)"}"`,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
const delegated = new Set(token.grants);
|
|
162
|
+
const inDelegated = delegated.has("*") || capabilityIds(req).some((id) => delegated.has(id));
|
|
163
|
+
if (!inDelegated) {
|
|
164
|
+
return {
|
|
165
|
+
allowed: false,
|
|
166
|
+
reason: `effect "${capabilityId(req)}" not in the delegated grant set`,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
// Intersection: the callee must ALSO hold the authority (no ambient escalation).
|
|
170
|
+
// This is what bounds a callee that could mint its own token — never the signature.
|
|
171
|
+
const baseDecision = this.options.base.authorize(req);
|
|
172
|
+
if (!baseDecision.allowed) {
|
|
173
|
+
return {
|
|
174
|
+
allowed: false,
|
|
175
|
+
reason: `delegated, but the callee itself lacks "${req.toolId}": ${baseDecision.reason ?? ""}`,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
return { allowed: true };
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
exports.DelegationAuthorizer = DelegationAuthorizer;
|
|
182
|
+
// ── K12.4 — verifiable attenuated delegation (macaroon-lite) ─────────────────
|
|
183
|
+
//
|
|
184
|
+
// The evaluation's amendment: "an attenuated grant set carried as a plain
|
|
185
|
+
// request field is forgeable by any caller or middlebox." So a delegation is
|
|
186
|
+
// SIGNED (HMAC) by the delegator and VERIFIED at the callee's trust boundary
|
|
187
|
+
// before its grants are honored. Attenuation can only NARROW: a holder derives
|
|
188
|
+
// a more-restricted token, never a broader one, because the delegated grant set
|
|
189
|
+
// is bound into the signature. The intersection is computed from the VERIFIED
|
|
190
|
+
// set, never a forgeable field.
|
|
191
|
+
const node_crypto_1 = require("node:crypto");
|
|
192
|
+
// `exp` is appended only when present, so tokens without it sign the exact prior payload
|
|
193
|
+
// (backward-compatible), while a tampered `exp` breaks the signature.
|
|
194
|
+
function delegationPayload(issuedTo, grants, exp) {
|
|
195
|
+
const base = `${issuedTo}\n${[...grants].sort().join(",")}`;
|
|
196
|
+
return exp !== undefined ? `${base}\nexp=${exp}` : base;
|
|
197
|
+
}
|
|
198
|
+
/** Mint a delegation token: the delegator signs the subset it confers on `issuedTo`. */
|
|
199
|
+
function signDelegation(secret, issuedTo, grants, exp) {
|
|
200
|
+
const sig = (0, node_crypto_1.createHmac)("sha256", secret)
|
|
201
|
+
.update(delegationPayload(issuedTo, grants, exp))
|
|
202
|
+
.digest("hex");
|
|
203
|
+
return { grants: [...grants], issuedTo, ...(exp !== undefined && { exp }), sig };
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* R3k (ADR 0111 D1) — a stable, NON-bearer identifier of a token, for the durable principal
|
|
207
|
+
* record: SHA-256 over the signature, so the log can say which delegation an execution held
|
|
208
|
+
* without holding anything that can be presented. The token itself is never written.
|
|
209
|
+
*/
|
|
210
|
+
function delegationDigest(token) {
|
|
211
|
+
return (0, node_crypto_1.createHash)("sha256").update(String(token.sig)).digest("hex");
|
|
212
|
+
}
|
|
213
|
+
/** Verify a delegation's signature (constant-time). A forged/tampered token fails. */
|
|
214
|
+
function verifyDelegation(secret, token) {
|
|
215
|
+
const expected = (0, node_crypto_1.createHmac)("sha256", secret)
|
|
216
|
+
.update(delegationPayload(token.issuedTo, token.grants, token.exp))
|
|
217
|
+
.digest("hex");
|
|
218
|
+
const a = Buffer.from(expected, "hex");
|
|
219
|
+
const b = Buffer.from(token.sig, "hex");
|
|
220
|
+
return a.length === b.length && (0, node_crypto_1.timingSafeEqual)(a, b);
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Attenuate a delegation to a narrower subset, re-signed for a new holder — only
|
|
224
|
+
* capabilities already in the token survive, and the parent's expiry is inherited.
|
|
225
|
+
* Requires the shared secret (the delegator/mint authority performs it); a
|
|
226
|
+
* pure-holder chained-HMAC variant is a future option.
|
|
227
|
+
*
|
|
228
|
+
* "Never broadening" is enforced on BOTH axes:
|
|
229
|
+
*
|
|
230
|
+
* - **Grants.** A capability absent from the parent cannot appear in the child. A parent
|
|
231
|
+
* holding `"*"` may attenuate to any concrete subset (that is narrowing) — previously
|
|
232
|
+
* such a subset was filtered against the literal `["*"]` array and came back EMPTY, so a
|
|
233
|
+
* wildcard delegator could not attenuate at all.
|
|
234
|
+
* - **Expiry.** The parent's `exp` is inherited, and `exp` may only be brought EARLIER.
|
|
235
|
+
* This was the important one: `exp` used not to be propagated, so attenuating a token
|
|
236
|
+
* that expired in an hour produced a child that **never expired** — narrowing the grant
|
|
237
|
+
* set while silently making the token immortal.
|
|
238
|
+
*
|
|
239
|
+
* Throws on an unverifiable parent. The signature is what makes the grant set trustworthy,
|
|
240
|
+
* and this function holds the secret — so attenuating an unchecked token would launder a
|
|
241
|
+
* forged one into a validly signed child. The old contract merely *documented* that the
|
|
242
|
+
* caller must pass a verified token; a security primitive should not depend on that.
|
|
243
|
+
*/
|
|
244
|
+
function attenuateDelegation(secret, token, issuedTo, subset, exp) {
|
|
245
|
+
if (!verifyDelegation(secret, token)) {
|
|
246
|
+
throw new Error("attenuateDelegation: parent delegation failed verification — refusing to sign a child from an unverified token");
|
|
247
|
+
}
|
|
248
|
+
const parentIsWildcard = token.grants.includes("*");
|
|
249
|
+
const narrowed = parentIsWildcard ? [...subset] : subset.filter((g) => token.grants.includes(g));
|
|
250
|
+
// Inherit the parent's expiry; an explicit `exp` may only tighten it.
|
|
251
|
+
const inherited = token.exp;
|
|
252
|
+
const nextExp = inherited === undefined ? exp : exp === undefined ? inherited : Math.min(inherited, exp);
|
|
253
|
+
return signDelegation(secret, issuedTo, narrowed, nextExp);
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* R16 / R17 — THE identity key: `[tenant, actor, onBehalfOf]`, one string, shared by everything that
|
|
257
|
+
* scopes state to "who" (a conversation's owner, a goal's owner). Two principals are the same identity
|
|
258
|
+
* iff all three fields are equal (an absent field equals only an absent field), so a delegate acting
|
|
259
|
+
* `onBehalfOf` someone is a DIFFERENT identity from that someone. A credential (a delegation token)
|
|
260
|
+
* is not part of identity. Keep one definition: two keys for one idea is how a scope check drifts.
|
|
261
|
+
*/
|
|
262
|
+
function identityKeyOf(i) {
|
|
263
|
+
return JSON.stringify([i.tenant ?? null, i.actor, i.onBehalfOf ?? null]);
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* The identity key of a principal, or `undefined` when it names no actor (it can own nothing) or the
|
|
267
|
+
* kernel marked it unusable ({@link principalBlocked}: shredded, delegation or record unresolved).
|
|
268
|
+
*/
|
|
269
|
+
function principalIdentityKey(principal) {
|
|
270
|
+
if (principal === undefined || principalBlocked(principal) !== undefined)
|
|
271
|
+
return undefined;
|
|
272
|
+
const actor = principal.actor;
|
|
273
|
+
if (typeof actor !== "string" || actor.trim() === "")
|
|
274
|
+
return undefined;
|
|
275
|
+
return identityKeyOf({
|
|
276
|
+
actor,
|
|
277
|
+
...(typeof principal.tenant === "string" && { tenant: principal.tenant }),
|
|
278
|
+
...(typeof principal.onBehalfOf === "string" && { onBehalfOf: principal.onBehalfOf }),
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
//# sourceMappingURL=authz.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authz.js","sourceRoot":"","sources":["../src/authz.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Effect, EffectContext } from "../types";
|
|
2
|
+
/**
|
|
3
|
+
* @deprecated ADR 0115 — the `a2a` effect belongs to `@loom/plugin-a2a`, which now defines and
|
|
4
|
+
* exports its own `A2AEffect`. This copy stays for one minor so existing imports keep working
|
|
5
|
+
* (a re-export would make this kernel-adjacent package depend on a plugin). `"a2a"` is just a
|
|
6
|
+
* custom kind to the kernel.
|
|
7
|
+
*/
|
|
8
|
+
export declare class A2AEffect<TIn = unknown, TOut = unknown> implements Effect<TIn, TOut> {
|
|
9
|
+
private readonly fn;
|
|
10
|
+
readonly kind: "a2a";
|
|
11
|
+
constructor(fn: (input: TIn, ctx: EffectContext) => Promise<TOut>);
|
|
12
|
+
execute(input: TIn, ctx: EffectContext): Promise<TOut>;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=A2AEffect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"A2AEffect.d.ts","sourceRoot":"","sources":["../../src/effects/A2AEffect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEtD;;;;;GAKG;AACH,qBAAa,SAAS,CAAC,GAAG,GAAG,OAAO,EAAE,IAAI,GAAG,OAAO,CAAE,YAAW,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC;IAGpE,OAAO,CAAC,QAAQ,CAAC,EAAE;IAF/B,QAAQ,CAAC,IAAI,EAAG,KAAK,CAAU;gBAEF,EAAE,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC;IAElF,OAAO,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;CAGvD"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.A2AEffect = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* @deprecated ADR 0115 — the `a2a` effect belongs to `@loom/plugin-a2a`, which now defines and
|
|
6
|
+
* exports its own `A2AEffect`. This copy stays for one minor so existing imports keep working
|
|
7
|
+
* (a re-export would make this kernel-adjacent package depend on a plugin). `"a2a"` is just a
|
|
8
|
+
* custom kind to the kernel.
|
|
9
|
+
*/
|
|
10
|
+
class A2AEffect {
|
|
11
|
+
fn;
|
|
12
|
+
kind = "a2a";
|
|
13
|
+
constructor(fn) {
|
|
14
|
+
this.fn = fn;
|
|
15
|
+
}
|
|
16
|
+
execute(input, ctx) {
|
|
17
|
+
return this.fn(input, ctx);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
exports.A2AEffect = A2AEffect;
|
|
21
|
+
//# sourceMappingURL=A2AEffect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"A2AEffect.js","sourceRoot":"","sources":["../../src/effects/A2AEffect.ts"],"names":[],"mappings":";;;AAEA;;;;;GAKG;AACH,MAAa,SAAS;IAGS;IAFpB,IAAI,GAAG,KAAc,CAAC;IAE/B,YAA6B,EAAqD;QAArD,OAAE,GAAF,EAAE,CAAmD;IAAG,CAAC;IAEtF,OAAO,CAAC,KAAU,EAAE,GAAkB;QACpC,OAAO,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC7B,CAAC;CACF;AARD,8BAQC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Effect, EffectContext } from "../types";
|
|
2
|
+
export interface HumanEffectConfig {
|
|
3
|
+
on: string;
|
|
4
|
+
timeout?: number;
|
|
5
|
+
correlationKey?: (input: unknown) => string;
|
|
6
|
+
}
|
|
7
|
+
export declare class HumanEffect<TIn = unknown, TOut = unknown> implements Effect<TIn, TOut> {
|
|
8
|
+
private readonly config;
|
|
9
|
+
readonly kind: "human";
|
|
10
|
+
constructor(config: HumanEffectConfig);
|
|
11
|
+
execute(input: TIn, _ctx: EffectContext): Promise<TOut>;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=HumanEffect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HumanEffect.d.ts","sourceRoot":"","sources":["../../src/effects/HumanEffect.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEtD,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,MAAM,CAAC;CAC7C;AAED,qBAAa,WAAW,CAAC,GAAG,GAAG,OAAO,EAAE,IAAI,GAAG,OAAO,CAAE,YAAW,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC;IAGtE,OAAO,CAAC,QAAQ,CAAC,MAAM;IAFnC,QAAQ,CAAC,IAAI,EAAG,OAAO,CAAU;gBAEJ,MAAM,EAAE,iBAAiB;IAEtD,OAAO,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;CAUxD"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HumanEffect = void 0;
|
|
4
|
+
const core_1 = require("@loomwork/core");
|
|
5
|
+
class HumanEffect {
|
|
6
|
+
config;
|
|
7
|
+
kind = "human";
|
|
8
|
+
constructor(config) {
|
|
9
|
+
this.config = config;
|
|
10
|
+
}
|
|
11
|
+
execute(input, _ctx) {
|
|
12
|
+
const correlationKey = this.config.correlationKey !== undefined ? this.config.correlationKey(input) : undefined;
|
|
13
|
+
throw new core_1.SuspendError({
|
|
14
|
+
on: this.config.on,
|
|
15
|
+
...(this.config.timeout !== undefined && { timeout: this.config.timeout }),
|
|
16
|
+
...(correlationKey !== undefined && { correlationKey }),
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
exports.HumanEffect = HumanEffect;
|
|
21
|
+
//# sourceMappingURL=HumanEffect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HumanEffect.js","sourceRoot":"","sources":["../../src/effects/HumanEffect.ts"],"names":[],"mappings":";;;AAAA,yCAA8C;AAS9C,MAAa,WAAW;IAGO;IAFpB,IAAI,GAAG,OAAgB,CAAC;IAEjC,YAA6B,MAAyB;QAAzB,WAAM,GAAN,MAAM,CAAmB;IAAG,CAAC;IAE1D,OAAO,CAAC,KAAU,EAAE,IAAmB;QACrC,MAAM,cAAc,GAClB,IAAI,CAAC,MAAM,CAAC,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAE3F,MAAM,IAAI,mBAAY,CAAC;YACrB,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE;YAClB,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,KAAK,SAAS,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YAC1E,GAAG,CAAC,cAAc,KAAK,SAAS,IAAI,EAAE,cAAc,EAAE,CAAC;SACxD,CAAC,CAAC;IACL,CAAC;CACF;AAfD,kCAeC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { HandlerSpec } from "@loomwork/core";
|
|
2
|
+
import type { Effect, EffectContext } from "../types";
|
|
3
|
+
export declare class LazyEffect<TIn = unknown, TOut = unknown> implements Effect<TIn, TOut> {
|
|
4
|
+
private readonly spec;
|
|
5
|
+
readonly kind: "tool";
|
|
6
|
+
private resolved;
|
|
7
|
+
constructor(spec: HandlerSpec<TIn, TOut>);
|
|
8
|
+
execute(input: TIn, ctx: EffectContext): Promise<TOut>;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=LazyEffect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LazyEffect.d.ts","sourceRoot":"","sources":["../../src/effects/LazyEffect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAwC,WAAW,EAAE,MAAM,gBAAgB,CAAC;AACxF,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAMtD,qBAAa,UAAU,CAAC,GAAG,GAAG,OAAO,EAAE,IAAI,GAAG,OAAO,CAAE,YAAW,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC;IAIrE,OAAO,CAAC,QAAQ,CAAC,IAAI;IAHjC,QAAQ,CAAC,IAAI,EAAG,MAAM,CAAU;IAChC,OAAO,CAAC,QAAQ,CAAmC;gBAEtB,IAAI,EAAE,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC;IAEnD,OAAO,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;CAW7D"}
|