@fabricorg/ports 0.5.2 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/catalog.cjs +171 -0
- package/dist/catalog.cjs.map +1 -1
- package/dist/catalog.d.cts +4 -3
- package/dist/catalog.d.ts +4 -3
- package/dist/catalog.js +10 -1
- package/dist/catalog.js.map +1 -1
- package/dist/{chunk-HEPIOWZI.js → chunk-7CFDCFTH.js} +164 -1
- package/dist/chunk-7CFDCFTH.js.map +1 -0
- package/dist/index.cjs +164 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +87 -1
- package/dist/index.d.ts +87 -1
- package/dist/index.js +3 -1
- package/package.json +2 -2
- package/dist/chunk-HEPIOWZI.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -27,6 +27,7 @@ __export(index_exports, {
|
|
|
27
27
|
assertPortRequirementsSatisfied: () => assertPortRequirementsSatisfied,
|
|
28
28
|
assertPortSuiteHasTeeth: () => assertPortSuiteHasTeeth,
|
|
29
29
|
certifyAdapter: () => certifyAdapter,
|
|
30
|
+
completionIngressPortChecks: () => completionIngressPortChecks,
|
|
30
31
|
contentPortChecks: () => contentPortChecks,
|
|
31
32
|
customerRecordPortChecks: () => customerRecordPortChecks,
|
|
32
33
|
definePort: () => definePort,
|
|
@@ -166,6 +167,168 @@ function actorContextFromClaims(claims, scope, now = /* @__PURE__ */ new Date())
|
|
|
166
167
|
spaceId: scope.spaceId
|
|
167
168
|
};
|
|
168
169
|
}
|
|
170
|
+
var RECEIVED_AT = "2026-09-02T10:00:00Z";
|
|
171
|
+
function auditIsSecretFree(result, secrets, where) {
|
|
172
|
+
expect(result.audit !== null && typeof result.audit === "object", `${where}: no audit record was produced`);
|
|
173
|
+
const serialized = JSON.stringify(result.audit);
|
|
174
|
+
for (const secret of secrets) {
|
|
175
|
+
if (secret.length === 0) continue;
|
|
176
|
+
expect(!serialized.includes(secret), `${where}: the audit record contains a secret`);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
function sameScope(left, right) {
|
|
180
|
+
return left.tenantId === right.tenantId && left.spaceId === right.spaceId && left.actionInvocationId === right.actionInvocationId;
|
|
181
|
+
}
|
|
182
|
+
function completionIngressPortChecks(fixtures) {
|
|
183
|
+
const callback = (input) => ({
|
|
184
|
+
provider: input.provider ?? fixtures.provider,
|
|
185
|
+
credential: input.credential === void 0 ? fixtures.validCredential : input.credential,
|
|
186
|
+
payload: fixtures.payload({ reference: input.reference, evidence: input.evidence, ...input.claimedScope ? { claimedScope: input.claimedScope } : {} }),
|
|
187
|
+
receivedAt: RECEIVED_AT
|
|
188
|
+
});
|
|
189
|
+
return [
|
|
190
|
+
{
|
|
191
|
+
id: "completion-ingress.derives-scope-from-server-state",
|
|
192
|
+
title: "a verified callback is forwarded under the scope the server-held binding resolves, and the outcome is the host's",
|
|
193
|
+
async run(port) {
|
|
194
|
+
await fixtures.reset();
|
|
195
|
+
const result = await port.receive(callback({ reference: fixtures.boundReference, evidence: "a" }));
|
|
196
|
+
expect(result.accepted, `a verified callback was refused: ${result.accepted ? "" : result.refusal}`);
|
|
197
|
+
if (!result.accepted) return;
|
|
198
|
+
expect(sameScope(result.scope, fixtures.expectedScope), "the forwarded scope is not the one the binding resolves");
|
|
199
|
+
expect(result.externalReference === fixtures.boundReference, "the forwarded reference is not the bound one");
|
|
200
|
+
expect(result.provider === fixtures.provider, "the forwarded provider is not the verified one");
|
|
201
|
+
expect(result.outcome === "completed" || result.outcome === "failed", `a first completion reported "${result.outcome}"`);
|
|
202
|
+
auditIsSecretFree(result, fixtures.secrets, "accepted callback");
|
|
203
|
+
}
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
id: "completion-ingress.rejects-invalid-credential",
|
|
207
|
+
title: "an unverifiable credential is refused before anything is resolved or forwarded",
|
|
208
|
+
async run(port) {
|
|
209
|
+
await fixtures.reset();
|
|
210
|
+
const result = await port.receive(callback({ reference: fixtures.boundReference, evidence: "a", credential: fixtures.invalidCredential }));
|
|
211
|
+
expect(!result.accepted && result.refusal === "invalid_credential", "an invalid credential was not refused as invalid_credential");
|
|
212
|
+
auditIsSecretFree(result, fixtures.secrets, "refused credential");
|
|
213
|
+
const later = await port.receive(callback({ reference: fixtures.boundReference, evidence: "a" }));
|
|
214
|
+
expect(later.accepted && (later.outcome === "completed" || later.outcome === "failed"), "the refused callback reached the host");
|
|
215
|
+
}
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
id: "completion-ingress.rejects-unknown-reference",
|
|
219
|
+
title: "a reference no binding resolves is refused rather than guessed at",
|
|
220
|
+
async run(port) {
|
|
221
|
+
await fixtures.reset();
|
|
222
|
+
const result = await port.receive(callback({ reference: fixtures.unknownReference, evidence: "a" }));
|
|
223
|
+
expect(!result.accepted && result.refusal === "unknown_reference", "an unknown reference was not refused as unknown_reference");
|
|
224
|
+
auditIsSecretFree(result, fixtures.secrets, "unknown reference");
|
|
225
|
+
}
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
id: "completion-ingress.ignores-claimed-scope",
|
|
229
|
+
title: "scope asserted in the payload never becomes the forwarded scope",
|
|
230
|
+
async run(port) {
|
|
231
|
+
await fixtures.reset();
|
|
232
|
+
const result = await port.receive(callback({ reference: fixtures.boundReference, evidence: "a", claimedScope: fixtures.foreignScope }));
|
|
233
|
+
if (result.accepted) {
|
|
234
|
+
expect(sameScope(result.scope, fixtures.expectedScope), "the sender's claimed scope was forwarded");
|
|
235
|
+
} else {
|
|
236
|
+
expect(result.refusal === "scope_mismatch" || result.refusal === "malformed", `a claimed scope was refused as "${result.refusal}"`);
|
|
237
|
+
}
|
|
238
|
+
auditIsSecretFree(result, fixtures.secrets, "claimed scope");
|
|
239
|
+
}
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
id: "completion-ingress.rejects-provider-mismatch",
|
|
243
|
+
title: "a reference bound to one provider is not accepted from another",
|
|
244
|
+
async run(port) {
|
|
245
|
+
await fixtures.reset();
|
|
246
|
+
const result = await port.receive(callback({ reference: fixtures.boundReference, evidence: "a", provider: fixtures.otherProvider }));
|
|
247
|
+
expect(!result.accepted, "a callback from the wrong provider was accepted");
|
|
248
|
+
expect(!result.accepted && (result.refusal === "provider_mismatch" || result.refusal === "invalid_credential"), "the wrong provider was refused for another reason");
|
|
249
|
+
auditIsSecretFree(result, fixtures.secrets, "provider mismatch");
|
|
250
|
+
}
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
id: "completion-ingress.rejects-cross-tenant-reference",
|
|
254
|
+
title: "a credential good for one tenant cannot complete another tenant's reference",
|
|
255
|
+
async run(port) {
|
|
256
|
+
await fixtures.reset();
|
|
257
|
+
const theirs = await port.receive(callback({ reference: fixtures.foreignReference, evidence: "a", credential: fixtures.foreignCredential }));
|
|
258
|
+
expect(theirs.accepted, "the foreign reference does not resolve for its own tenant, so the fixture proves nothing");
|
|
259
|
+
if (theirs.accepted) expect(sameScope(theirs.scope, fixtures.foreignScope), "the foreign reference resolved to an unexpected scope");
|
|
260
|
+
await fixtures.reset();
|
|
261
|
+
const result = await port.receive(callback({ reference: fixtures.foreignReference, evidence: "a" }));
|
|
262
|
+
expect(!result.accepted, "another tenant's reference was accepted");
|
|
263
|
+
expect(!result.accepted && (result.refusal === "scope_mismatch" || result.refusal === "unknown_reference" || result.refusal === "invalid_credential"), "the foreign reference was refused for another reason");
|
|
264
|
+
auditIsSecretFree(result, fixtures.secrets, "cross-tenant reference");
|
|
265
|
+
}
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
id: "completion-ingress.absorbs-exact-replay",
|
|
269
|
+
title: "the same callback twice is accepted twice with the same scope, and the second is a replay",
|
|
270
|
+
async run(port) {
|
|
271
|
+
await fixtures.reset();
|
|
272
|
+
const first = await port.receive(callback({ reference: fixtures.boundReference, evidence: "a" }));
|
|
273
|
+
const second = await port.receive(callback({ reference: fixtures.boundReference, evidence: "a" }));
|
|
274
|
+
expect(first.accepted && second.accepted, "an exact replay was refused");
|
|
275
|
+
if (!first.accepted || !second.accepted) return;
|
|
276
|
+
expect(sameScope(first.scope, second.scope), "a replay was forwarded under a different scope");
|
|
277
|
+
expect(second.outcome === "replayed" || second.outcome === first.outcome, `a replay reported "${second.outcome}" after "${first.outcome}"`);
|
|
278
|
+
expect(await fixtures.observed.settlements(fixtures.boundReference) === 1, "an exact replay settled the invocation a second time");
|
|
279
|
+
auditIsSecretFree(second, fixtures.secrets, "replay");
|
|
280
|
+
}
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
id: "completion-ingress.routes-changed-evidence",
|
|
284
|
+
title: "the same reference with different evidence is a contradiction the host reconciles, not a replay",
|
|
285
|
+
async run(port) {
|
|
286
|
+
await fixtures.reset();
|
|
287
|
+
const first = await port.receive(callback({ reference: fixtures.boundReference, evidence: "a" }));
|
|
288
|
+
const changed = await port.receive(callback({ reference: fixtures.boundReference, evidence: "b" }));
|
|
289
|
+
expect(first.accepted, "the first callback was refused");
|
|
290
|
+
expect(changed.accepted, "changed evidence was refused instead of routed to reconciliation");
|
|
291
|
+
if (!changed.accepted) return;
|
|
292
|
+
expect(changed.outcome === "reconciliation_required", `changed evidence reported "${changed.outcome}"`);
|
|
293
|
+
auditIsSecretFree(changed, fixtures.secrets, "changed evidence");
|
|
294
|
+
}
|
|
295
|
+
},
|
|
296
|
+
{
|
|
297
|
+
id: "completion-ingress.refusals-are-auditable",
|
|
298
|
+
title: "every refusal leaves a secret-free audit record naming the refusal",
|
|
299
|
+
async run(port) {
|
|
300
|
+
await fixtures.reset();
|
|
301
|
+
const results = await Promise.all([
|
|
302
|
+
port.receive(callback({ reference: fixtures.boundReference, evidence: "a", credential: fixtures.invalidCredential })),
|
|
303
|
+
port.receive(callback({ reference: fixtures.unknownReference, evidence: "a" })),
|
|
304
|
+
port.receive(callback({ reference: fixtures.boundReference, evidence: "a", provider: fixtures.otherProvider }))
|
|
305
|
+
]);
|
|
306
|
+
for (const result of results) {
|
|
307
|
+
expect(!result.accepted, "a refusal case was accepted");
|
|
308
|
+
if (result.accepted) continue;
|
|
309
|
+
expect(Object.keys(result.audit).length > 0, "a refusal produced an empty audit record");
|
|
310
|
+
expect(JSON.stringify(result.audit).includes(result.refusal), "the audit record does not name the refusal");
|
|
311
|
+
auditIsSecretFree(result, fixtures.secrets, `refusal ${result.refusal}`);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
id: "completion-ingress.holds-under-concurrent-callbacks",
|
|
317
|
+
title: "identical callbacks arriving together are all accepted under one scope, with exactly one first completion",
|
|
318
|
+
async run(port) {
|
|
319
|
+
await fixtures.reset();
|
|
320
|
+
const results = await Promise.all(Array.from({ length: 8 }, () => port.receive(callback({ reference: fixtures.boundReference, evidence: "a" }))));
|
|
321
|
+
const accepted = results.filter((result) => result.accepted);
|
|
322
|
+
expect(accepted.length === results.length, `${results.length - accepted.length} of ${results.length} concurrent callbacks were refused`);
|
|
323
|
+
expect(accepted.every((result) => sameScope(result.scope, fixtures.expectedScope)), "concurrent callbacks were forwarded under different scopes");
|
|
324
|
+
const settled = accepted.filter((result) => result.outcome === "completed" || result.outcome === "failed");
|
|
325
|
+
expect(settled.length >= 1, "no concurrent callback settled the invocation");
|
|
326
|
+
expect(accepted.every((result) => result.outcome !== "reconciliation_required"), "identical concurrent callbacks were reported as contradicting each other");
|
|
327
|
+
expect(await fixtures.observed.settlements(fixtures.boundReference) === 1, "concurrent identical callbacks settled the invocation more than once");
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
];
|
|
331
|
+
}
|
|
169
332
|
var PORT_ID = /^[a-z][a-z0-9-]*(?:\.[a-z0-9-]+)+$/;
|
|
170
333
|
function definePort(definition) {
|
|
171
334
|
if (!PORT_ID.test(definition.id)) {
|
|
@@ -683,6 +846,7 @@ async function runPortContract(port, checks) {
|
|
|
683
846
|
assertPortRequirementsSatisfied,
|
|
684
847
|
assertPortSuiteHasTeeth,
|
|
685
848
|
certifyAdapter,
|
|
849
|
+
completionIngressPortChecks,
|
|
686
850
|
contentPortChecks,
|
|
687
851
|
customerRecordPortChecks,
|
|
688
852
|
definePort,
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../index.ts"],"sourcesContent":["/**\n * Port interfaces are declared here and implemented by vendor adapters elsewhere.\n * Nothing in this package imports a vendor SDK: a port is a shape, and an adapter\n * is anything that satisfies it. Where an open standard exists the port speaks it,\n * so the incumbent vendor is already just one provider behind the interface.\n */\n\n// ── Feature flags (OpenFeature-shaped) ──────────────────────────────────────\n\nexport type FlagValue = boolean | string | number | { [key: string]: unknown };\n\nexport interface EvaluationContext {\n\t/** Stable identifier for the subject of evaluation, usually a tenant or actor. */\n\ttargetingKey?: string;\n\t[attribute: string]: unknown;\n}\n\nexport type ResolutionReason = \"STATIC\" | \"DEFAULT\" | \"TARGETING_MATCH\" | \"SPLIT\" | \"CACHED\" | \"ERROR\";\n\nexport interface ResolutionDetails<T extends FlagValue> {\n\tvalue: T;\n\treason: ResolutionReason;\n\tvariant?: string;\n\terrorCode?: string;\n}\n\n/**\n * Structurally compatible with an OpenFeature provider's evaluation surface, so an\n * OpenFeature provider is a thin adapter rather than a translation layer.\n */\nexport interface FlagsPort {\n\tresolveBoolean(flagKey: string, defaultValue: boolean, context?: EvaluationContext): Promise<ResolutionDetails<boolean>>;\n\tresolveString(flagKey: string, defaultValue: string, context?: EvaluationContext): Promise<ResolutionDetails<string>>;\n\tresolveNumber(flagKey: string, defaultValue: number, context?: EvaluationContext): Promise<ResolutionDetails<number>>;\n}\n\n// ── Design tokens (W3C DTCG) ────────────────────────────────────────────────\n\nexport interface DtcgToken {\n\t$value: unknown;\n\t$type?: string;\n\t$description?: string;\n}\n\nexport interface DtcgGroup {\n\t$type?: string;\n\t$description?: string;\n\t[member: string]: DtcgToken | DtcgGroup | string | undefined;\n}\n\nexport interface ResolvedToken {\n\tname: string;\n\tvalue: unknown;\n\ttype?: string;\n\tdescription?: string;\n}\n\nexport interface DesignTokensPort {\n\t/** Resolved tokens for one theme. Aliases are already followed. */\n\tresolve(theme: string): Promise<ResolvedToken[]>;\n}\n\nconst ALIAS = /^\\{([^}]+)\\}$/;\n\nconst isToken = (value: unknown): value is DtcgToken =>\n\t!!value && typeof value === \"object\" && !Array.isArray(value) && \"$value\" in value;\n\nconst isGroup = (value: unknown): value is DtcgGroup =>\n\t!!value && typeof value === \"object\" && !Array.isArray(value) && !(\"$value\" in value);\n\n/**\n * Flattens a DTCG document and follows aliases. `$type` is inherited from the\n * nearest ancestor group that declares one, which is what the format specifies\n * and what makes a theme file readable.\n */\nexport function resolveDesignTokens(document: DtcgGroup): ResolvedToken[] {\n\tconst flat = new Map<string, { token: DtcgToken; type?: string }>();\n\n\tconst walk = (node: DtcgGroup, path: string[], inheritedType?: string): void => {\n\t\tconst groupType = typeof node.$type === \"string\" ? node.$type : inheritedType;\n\t\tfor (const [key, member] of Object.entries(node)) {\n\t\t\tif (key.startsWith(\"$\")) continue;\n\t\t\tconst next = [...path, key];\n\t\t\tif (isToken(member)) {\n\t\t\t\tflat.set(next.join(\".\"), { token: member, type: member.$type ?? groupType });\n\t\t\t} else if (isGroup(member)) {\n\t\t\t\twalk(member, next, groupType);\n\t\t\t}\n\t\t}\n\t};\n\twalk(document, []);\n\n\tconst resolving = new Set<string>();\n\tconst resolved = new Map<string, unknown>();\n\n\tconst valueOf = (name: string): unknown => {\n\t\tif (resolved.has(name)) return resolved.get(name);\n\t\tconst entry = flat.get(name);\n\t\tif (!entry) throw new Error(`Design token alias \"{${name}}\" does not resolve to a declared token.`);\n\t\tif (resolving.has(name)) {\n\t\t\tthrow new Error(`Design token alias cycle: ${[...resolving, name].join(\" -> \")}.`);\n\t\t}\n\t\tconst raw = entry.token.$value;\n\t\tif (typeof raw !== \"string\") {\n\t\t\tresolved.set(name, raw);\n\t\t\treturn raw;\n\t\t}\n\t\tconst alias = ALIAS.exec(raw.trim());\n\t\tif (!alias) {\n\t\t\tresolved.set(name, raw);\n\t\t\treturn raw;\n\t\t}\n\t\tresolving.add(name);\n\t\tconst target = valueOf(alias[1]!);\n\t\tresolving.delete(name);\n\t\tresolved.set(name, target);\n\t\treturn target;\n\t};\n\n\treturn [...flat.entries()].map(([name, entry]) => {\n\t\tconst value = valueOf(name);\n\t\treturn {\n\t\t\tname,\n\t\t\tvalue,\n\t\t\t...(entry.type === undefined ? {} : { type: entry.type }),\n\t\t\t...(entry.token.$description === undefined ? {} : { description: entry.token.$description }),\n\t\t};\n\t});\n}\n\n// ── Identity (OAuth2 / OIDC-shaped) ─────────────────────────────────────────\n\n/**\n * Actor kinds a verified credential can resolve to. This mirrors `ActorType` in\n * `@fabricorg/platform`, restated here so this package keeps zero runtime\n * dependencies. `identityPortChecks` asserts the two stay identical.\n */\nexport type IdentityActorType =\n\t| \"natural_person\"\n\t| \"agent\"\n\t| \"system\"\n\t| \"service_account\"\n\t| \"external_system\"\n\t| \"integration\";\n\nexport const IDENTITY_ACTOR_TYPES: readonly IdentityActorType[] = [\n\t\"natural_person\",\n\t\"agent\",\n\t\"system\",\n\t\"service_account\",\n\t\"external_system\",\n\t\"integration\",\n];\n\n/**\n * The scopes a credential covers. `\"tenant-wide\"` is spelled out rather than\n * left as an absent field, so a credential that simply forgot to carry space\n * coverage can never be read as covering everything.\n */\nexport type ActorSpaceCoverage = readonly string[] | \"tenant-wide\";\n\n/**\n * Identity resolved from a verified credential. Every governed action,\n * projection decision, grant and audit record derives from actor context, so\n * this is the shape a gateway must produce before the platform is called.\n *\n * It carries no credential material. `credentialId` is an opaque, non-secret\n * reference retained for audit, matching the convention used by\n * `authorizationBindingId`.\n */\nexport interface ActorClaims {\n\t/** Stable subject identifier; becomes `actorId` on a governed submission. */\n\tsubject: string;\n\tactorType: IdentityActorType;\n\ttenantId: string;\n\tspaceIds: ActorSpaceCoverage;\n\t/** Granted scopes, if the issuer expresses authority that way. */\n\tscopes?: readonly string[];\n\tissuer: string;\n\t/** RFC 3339 timestamps. */\n\tissuedAt: string;\n\texpiresAt: string;\n\t/** Opaque, non-secret reference to the presented credential, for audit. */\n\tcredentialId?: string;\n}\n\n/**\n * Verifies a presented credential and resolves it to actor claims.\n *\n * An implementation returns `null` for any credential it cannot positively\n * verify — expired, malformed, wrong issuer, bad signature. It never returns\n * partially trusted claims, and it never echoes credential material back.\n */\nexport interface IdentityPort {\n\tverify(credential: string): Promise<ActorClaims | null>;\n}\n\nexport type ActorScopeRejection =\n\t| \"malformed_claims\"\n\t| \"expired\"\n\t| \"not_yet_valid\"\n\t| \"tenant_mismatch\"\n\t| \"space_not_covered\"\n\t| \"unknown_actor_type\";\n\nexport class ActorScopeError extends Error {\n\toverride readonly name = \"ActorScopeError\";\n\tconstructor(\n\t\treadonly rejection: ActorScopeRejection,\n\t\tmessage: string,\n\t) {\n\t\tsuper(message);\n\t}\n}\n\n/**\n * Confirm verified claims actually cover the tenant and space being acted on.\n *\n * Verification proves who the caller is. It does not prove they may act here.\n * Calling this before a governed submission is what stops a valid credential\n * for one tenant from being replayed against another.\n */\nexport function assertActorClaimsCoverScope(\n\tclaims: ActorClaims,\n\tscope: { tenantId: string; spaceId: string },\n\tnow: Date = new Date(),\n): void {\n\t// Every comparison against an invalid clock is false, which would let an\n\t// expired credential through. Reject the clock before trusting it.\n\tconst currentTime = now.getTime();\n\tif (Number.isNaN(currentTime)) {\n\t\tthrow new ActorScopeError(\"malformed_claims\", \"Actor scope was evaluated against an invalid clock.\");\n\t}\n\n\tif (typeof claims.actorType !== \"string\" || !IDENTITY_ACTOR_TYPES.includes(claims.actorType)) {\n\t\tthrow new ActorScopeError(\"unknown_actor_type\", `Actor type \"${String(claims.actorType)}\" is not a known actor kind.`);\n\t}\n\tif (typeof claims.subject !== \"string\" || claims.subject.length === 0) {\n\t\tthrow new ActorScopeError(\"malformed_claims\", \"Actor claims carry no subject.\");\n\t}\n\tif (typeof claims.tenantId !== \"string\" || claims.tenantId.length === 0) {\n\t\tthrow new ActorScopeError(\"malformed_claims\", \"Actor claims carry no tenant.\");\n\t}\n\n\t// Date.parse accepts timezone-less strings and reads them in the host's\n\t// local zone, so the same credential would expire at different instants on\n\t// different machines. Require an explicit offset.\n\tconst issuedAt = parseRfc3339(claims.issuedAt);\n\tconst expiresAt = parseRfc3339(claims.expiresAt);\n\tif (issuedAt === undefined || expiresAt === undefined) {\n\t\tthrow new ActorScopeError(\"malformed_claims\", \"Actor claims carry an issuedAt or expiresAt that is not an RFC 3339 timestamp with an explicit offset.\");\n\t}\n\tif (currentTime >= expiresAt) {\n\t\tthrow new ActorScopeError(\"expired\", `Actor claims expired at ${claims.expiresAt}.`);\n\t}\n\tif (currentTime < issuedAt) {\n\t\tthrow new ActorScopeError(\"not_yet_valid\", `Actor claims are not valid until ${claims.issuedAt}.`);\n\t}\n\n\tif (claims.tenantId !== scope.tenantId) {\n\t\tthrow new ActorScopeError(\n\t\t\t\"tenant_mismatch\",\n\t\t\t`Actor claims cover tenant \"${claims.tenantId}\" but the request targets \"${scope.tenantId}\".`,\n\t\t);\n\t}\n\n\t// A malformed adapter returning a bare string would otherwise reach\n\t// String.prototype.includes, where \"space_10\" covers \"space_1\".\n\tif (claims.spaceIds === \"tenant-wide\") return;\n\tif (!Array.isArray(claims.spaceIds) || !claims.spaceIds.every((space) => typeof space === \"string\")) {\n\t\tthrow new ActorScopeError(\"malformed_claims\", 'Actor claims spaceIds must be an array of strings or the literal \"tenant-wide\".');\n\t}\n\tif (!claims.spaceIds.includes(scope.spaceId)) {\n\t\tthrow new ActorScopeError(\n\t\t\t\"space_not_covered\",\n\t\t\t`Actor claims do not cover space \"${scope.spaceId}\".`,\n\t\t);\n\t}\n}\n\n/** RFC 3339 with a mandatory offset, so an instant means the same thing everywhere. */\nconst RFC3339 = /^\\d{4}-\\d{2}-\\d{2}[Tt]\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:[Zz]|[+-]\\d{2}:\\d{2})$/;\n\nfunction parseRfc3339(value: string): number | undefined {\n\tif (typeof value !== \"string\" || !RFC3339.test(value)) return undefined;\n\tconst parsed = Date.parse(value);\n\treturn Number.isNaN(parsed) ? undefined : parsed;\n}\n\n/**\n * The actor fields a governed submission needs, derived from verified claims\n * after {@link assertActorClaimsCoverScope} has accepted them. Taking these\n * from claims rather than from request input is what keeps the audit trail\n * tied to something that was actually proven.\n */\nexport function actorContextFromClaims(\n\tclaims: ActorClaims,\n\tscope: { tenantId: string; spaceId: string },\n\tnow: Date = new Date(),\n): { actorId: string; actorType: IdentityActorType; tenantId: string; spaceId: string } {\n\tassertActorClaimsCoverScope(claims, scope, now);\n\treturn {\n\t\tactorId: claims.subject,\n\t\tactorType: claims.actorType,\n\t\ttenantId: claims.tenantId,\n\t\tspaceId: scope.spaceId,\n\t};\n}\n\n// ── Content (headless CMS-shaped) ───────────────────────────────────────────\n\n/**\n * A resolved piece of authored content.\n *\n * Content is copy and layout, never permission. A content system deciding what\n * a screen says is expected; a content system deciding what a screen may reach\n * is the failure this whole boundary exists to prevent, which is why nothing\n * here carries a capability reference.\n */\nexport interface ContentEntry {\n\tkey: string;\n\tlocale: string;\n\t/** Opaque revision, stable for identical content. Use it for cache keys. */\n\trevision: string;\n\tvalue: JsonLike;\n}\n\nexport type JsonLike = string | number | boolean | null | JsonLike[] | { [key: string]: JsonLike };\n\nexport interface ContentQuery {\n\tkey: string;\n\tlocale: string;\n\t/** Optional variant, for an experiment arm already enumerated in a release. */\n\tvariant?: string;\n}\n\nexport interface ContentPort {\n\t/** Resolves to `null` when the key is not authored, rather than inventing a default. */\n\tresolve(query: ContentQuery): Promise<ContentEntry | null>;\n}\n\n// ── Payments ────────────────────────────────────────────────────────────────\n\n/**\n * Money as an integer in the currency's minor unit.\n *\n * Never a float. A payment expressed as 10.1 is a payment that will eventually\n * be off by a cent, and reconciling that costs more than the type ever did.\n */\nexport interface MinorUnitAmount {\n\t/** Integer in the minor unit: 1050 is USD 10.50. */\n\tamount: number;\n\t/** ISO 4217 alphabetic code. */\n\tcurrency: string;\n}\n\n/**\n * The outcome of asking a provider to move money.\n *\n * `ambiguous` is the one that matters and the one most interfaces omit. A\n * timeout tells you nothing about whether the charge landed, and guessing is\n * how a customer gets billed twice. It maps onto the platform's own\n * `AdapterOutcomeKind`, so an ambiguous payment routes to reconciliation with\n * durable evidence instead of being retried.\n */\nexport type PaymentOutcome = \"succeeded\" | \"failed\" | \"ambiguous\";\n\nexport interface PaymentResult {\n\toutcome: PaymentOutcome;\n\t/** The provider's own identifier, for reconciliation. Required when known. */\n\tproviderReference?: string;\n\t/** Provider-supplied reason, for evidence rather than for branching. */\n\treason?: string;\n}\n\nexport interface PaymentRequest {\n\t/** Caller-stable key. The same key must never move money twice. */\n\tidempotencyKey: string;\n\tamount: MinorUnitAmount;\n}\n\nexport interface PaymentsPort {\n\tcharge(request: PaymentRequest): Promise<PaymentResult>;\n}\n\n// ── Search and recommendation ───────────────────────────────────────────────\n\n/**\n * A latency-critical read path, deliberately outside the governed pipeline.\n *\n * Search results are pointers, not authority. An identifier appearing in a\n * result set says the index knows about it, never that this actor may read it,\n * so anything the viewer then opens still goes through `ProjectionHost`.\n */\nexport interface SearchHit {\n\t/** Identifier a governed read can resolve. Never the record itself. */\n\tid: string;\n\tscore: number;\n}\n\nexport interface SearchQuery {\n\ttext: string;\n\tlimit: number;\n\t/** Narrowing the index can apply cheaply. Never a substitute for authorization. */\n\tfilters?: Record<string, string>;\n}\n\nexport interface SearchPort {\n\tquery(query: SearchQuery): Promise<{ hits: SearchHit[]; total: number }>;\n}\n\n// ── Customer relationship ───────────────────────────────────────────────────\n\n/**\n * An outbound record of something that already happened.\n *\n * A CRM is downstream of the governed pipeline, never upstream of it. It is\n * told; it does not decide. Keeping this one-way is what stops a marketing\n * system becoming a source of business truth.\n */\nexport interface CustomerEvent {\n\t/** Stable key so redelivery does not duplicate the record. */\n\teventId: string;\n\tsubjectId: string;\n\ttype: string;\n\toccurredAt: string;\n\tattributes?: Record<string, JsonLike>;\n}\n\nexport interface CustomerRecordPort {\n\trecord(event: CustomerEvent): Promise<void>;\n}\n\n// ── Defining a port ─────────────────────────────────────────────────────────\n\n/**\n * A port, as a first-class thing rather than a name in a string.\n *\n * Fabric ships a handful of port definitions because they speak open standards\n * and everyone needs them. It cannot ship the rest: an enterprise integrates\n * hundreds of external systems, and a framework that requires a pull request\n * for each one is not a framework. A vertical, a partner or a vendor defines\n * its own port with {@link definePort} and every mechanism here applies to it\n * unchanged — Fabric never learns what the system behind it is.\n *\n * The definition binds an id to the suite that certifies an adapter for it.\n * That binding is the point: without it, \"this port is satisfied\" only ever\n * meant \"somebody registered something claiming to be it\".\n */\nexport interface PortDefinition<TPort, TFixtures = void> {\n\t/**\n\t * Namespaced identifier, for example `fabric.flags` or `acme.docusign`.\n\t * Namespacing is required so a port defined outside this repository cannot\n\t * collide with one defined inside it.\n\t */\n\tid: string;\n\t/**\n\t * Version of the port contract itself, not of any adapter.\n\t *\n\t * Bump it when the interface changes shape. Certification is recorded\n\t * against a version, so raising it correctly invalidates every adapter\n\t * certified against the old contract instead of silently carrying them\n\t * forward.\n\t */\n\tversion: string;\n\t/** The open standard this port speaks, where one exists. */\n\tstandard?: { name: string; version?: string };\n\t/** One-line statement of what an adapter behind this port is responsible for. */\n\tdescription: string;\n\t/** The suite every adapter must pass. */\n\tchecks(fixtures: TFixtures): readonly PortCheck<TPort>[];\n}\n\n// Segments after the first take exactly the manifest's grammar, so every\n// namespaced name a capability can declare is a name a port can define. The\n// one shape a manifest permits that this does not is a *dotless* name such as\n// \"flags\", by design: namespacing is what keeps a port defined outside this\n// repository from colliding with one defined inside it, and a dotless\n// requirement has no namespace to protect.\nconst PORT_ID = /^[a-z][a-z0-9-]*(?:\\.[a-z0-9-]+)+$/;\n\n/**\n * Declare a port. Validates the definition itself, because a malformed port\n * definition produces adapters that certify against nothing.\n */\nexport function definePort<TPort, TFixtures = void>(\n\tdefinition: PortDefinition<TPort, TFixtures>,\n): PortDefinition<TPort, TFixtures> {\n\tif (!PORT_ID.test(definition.id)) {\n\t\tthrow new Error(`Port id \"${definition.id}\" must be namespaced lowercase, for example \"acme.docusign\".`);\n\t}\n\tif (!/^\\d+\\.\\d+\\.\\d+$/.test(definition.version)) {\n\t\tthrow new Error(`Port \"${definition.id}\" version must be a semver version.`);\n\t}\n\tif (!definition.description.trim()) {\n\t\tthrow new Error(`Port \"${definition.id}\" must describe what an adapter behind it is responsible for.`);\n\t}\n\tif (typeof definition.checks !== \"function\") {\n\t\tthrow new Error(`Port \"${definition.id}\" must supply a conformance suite.`);\n\t}\n\treturn definition;\n}\n\n/**\n * Confirm a port's suite can actually fail, and that its check ids are unique.\n *\n * A suite whose checks all pass against a deliberately broken adapter certifies\n * nothing while looking rigorous, which is worse than having no suite at all.\n * Run this against a stub that does the wrong thing when you author a port.\n */\nexport async function assertPortSuiteHasTeeth<TPort, TFixtures>(\n\tdefinition: PortDefinition<TPort, TFixtures>,\n\tfixtures: TFixtures,\n\tbrokenAdapters: TPort | readonly TPort[],\n): Promise<void> {\n\tconst checks = definition.checks(fixtures);\n\tif (checks.length === 0) {\n\t\tthrow new Error(`Port \"${definition.id}\" declares no checks, so no adapter can be certified against it.`);\n\t}\n\tconst ids = new Set<string>();\n\tfor (const check of checks) {\n\t\tif (ids.has(check.id)) throw new Error(`Port \"${definition.id}\" declares check \"${check.id}\" twice.`);\n\t\tids.add(check.id);\n\t}\n\t// Every check must be caught by *some* adapter in the set, not all of them\n\t// by one. Demanding a single stub fail every check is unsatisfiable for any\n\t// suite containing a fixture-liveness guard, because such a guard bites on\n\t// the complement of what the checks it guards bite on: an adapter returning\n\t// nothing trips the guard, and an adapter returning something malformed\n\t// trips the checks. Supply one adapter per way of being wrong.\n\tconst adapters = Array.isArray(brokenAdapters) ? brokenAdapters : [brokenAdapters as TPort];\n\tif (adapters.length === 0) {\n\t\tthrow new Error(`Port \"${definition.id}\" needs at least one deliberately broken adapter to prove its suite bites.`);\n\t}\n\n\tconst uncaught = new Set(checks.map((check) => check.id));\n\tfor (const adapter of adapters) {\n\t\tfor (const check of checks) {\n\t\t\tif (!uncaught.has(check.id)) continue;\n\t\t\ttry {\n\t\t\t\tawait check.run(adapter);\n\t\t\t} catch {\n\t\t\t\tuncaught.delete(check.id);\n\t\t\t}\n\t\t}\n\t}\n\tif (uncaught.size > 0) {\n\t\tthrow new Error(\n\t\t\t`Port \"${definition.id}\" has ${uncaught.size} check(s) that no supplied broken adapter trips, so they prove nothing: ${[...uncaught].join(\", \")}.`,\n\t\t);\n\t}\n}\n\n// ── Certifying an adapter ───────────────────────────────────────────────────\n\n/** Evidence that an adapter passed a port's suite, and which contract it passed. */\nexport interface AdapterCertification {\n\tportId: string;\n\t/** Port contract version the adapter was certified against. */\n\tportVersion: string;\n\tchecks: string[];\n\tcertifiedAt: string;\n}\n\nexport interface CertifiedAdapter extends RegisteredAdapter {\n\tcertification: AdapterCertification;\n}\n\n/**\n * Run a port's suite against an adapter and record what it passed.\n *\n * Registration is a claim; certification is evidence. Deployment gates can then\n * require the second rather than accepting the first.\n */\nexport async function certifyAdapter<TPort, TFixtures>(input: {\n\tdefinition: PortDefinition<TPort, TFixtures>;\n\tfixtures: TFixtures;\n\tadapter: TPort;\n\tvendor: string;\n\tversion?: string;\n\tnow?: Date;\n}): Promise<CertifiedAdapter> {\n\t// Validate the definition here too: a definition not built through\n\t// definePort can carry a version like \"1.0\", and the certification it\n\t// produces is then reported downstream as missing rather than malformed.\n\tdefinePort(input.definition);\n\tconst checks = input.definition.checks(input.fixtures);\n\tif (checks.length === 0) {\n\t\tthrow new Error(`Port \"${input.definition.id}\" declares no checks, so no adapter can be certified against it.`);\n\t}\n\tconst passed: string[] = [];\n\tfor (const check of checks) {\n\t\ttry {\n\t\t\tawait check.run(input.adapter);\n\t\t} catch (error) {\n\t\t\tthrow new Error(\n\t\t\t\t`Adapter \"${input.vendor}\" failed port \"${input.definition.id}\" check \"${check.id}\": ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t);\n\t\t}\n\t\tpassed.push(check.id);\n\t}\n\treturn {\n\t\tport: input.definition.id,\n\t\tvendor: input.vendor,\n\t\t...(input.version === undefined ? {} : { version: input.version }),\n\t\t...(input.definition.standard ? { standard: input.definition.standard } : {}),\n\t\tcertification: {\n\t\t\tportId: input.definition.id,\n\t\t\tportVersion: input.definition.version,\n\t\t\tchecks: passed,\n\t\t\tcertifiedAt: (input.now ?? new Date()).toISOString(),\n\t\t},\n\t};\n}\n\n/**\n * Whether an adapter carries certification evidence *for this port*.\n *\n * Testing only that a `certification` property exists made the evidence a claim\n * again: any hand-written object with the right property name satisfied the\n * gate. The evidence has to be internally consistent and about the port being\n * required, or it is decoration.\n */\nfunction isCertifiedFor(adapter: RegisteredAdapter, portName: string): adapter is CertifiedAdapter {\n\tconst certification = (adapter as CertifiedAdapter).certification;\n\tif (!certification || typeof certification !== \"object\") return false;\n\tif (certification.portId !== portName) return false;\n\tif (certification.portId !== adapter.port) return false;\n\tif (!/^\\d+\\.\\d+\\.\\d+$/.test(certification.portVersion ?? \"\")) return false;\n\tif (!Array.isArray(certification.checks) || certification.checks.length === 0) return false;\n\tif (Number.isNaN(Date.parse(certification.certifiedAt ?? \"\"))) return false;\n\treturn true;\n}\n\n// ── Requirement satisfaction ────────────────────────────────────────────────\n\nexport interface PortRequirement {\n\tname: string;\n\tversion?: string;\n\tstandard?: { name: string; version?: string };\n}\n\n/** The subset of capability metadata that declares what ports it needs. */\nexport interface PortRequiringCapability {\n\tnamespace: string;\n\trequirements?: { ports?: PortRequirement[] };\n}\n\nexport interface RegisteredAdapter {\n\t/** Port this adapter implements, matching the requirement's `name`. */\n\tport: string;\n\tvendor: string;\n\tversion?: string;\n\tstandard?: { name: string; version?: string };\n}\n\nexport type PortFindingCode =\n\t| \"unsatisfied_port\"\n\t| \"standard_not_spoken\"\n\t| \"version_mismatch\"\n\t| \"uncertified_adapter\"\n\t| \"stale_certification\";\n\nexport interface PortFinding {\n\tcode: PortFindingCode;\n\tport: string;\n\tmessage: string;\n}\n\nexport interface PortValidationResult {\n\tvalid: boolean;\n\tfindings: PortFinding[];\n}\n\n/**\n * Checks that every port a capability declares is backed by a registered adapter.\n * `CapabilityPortRequirement` is otherwise a name that resolves against nothing;\n * this is what turns the declaration into a deployment-time gate.\n *\n * Version matching is exact. Range negotiation belongs to whatever installs the\n * adapters, and pretending to do semver here would be worse than not doing it.\n */\nexport function validatePortRequirements(input: {\n\tcapability: PortRequiringCapability;\n\tadapters: readonly RegisteredAdapter[];\n\t/**\n\t * Port definitions in force. Supplying them checks that whatever\n\t * certification is present was issued against the current contract version.\n\t *\n\t * They do not by themselves require certification to exist: pass\n\t * `requireCertification` for that. Definitions alone catch a stale\n\t * certification, not a missing one, and an adapter carrying none passes.\n\t */\n\tdefinitions?: readonly PortDefinition<never, never>[];\n\t/** Require certification for every required port. Defaults to false. */\n\trequireCertification?: boolean;\n}): PortValidationResult {\n\tconst definitions = new Map((input.definitions ?? []).map((definition) => [definition.id, definition]));\n\tconst findings: PortFinding[] = [];\n\tfor (const requirement of input.capability.requirements?.ports ?? []) {\n\t\tconst candidates = input.adapters.filter((adapter) => adapter.port === requirement.name);\n\t\tif (candidates.length === 0) {\n\t\t\tfindings.push({\n\t\t\t\tcode: \"unsatisfied_port\",\n\t\t\t\tport: requirement.name,\n\t\t\t\tmessage: `capability \"${input.capability.namespace}\" requires port \"${requirement.name}\" and no adapter is registered for it`,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\t// Narrowed as each constraint is applied, so one adapter cannot satisfy\n\t\t// the standard while a different one satisfies the version.\n\t\tlet eligible = candidates;\n\t\tif (requirement.standard) {\n\t\t\teligible = eligible.filter((adapter) => adapter.standard?.name === requirement.standard!.name);\n\t\t\tif (eligible.length === 0) {\n\t\t\t\tfindings.push({\n\t\t\t\t\tcode: \"standard_not_spoken\",\n\t\t\t\t\tport: requirement.name,\n\t\t\t\t\tmessage: `port \"${requirement.name}\" must speak \"${requirement.standard.name}\"; registered adapters are ${candidates.map((adapter) => `${adapter.vendor}(${adapter.standard?.name ?? \"no standard\"})`).join(\", \")}`,\n\t\t\t\t});\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (requirement.standard.version) {\n\t\t\t\tconst atVersion = eligible.filter((adapter) => adapter.standard?.version === requirement.standard!.version);\n\t\t\t\tif (atVersion.length === 0) {\n\t\t\t\t\tfindings.push({\n\t\t\t\t\t\tcode: \"standard_not_spoken\",\n\t\t\t\t\t\tport: requirement.name,\n\t\t\t\t\t\tmessage: `port \"${requirement.name}\" must speak \"${requirement.standard.name}\" version \"${requirement.standard.version}\"; registered adapters speak ${eligible.map((adapter) => adapter.standard?.version ?? \"an unstated version\").join(\", \")}`,\n\t\t\t\t\t});\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\teligible = atVersion;\n\t\t\t}\n\t\t}\n\t\tif (requirement.version) {\n\t\t\tconst atVersion = eligible.filter((adapter) => adapter.version === requirement.version);\n\t\t\tif (atVersion.length === 0) {\n\t\t\t\tfindings.push({\n\t\t\t\t\tcode: \"version_mismatch\",\n\t\t\t\t\tport: requirement.name,\n\t\t\t\t\tmessage: `port \"${requirement.name}\" requires version \"${requirement.version}\"; eligible adapters are ${eligible.map((adapter) => `${adapter.vendor}@${adapter.version ?? \"unversioned\"}`).join(\", \")}`,\n\t\t\t\t});\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\teligible = atVersion;\n\t\t}\n\n\t\t// Registration is a claim. Certification is evidence that the adapter\n\t\t// passed the port's own suite, against the contract version in force.\n\t\tconst definition = definitions.get(requirement.name);\n\t\tif (input.requireCertification || definition) {\n\t\t\tconst certified = eligible.filter((adapter) => isCertifiedFor(adapter, requirement.name));\n\t\t\tif (certified.length === 0) {\n\t\t\t\tif (input.requireCertification) {\n\t\t\t\t\tfindings.push({\n\t\t\t\t\t\tcode: \"uncertified_adapter\",\n\t\t\t\t\t\tport: requirement.name,\n\t\t\t\t\t\tmessage: `port \"${requirement.name}\" has eligible adapters (${eligible.map((adapter) => adapter.vendor).join(\", \")}) but none carries certification evidence`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (definition && !certified.some((adapter) => adapter.certification.portVersion === definition.version)) {\n\t\t\t\tfindings.push({\n\t\t\t\t\tcode: \"stale_certification\",\n\t\t\t\t\tport: requirement.name,\n\t\t\t\t\tmessage: `port \"${requirement.name}\" is at contract version ${definition.version}; adapters are certified against ${certified.map((adapter) => `${adapter.vendor}@${adapter.certification.portVersion}`).join(\", \")}`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\treturn { valid: findings.length === 0, findings };\n}\n\nexport function assertPortRequirementsSatisfied(input: {\n\tcapability: PortRequiringCapability;\n\tadapters: readonly RegisteredAdapter[];\n\tdefinitions?: readonly PortDefinition<never, never>[];\n\trequireCertification?: boolean;\n}): void {\n\tconst result = validatePortRequirements(input);\n\tif (result.valid) return;\n\tthrow new Error([\n\t\t`Port requirements for \"${input.capability.namespace}\" are not satisfied:`,\n\t\t...result.findings.map((finding) => ` - ${finding.message}`),\n\t].join(\"\\n\"));\n}\n\n// ── Adapter contract kit ────────────────────────────────────────────────────\n\nexport interface PortCheck<TPort> {\n\tid: string;\n\ttitle: string;\n\t/** Throws on failure, exactly as an assertion would. */\n\trun(port: TPort): Promise<void>;\n}\n\nclass PortContractFailure extends Error {\n\toverride readonly name = \"PortContractFailure\";\n}\n\nfunction expect(condition: unknown, message: string): asserts condition {\n\tif (!condition) throw new PortContractFailure(message);\n}\n\n/**\n * Every flags adapter must pass these, so swapping vendors is an adapter build\n * plus a configuration change rather than a migration.\n */\nexport function flagsPortChecks(): PortCheck<FlagsPort>[] {\n\tconst unknownKey = \"fabric.contract.definitely-not-configured\";\n\treturn [\n\t\t{\n\t\t\tid: \"flags.default-on-unknown-key\",\n\t\t\ttitle: \"an unknown flag resolves to the supplied default rather than throwing\",\n\t\t\tasync run(port) {\n\t\t\t\tconst result = await port.resolveBoolean(unknownKey, true);\n\t\t\t\texpect(result.value === true, `an unknown flag returned ${String(result.value)} instead of the supplied default`);\n\t\t\t\texpect(\n\t\t\t\t\tresult.reason === \"DEFAULT\" || result.reason === \"ERROR\",\n\t\t\t\t\t`an unknown flag resolved with reason \"${result.reason}\"; a default or error was expected`,\n\t\t\t\t);\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"flags.default-is-typed\",\n\t\t\ttitle: \"each typed resolver returns its own type\",\n\t\t\tasync run(port) {\n\t\t\t\texpect(typeof (await port.resolveBoolean(unknownKey, false)).value === \"boolean\", \"resolveBoolean did not return a boolean\");\n\t\t\t\texpect(typeof (await port.resolveString(unknownKey, \"fallback\")).value === \"string\", \"resolveString did not return a string\");\n\t\t\t\texpect(typeof (await port.resolveNumber(unknownKey, 42)).value === \"number\", \"resolveNumber did not return a number\");\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"flags.evaluation-is-pure\",\n\t\t\ttitle: \"the same key and context resolve the same way twice\",\n\t\t\tasync run(port) {\n\t\t\t\tconst context = { targetingKey: \"fabric-contract-subject\" };\n\t\t\t\tconst first = await port.resolveString(unknownKey, \"fallback\", context);\n\t\t\t\tconst second = await port.resolveString(unknownKey, \"fallback\", context);\n\t\t\t\texpect(first.value === second.value, `the same evaluation returned \"${first.value}\" then \"${second.value}\"`);\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"flags.tolerates-absent-context\",\n\t\t\ttitle: \"evaluation without a context does not throw\",\n\t\t\tasync run(port) {\n\t\t\t\tawait port.resolveBoolean(unknownKey, false);\n\t\t\t},\n\t\t},\n\t];\n}\n\n/**\n * The suite an identity adapter must pass before it can stand behind\n * `IdentityPort`. Every check here is a fail-closed property: the cost of\n * getting one wrong is a credential being trusted further than it proves.\n *\n * `validCredential` must be a credential the adapter verifies successfully,\n * and `expected` the claims it should resolve to.\n */\nexport function identityPortChecks(fixtures: {\n\tvalidCredential: string;\n\texpected: Pick<ActorClaims, \"subject\" | \"tenantId\">;\n\texpiredCredential?: string;\n}): PortCheck<IdentityPort>[] {\n\tconst checks: PortCheck<IdentityPort>[] = [\n\t\t{\n\t\t\tid: \"identity.rejects-garbage\",\n\t\t\ttitle: \"an unverifiable credential resolves to null rather than partial claims\",\n\t\t\tasync run(port) {\n\t\t\t\tconst result = await port.verify(\"not-a-credential\");\n\t\t\t\texpect(result === null, \"an unverifiable credential resolved to claims instead of null\");\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"identity.rejects-empty\",\n\t\t\ttitle: \"an empty credential resolves to null\",\n\t\t\tasync run(port) {\n\t\t\t\texpect((await port.verify(\"\")) === null, \"an empty credential resolved to claims\");\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"identity.resolves-valid\",\n\t\t\ttitle: \"a valid credential resolves to the expected subject and tenant\",\n\t\t\tasync run(port) {\n\t\t\t\tconst claims = await port.verify(fixtures.validCredential);\n\t\t\t\texpect(claims !== null, \"a valid credential failed to verify\");\n\t\t\t\texpect(claims?.subject === fixtures.expected.subject, `subject was \"${claims?.subject}\"`);\n\t\t\t\texpect(claims?.tenantId === fixtures.expected.tenantId, `tenantId was \"${claims?.tenantId}\"`);\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"identity.claims-are-complete\",\n\t\t\ttitle: \"resolved claims carry every field the platform derives actor context from\",\n\t\t\tasync run(port) {\n\t\t\t\tconst claims = await port.verify(fixtures.validCredential);\n\t\t\t\texpect(claims !== null, \"a valid credential failed to verify\");\n\t\t\t\tif (!claims) return;\n\t\t\t\texpect(IDENTITY_ACTOR_TYPES.includes(claims.actorType), `actorType \"${claims.actorType}\" is not a known actor kind`);\n\t\t\t\texpect(typeof claims.issuer === \"string\" && claims.issuer.length > 0, \"claims carry no issuer\");\n\t\t\t\t// The same grammar assertActorClaimsCoverScope enforces. Certifying\n\t\t\t\t// a looser one produces an adapter that passes here and is refused\n\t\t\t\t// on every request.\n\t\t\t\texpect(RFC3339.test(claims.issuedAt), `issuedAt \"${claims.issuedAt}\" is not RFC 3339 with an explicit offset`);\n\t\t\t\texpect(RFC3339.test(claims.expiresAt), `expiresAt \"${claims.expiresAt}\" is not RFC 3339 with an explicit offset`);\n\t\t\t\texpect(typeof claims.tenantId === \"string\" && claims.tenantId.length > 0, \"claims carry no tenant\");\n\t\t\t\texpect(\n\t\t\t\t\tclaims.spaceIds === \"tenant-wide\" || Array.isArray(claims.spaceIds),\n\t\t\t\t\t\"spaceIds must be an explicit list or the literal \\\"tenant-wide\\\"\",\n\t\t\t\t);\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"identity.carries-no-credential-material\",\n\t\t\ttitle: \"resolved claims never echo the credential back\",\n\t\t\tasync run(port) {\n\t\t\t\tconst claims = await port.verify(fixtures.validCredential);\n\t\t\t\texpect(claims !== null, \"a valid credential failed to verify, so this check proved nothing\");\n\t\t\t\tif (!claims) return;\n\t\t\t\tconst serialized = JSON.stringify(claims);\n\t\t\t\texpect(\n\t\t\t\t\t!serialized.includes(fixtures.validCredential),\n\t\t\t\t\t\"resolved claims contain the presented credential; claims must carry an opaque reference instead\",\n\t\t\t\t);\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"identity.verification-is-stable\",\n\t\t\ttitle: \"the same credential resolves the same subject twice\",\n\t\t\tasync run(port) {\n\t\t\t\tconst first = await port.verify(fixtures.validCredential);\n\t\t\t\tconst second = await port.verify(fixtures.validCredential);\n\t\t\t\texpect(first?.subject === second?.subject, \"the same credential resolved to two different subjects\");\n\t\t\t},\n\t\t},\n\t];\n\n\tif (fixtures.expiredCredential !== undefined) {\n\t\tchecks.push({\n\t\t\tid: \"identity.rejects-expired\",\n\t\t\ttitle: \"an expired credential resolves to null rather than stale claims\",\n\t\t\tasync run(port) {\n\t\t\t\tconst expiredCredential = fixtures.expiredCredential as string;\n\t\t\t\texpect((await port.verify(expiredCredential)) === null, \"an expired credential still resolved to claims\");\n\t\t\t},\n\t\t});\n\t}\n\n\treturn checks;\n}\n\n/** The suite a content adapter must pass. */\nexport function contentPortChecks(fixtures: {\n\tpresent: ContentQuery;\n\tabsentKey: string;\n}): PortCheck<ContentPort>[] {\n\treturn [\n\t\t{\n\t\t\tid: \"content.missing-resolves-null\",\n\t\t\ttitle: \"an unauthored key resolves to null rather than an invented default\",\n\t\t\tasync run(port) {\n\t\t\t\tconst result = await port.resolve({ ...fixtures.present, key: fixtures.absentKey });\n\t\t\t\texpect(result === null, \"an unauthored key resolved to content instead of null\");\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"content.revision-is-stable\",\n\t\t\ttitle: \"identical content resolves the same revision twice\",\n\t\t\tasync run(port) {\n\t\t\t\tconst first = await port.resolve(fixtures.present);\n\t\t\t\tconst second = await port.resolve(fixtures.present);\n\t\t\t\texpect(first !== null && second !== null, \"the fixture key is not authored\");\n\t\t\t\texpect(first?.revision === second?.revision, \"the same content reported two revisions, so it cannot be cached\");\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"content.carries-no-capability-reference\",\n\t\t\ttitle: \"authored content never carries a capability reference\",\n\t\t\tasync run(port) {\n\t\t\t\tconst result = await port.resolve(fixtures.present);\n\t\t\t\texpect(\n\t\t\t\t\t!JSON.stringify(result ?? {}).includes(\"capability://\"),\n\t\t\t\t\t\"content carried a capability reference; what a screen may reach is decided by a release, not by an author\",\n\t\t\t\t);\n\t\t\t},\n\t\t},\n\t];\n}\n\n/** The suite a payments adapter must pass. */\nexport function paymentsPortChecks(fixtures: {\n\trequest: PaymentRequest;\n}): PortCheck<PaymentsPort>[] {\n\treturn [\n\t\t{\n\t\t\tid: \"payments.rejects-non-integer-amount\",\n\t\t\ttitle: \"a fractional minor-unit amount is refused rather than rounded\",\n\t\t\tasync run(port) {\n\t\t\t\tlet refused = false;\n\t\t\t\ttry {\n\t\t\t\t\tawait port.charge({ ...fixtures.request, amount: { ...fixtures.request.amount, amount: 10.5 } });\n\t\t\t\t} catch {\n\t\t\t\t\trefused = true;\n\t\t\t\t}\n\t\t\t\texpect(refused, \"a fractional minor-unit amount was accepted; money is an integer or it drifts\");\n\t\t\t\t// The same request without the fraction must actually charge, or an\n\t\t\t\t// adapter that refuses everything, or succeeds at nothing, passes\n\t\t\t\t// every check in this suite.\n\t\t\t\tconst control = await port.charge({\n\t\t\t\t\t...fixtures.request,\n\t\t\t\t\tidempotencyKey: `${fixtures.request.idempotencyKey}:integer-probe`,\n\t\t\t\t});\n\t\t\t\texpect(\n\t\t\t\t\tcontrol.outcome === \"succeeded\",\n\t\t\t\t\t`the fixture charge resolved \"${control.outcome}\"; a suite run against an adapter that never succeeds certifies nothing`,\n\t\t\t\t);\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"payments.requires-idempotency-key\",\n\t\t\ttitle: \"a charge without a stable key is refused\",\n\t\t\tasync run(port) {\n\t\t\t\tlet refused = false;\n\t\t\t\ttry {\n\t\t\t\t\tawait port.charge({ ...fixtures.request, idempotencyKey: \"\" });\n\t\t\t\t} catch {\n\t\t\t\t\trefused = true;\n\t\t\t\t}\n\t\t\t\texpect(refused, \"a charge with no idempotency key was accepted; a retry would move money twice\");\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"payments.same-key-moves-money-once\",\n\t\t\ttitle: \"the same idempotency key resolves to the same provider reference\",\n\t\t\tasync run(port) {\n\t\t\t\tconst first = await port.charge(fixtures.request);\n\t\t\t\tconst second = await port.charge(fixtures.request);\n\t\t\t\texpect(\n\t\t\t\t\tfirst.outcome === second.outcome,\n\t\t\t\t\t`the same key produced \"${first.outcome}\" then \"${second.outcome}\"`,\n\t\t\t\t);\n\t\t\t\t// Without a reference there is nothing to compare, and a\n\t\t\t\t// double-charger would pass on outcome equality alone. A\n\t\t\t\t// succeeded charge must be identifiable or it cannot be reconciled.\n\t\t\t\texpect(\n\t\t\t\t\tfirst.outcome !== \"succeeded\" || first.providerReference !== undefined,\n\t\t\t\t\t\"a succeeded charge carried no provider reference, so a retry cannot be told from a second charge\",\n\t\t\t\t);\n\t\t\t\texpect(\n\t\t\t\t\tfirst.providerReference === second.providerReference,\n\t\t\t\t\t\"the same key produced two provider references, so a retry charged twice\",\n\t\t\t\t);\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"payments.outcome-is-declared\",\n\t\t\ttitle: \"an outcome is one of the three the platform can act on\",\n\t\t\tasync run(port) {\n\t\t\t\tconst result = await port.charge(fixtures.request);\n\t\t\t\texpect(\n\t\t\t\t\tresult.outcome === \"succeeded\" || result.outcome === \"failed\" || result.outcome === \"ambiguous\",\n\t\t\t\t\t`outcome \"${result.outcome}\" is not one the platform can reconcile`,\n\t\t\t\t);\n\t\t\t},\n\t\t},\n\t];\n}\n\n/** The suite a search adapter must pass. */\nexport function searchPortChecks(fixtures: {\n\tquery: SearchQuery;\n}): PortCheck<SearchPort>[] {\n\treturn [\n\t\t{\n\t\t\tid: \"search.fixture-returns-hits\",\n\t\t\ttitle: \"the fixture query matches something, so the checks below are not vacuous\",\n\t\t\tasync run(port) {\n\t\t\t\tconst result = await port.query(fixtures.query);\n\t\t\t\texpect(\n\t\t\t\t\tresult.hits.length > 0,\n\t\t\t\t\t\"the fixture query returned nothing, so every check below passes without exercising the adapter\",\n\t\t\t\t);\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"search.respects-limit\",\n\t\t\ttitle: \"a result set never exceeds the requested limit\",\n\t\t\tasync run(port) {\n\t\t\t\tconst result = await port.query({ ...fixtures.query, limit: 1 });\n\t\t\t\texpect(result.hits.length <= 1, `returned ${result.hits.length} hits for a limit of 1`);\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"search.returns-identifiers-not-records\",\n\t\t\ttitle: \"a hit carries an identifier a governed read can resolve, not the record\",\n\t\t\tasync run(port) {\n\t\t\t\tconst result = await port.query(fixtures.query);\n\t\t\t\tfor (const hit of result.hits) {\n\t\t\t\t\texpect(typeof hit.id === \"string\" && hit.id.length > 0, \"a hit carried no identifier\");\n\t\t\t\t\texpect(\n\t\t\t\t\t\tObject.keys(hit).every((key) => key === \"id\" || key === \"score\"),\n\t\t\t\t\t\t\"a hit carried record fields; search results are pointers, and reading one still goes through ProjectionHost\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t];\n}\n\n/** The suite a customer-record adapter must pass. */\nexport function customerRecordPortChecks(fixtures: {\n\tevent: CustomerEvent;\n}): PortCheck<CustomerRecordPort>[] {\n\treturn [\n\t\t{\n\t\t\t// This proves redelivery does not *fail*. Whether it duplicates is not\n\t\t\t// observable through this port, which has no read side by design, so\n\t\t\t// the suite says what it can and does not imply more.\n\t\t\tid: \"crm.redelivery-does-not-fail\",\n\t\t\ttitle: \"recording the same event twice is not an error\",\n\t\t\tasync run(port) {\n\t\t\t\tawait port.record(fixtures.event);\n\t\t\t\tawait port.record(fixtures.event);\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"crm.rejects-unidentified-event\",\n\t\t\ttitle: \"an event with no stable id is refused\",\n\t\t\tasync run(port) {\n\t\t\t\tlet refused = false;\n\t\t\t\ttry {\n\t\t\t\t\tawait port.record({ ...fixtures.event, eventId: \"\" });\n\t\t\t\t} catch {\n\t\t\t\t\trefused = true;\n\t\t\t\t}\n\t\t\t\texpect(refused, \"an event with no id was accepted; redelivery would duplicate the record\");\n\t\t\t},\n\t\t},\n\t];\n}\n\nexport function designTokensPortChecks(theme: string): PortCheck<DesignTokensPort>[] {\n\treturn [\n\t\t{\n\t\t\tid: \"tokens.theme-resolves\",\n\t\t\ttitle: \"a known theme resolves to at least one token\",\n\t\t\tasync run(port) {\n\t\t\t\tconst tokens = await port.resolve(theme);\n\t\t\t\texpect(Array.isArray(tokens) && tokens.length > 0, `theme \"${theme}\" resolved to no tokens`);\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"tokens.no-unresolved-aliases\",\n\t\t\ttitle: \"no resolved token still carries an alias\",\n\t\t\tasync run(port) {\n\t\t\t\tfor (const token of await port.resolve(theme)) {\n\t\t\t\t\texpect(\n\t\t\t\t\t\ttypeof token.value !== \"string\" || !ALIAS.test(token.value.trim()),\n\t\t\t\t\t\t`token \"${token.name}\" resolved to the unfollowed alias ${String(token.value)}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"tokens.names-are-unique\",\n\t\t\ttitle: \"token names are unique within a theme\",\n\t\t\tasync run(port) {\n\t\t\t\tconst names = (await port.resolve(theme)).map((token) => token.name);\n\t\t\t\texpect(new Set(names).size === names.length, \"the theme resolved duplicate token names\");\n\t\t\t},\n\t\t},\n\t];\n}\n\n/** Runs a contract suite and returns every failure, rather than stopping at the first. */\nexport async function runPortContract<TPort>(port: TPort, checks: readonly PortCheck<TPort>[]): Promise<{ passed: boolean; failures: Array<{ id: string; message: string }> }> {\n\tconst failures: Array<{ id: string; message: string }> = [];\n\tfor (const check of checks) {\n\t\ttry {\n\t\t\tawait check.run(port);\n\t\t} catch (error) {\n\t\t\tfailures.push({ id: check.id, message: error instanceof Error ? error.message : String(error) });\n\t\t}\n\t}\n\treturn { passed: failures.length === 0, failures };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA8DA,IAAM,QAAQ;AAEd,IAAM,UAAU,CAAC,UAChB,CAAC,CAAC,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,KAAK,YAAY;AAE9E,IAAM,UAAU,CAAC,UAChB,CAAC,CAAC,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,KAAK,EAAE,YAAY;AAOzE,SAAS,oBAAoB,UAAsC;AACzE,QAAM,OAAO,oBAAI,IAAiD;AAElE,QAAM,OAAO,CAAC,MAAiB,MAAgB,kBAAiC;AAC/E,UAAM,YAAY,OAAO,KAAK,UAAU,WAAW,KAAK,QAAQ;AAChE,eAAW,CAAC,KAAK,MAAM,KAAK,OAAO,QAAQ,IAAI,GAAG;AACjD,UAAI,IAAI,WAAW,GAAG,EAAG;AACzB,YAAM,OAAO,CAAC,GAAG,MAAM,GAAG;AAC1B,UAAI,QAAQ,MAAM,GAAG;AACpB,aAAK,IAAI,KAAK,KAAK,GAAG,GAAG,EAAE,OAAO,QAAQ,MAAM,OAAO,SAAS,UAAU,CAAC;AAAA,MAC5E,WAAW,QAAQ,MAAM,GAAG;AAC3B,aAAK,QAAQ,MAAM,SAAS;AAAA,MAC7B;AAAA,IACD;AAAA,EACD;AACA,OAAK,UAAU,CAAC,CAAC;AAEjB,QAAM,YAAY,oBAAI,IAAY;AAClC,QAAM,WAAW,oBAAI,IAAqB;AAE1C,QAAM,UAAU,CAAC,SAA0B;AAC1C,QAAI,SAAS,IAAI,IAAI,EAAG,QAAO,SAAS,IAAI,IAAI;AAChD,UAAM,QAAQ,KAAK,IAAI,IAAI;AAC3B,QAAI,CAAC,MAAO,OAAM,IAAI,MAAM,wBAAwB,IAAI,0CAA0C;AAClG,QAAI,UAAU,IAAI,IAAI,GAAG;AACxB,YAAM,IAAI,MAAM,6BAA6B,CAAC,GAAG,WAAW,IAAI,EAAE,KAAK,MAAM,CAAC,GAAG;AAAA,IAClF;AACA,UAAM,MAAM,MAAM,MAAM;AACxB,QAAI,OAAO,QAAQ,UAAU;AAC5B,eAAS,IAAI,MAAM,GAAG;AACtB,aAAO;AAAA,IACR;AACA,UAAM,QAAQ,MAAM,KAAK,IAAI,KAAK,CAAC;AACnC,QAAI,CAAC,OAAO;AACX,eAAS,IAAI,MAAM,GAAG;AACtB,aAAO;AAAA,IACR;AACA,cAAU,IAAI,IAAI;AAClB,UAAM,SAAS,QAAQ,MAAM,CAAC,CAAE;AAChC,cAAU,OAAO,IAAI;AACrB,aAAS,IAAI,MAAM,MAAM;AACzB,WAAO;AAAA,EACR;AAEA,SAAO,CAAC,GAAG,KAAK,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM;AACjD,UAAM,QAAQ,QAAQ,IAAI;AAC1B,WAAO;AAAA,MACN;AAAA,MACA;AAAA,MACA,GAAI,MAAM,SAAS,SAAY,CAAC,IAAI,EAAE,MAAM,MAAM,KAAK;AAAA,MACvD,GAAI,MAAM,MAAM,iBAAiB,SAAY,CAAC,IAAI,EAAE,aAAa,MAAM,MAAM,aAAa;AAAA,IAC3F;AAAA,EACD,CAAC;AACF;AAiBO,IAAM,uBAAqD;AAAA,EACjE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD;AAqDO,IAAM,kBAAN,cAA8B,MAAM;AAAA,EAE1C,YACU,WACT,SACC;AACD,UAAM,OAAO;AAHJ;AAAA,EAIV;AAAA,EAJU;AAAA,EAFQ,OAAO;AAO1B;AASO,SAAS,4BACf,QACA,OACA,MAAY,oBAAI,KAAK,GACd;AAGP,QAAM,cAAc,IAAI,QAAQ;AAChC,MAAI,OAAO,MAAM,WAAW,GAAG;AAC9B,UAAM,IAAI,gBAAgB,oBAAoB,qDAAqD;AAAA,EACpG;AAEA,MAAI,OAAO,OAAO,cAAc,YAAY,CAAC,qBAAqB,SAAS,OAAO,SAAS,GAAG;AAC7F,UAAM,IAAI,gBAAgB,sBAAsB,eAAe,OAAO,OAAO,SAAS,CAAC,8BAA8B;AAAA,EACtH;AACA,MAAI,OAAO,OAAO,YAAY,YAAY,OAAO,QAAQ,WAAW,GAAG;AACtE,UAAM,IAAI,gBAAgB,oBAAoB,gCAAgC;AAAA,EAC/E;AACA,MAAI,OAAO,OAAO,aAAa,YAAY,OAAO,SAAS,WAAW,GAAG;AACxE,UAAM,IAAI,gBAAgB,oBAAoB,+BAA+B;AAAA,EAC9E;AAKA,QAAM,WAAW,aAAa,OAAO,QAAQ;AAC7C,QAAM,YAAY,aAAa,OAAO,SAAS;AAC/C,MAAI,aAAa,UAAa,cAAc,QAAW;AACtD,UAAM,IAAI,gBAAgB,oBAAoB,wGAAwG;AAAA,EACvJ;AACA,MAAI,eAAe,WAAW;AAC7B,UAAM,IAAI,gBAAgB,WAAW,2BAA2B,OAAO,SAAS,GAAG;AAAA,EACpF;AACA,MAAI,cAAc,UAAU;AAC3B,UAAM,IAAI,gBAAgB,iBAAiB,oCAAoC,OAAO,QAAQ,GAAG;AAAA,EAClG;AAEA,MAAI,OAAO,aAAa,MAAM,UAAU;AACvC,UAAM,IAAI;AAAA,MACT;AAAA,MACA,8BAA8B,OAAO,QAAQ,8BAA8B,MAAM,QAAQ;AAAA,IAC1F;AAAA,EACD;AAIA,MAAI,OAAO,aAAa,cAAe;AACvC,MAAI,CAAC,MAAM,QAAQ,OAAO,QAAQ,KAAK,CAAC,OAAO,SAAS,MAAM,CAAC,UAAU,OAAO,UAAU,QAAQ,GAAG;AACpG,UAAM,IAAI,gBAAgB,oBAAoB,iFAAiF;AAAA,EAChI;AACA,MAAI,CAAC,OAAO,SAAS,SAAS,MAAM,OAAO,GAAG;AAC7C,UAAM,IAAI;AAAA,MACT;AAAA,MACA,oCAAoC,MAAM,OAAO;AAAA,IAClD;AAAA,EACD;AACD;AAGA,IAAM,UAAU;AAEhB,SAAS,aAAa,OAAmC;AACxD,MAAI,OAAO,UAAU,YAAY,CAAC,QAAQ,KAAK,KAAK,EAAG,QAAO;AAC9D,QAAM,SAAS,KAAK,MAAM,KAAK;AAC/B,SAAO,OAAO,MAAM,MAAM,IAAI,SAAY;AAC3C;AAQO,SAAS,uBACf,QACA,OACA,MAAY,oBAAI,KAAK,GACkE;AACvF,8BAA4B,QAAQ,OAAO,GAAG;AAC9C,SAAO;AAAA,IACN,SAAS,OAAO;AAAA,IAChB,WAAW,OAAO;AAAA,IAClB,UAAU,OAAO;AAAA,IACjB,SAAS,MAAM;AAAA,EAChB;AACD;AA4KA,IAAM,UAAU;AAMT,SAAS,WACf,YACmC;AACnC,MAAI,CAAC,QAAQ,KAAK,WAAW,EAAE,GAAG;AACjC,UAAM,IAAI,MAAM,YAAY,WAAW,EAAE,8DAA8D;AAAA,EACxG;AACA,MAAI,CAAC,kBAAkB,KAAK,WAAW,OAAO,GAAG;AAChD,UAAM,IAAI,MAAM,SAAS,WAAW,EAAE,qCAAqC;AAAA,EAC5E;AACA,MAAI,CAAC,WAAW,YAAY,KAAK,GAAG;AACnC,UAAM,IAAI,MAAM,SAAS,WAAW,EAAE,+DAA+D;AAAA,EACtG;AACA,MAAI,OAAO,WAAW,WAAW,YAAY;AAC5C,UAAM,IAAI,MAAM,SAAS,WAAW,EAAE,oCAAoC;AAAA,EAC3E;AACA,SAAO;AACR;AASA,eAAsB,wBACrB,YACA,UACA,gBACgB;AAChB,QAAM,SAAS,WAAW,OAAO,QAAQ;AACzC,MAAI,OAAO,WAAW,GAAG;AACxB,UAAM,IAAI,MAAM,SAAS,WAAW,EAAE,kEAAkE;AAAA,EACzG;AACA,QAAM,MAAM,oBAAI,IAAY;AAC5B,aAAW,SAAS,QAAQ;AAC3B,QAAI,IAAI,IAAI,MAAM,EAAE,EAAG,OAAM,IAAI,MAAM,SAAS,WAAW,EAAE,qBAAqB,MAAM,EAAE,UAAU;AACpG,QAAI,IAAI,MAAM,EAAE;AAAA,EACjB;AAOA,QAAM,WAAW,MAAM,QAAQ,cAAc,IAAI,iBAAiB,CAAC,cAAuB;AAC1F,MAAI,SAAS,WAAW,GAAG;AAC1B,UAAM,IAAI,MAAM,SAAS,WAAW,EAAE,4EAA4E;AAAA,EACnH;AAEA,QAAM,WAAW,IAAI,IAAI,OAAO,IAAI,CAAC,UAAU,MAAM,EAAE,CAAC;AACxD,aAAW,WAAW,UAAU;AAC/B,eAAW,SAAS,QAAQ;AAC3B,UAAI,CAAC,SAAS,IAAI,MAAM,EAAE,EAAG;AAC7B,UAAI;AACH,cAAM,MAAM,IAAI,OAAO;AAAA,MACxB,QAAQ;AACP,iBAAS,OAAO,MAAM,EAAE;AAAA,MACzB;AAAA,IACD;AAAA,EACD;AACA,MAAI,SAAS,OAAO,GAAG;AACtB,UAAM,IAAI;AAAA,MACT,SAAS,WAAW,EAAE,SAAS,SAAS,IAAI,2EAA2E,CAAC,GAAG,QAAQ,EAAE,KAAK,IAAI,CAAC;AAAA,IAChJ;AAAA,EACD;AACD;AAuBA,eAAsB,eAAiC,OAOzB;AAI7B,aAAW,MAAM,UAAU;AAC3B,QAAM,SAAS,MAAM,WAAW,OAAO,MAAM,QAAQ;AACrD,MAAI,OAAO,WAAW,GAAG;AACxB,UAAM,IAAI,MAAM,SAAS,MAAM,WAAW,EAAE,kEAAkE;AAAA,EAC/G;AACA,QAAM,SAAmB,CAAC;AAC1B,aAAW,SAAS,QAAQ;AAC3B,QAAI;AACH,YAAM,MAAM,IAAI,MAAM,OAAO;AAAA,IAC9B,SAAS,OAAO;AACf,YAAM,IAAI;AAAA,QACT,YAAY,MAAM,MAAM,kBAAkB,MAAM,WAAW,EAAE,YAAY,MAAM,EAAE,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,MAC9I;AAAA,IACD;AACA,WAAO,KAAK,MAAM,EAAE;AAAA,EACrB;AACA,SAAO;AAAA,IACN,MAAM,MAAM,WAAW;AAAA,IACvB,QAAQ,MAAM;AAAA,IACd,GAAI,MAAM,YAAY,SAAY,CAAC,IAAI,EAAE,SAAS,MAAM,QAAQ;AAAA,IAChE,GAAI,MAAM,WAAW,WAAW,EAAE,UAAU,MAAM,WAAW,SAAS,IAAI,CAAC;AAAA,IAC3E,eAAe;AAAA,MACd,QAAQ,MAAM,WAAW;AAAA,MACzB,aAAa,MAAM,WAAW;AAAA,MAC9B,QAAQ;AAAA,MACR,cAAc,MAAM,OAAO,oBAAI,KAAK,GAAG,YAAY;AAAA,IACpD;AAAA,EACD;AACD;AAUA,SAAS,eAAe,SAA4B,UAA+C;AAClG,QAAM,gBAAiB,QAA6B;AACpD,MAAI,CAAC,iBAAiB,OAAO,kBAAkB,SAAU,QAAO;AAChE,MAAI,cAAc,WAAW,SAAU,QAAO;AAC9C,MAAI,cAAc,WAAW,QAAQ,KAAM,QAAO;AAClD,MAAI,CAAC,kBAAkB,KAAK,cAAc,eAAe,EAAE,EAAG,QAAO;AACrE,MAAI,CAAC,MAAM,QAAQ,cAAc,MAAM,KAAK,cAAc,OAAO,WAAW,EAAG,QAAO;AACtF,MAAI,OAAO,MAAM,KAAK,MAAM,cAAc,eAAe,EAAE,CAAC,EAAG,QAAO;AACtE,SAAO;AACR;AAkDO,SAAS,yBAAyB,OAchB;AACxB,QAAM,cAAc,IAAI,KAAK,MAAM,eAAe,CAAC,GAAG,IAAI,CAAC,eAAe,CAAC,WAAW,IAAI,UAAU,CAAC,CAAC;AACtG,QAAM,WAA0B,CAAC;AACjC,aAAW,eAAe,MAAM,WAAW,cAAc,SAAS,CAAC,GAAG;AACrE,UAAM,aAAa,MAAM,SAAS,OAAO,CAAC,YAAY,QAAQ,SAAS,YAAY,IAAI;AACvF,QAAI,WAAW,WAAW,GAAG;AAC5B,eAAS,KAAK;AAAA,QACb,MAAM;AAAA,QACN,MAAM,YAAY;AAAA,QAClB,SAAS,eAAe,MAAM,WAAW,SAAS,oBAAoB,YAAY,IAAI;AAAA,MACvF,CAAC;AACD;AAAA,IACD;AAGA,QAAI,WAAW;AACf,QAAI,YAAY,UAAU;AACzB,iBAAW,SAAS,OAAO,CAAC,YAAY,QAAQ,UAAU,SAAS,YAAY,SAAU,IAAI;AAC7F,UAAI,SAAS,WAAW,GAAG;AAC1B,iBAAS,KAAK;AAAA,UACb,MAAM;AAAA,UACN,MAAM,YAAY;AAAA,UAClB,SAAS,SAAS,YAAY,IAAI,iBAAiB,YAAY,SAAS,IAAI,8BAA8B,WAAW,IAAI,CAAC,YAAY,GAAG,QAAQ,MAAM,IAAI,QAAQ,UAAU,QAAQ,aAAa,GAAG,EAAE,KAAK,IAAI,CAAC;AAAA,QAClN,CAAC;AACD;AAAA,MACD;AACA,UAAI,YAAY,SAAS,SAAS;AACjC,cAAM,YAAY,SAAS,OAAO,CAAC,YAAY,QAAQ,UAAU,YAAY,YAAY,SAAU,OAAO;AAC1G,YAAI,UAAU,WAAW,GAAG;AAC3B,mBAAS,KAAK;AAAA,YACb,MAAM;AAAA,YACN,MAAM,YAAY;AAAA,YAClB,SAAS,SAAS,YAAY,IAAI,iBAAiB,YAAY,SAAS,IAAI,cAAc,YAAY,SAAS,OAAO,gCAAgC,SAAS,IAAI,CAAC,YAAY,QAAQ,UAAU,WAAW,qBAAqB,EAAE,KAAK,IAAI,CAAC;AAAA,UAC/O,CAAC;AACD;AAAA,QACD;AACA,mBAAW;AAAA,MACZ;AAAA,IACD;AACA,QAAI,YAAY,SAAS;AACxB,YAAM,YAAY,SAAS,OAAO,CAAC,YAAY,QAAQ,YAAY,YAAY,OAAO;AACtF,UAAI,UAAU,WAAW,GAAG;AAC3B,iBAAS,KAAK;AAAA,UACb,MAAM;AAAA,UACN,MAAM,YAAY;AAAA,UAClB,SAAS,SAAS,YAAY,IAAI,uBAAuB,YAAY,OAAO,4BAA4B,SAAS,IAAI,CAAC,YAAY,GAAG,QAAQ,MAAM,IAAI,QAAQ,WAAW,aAAa,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA,QACtM,CAAC;AACD;AAAA,MACD;AACA,iBAAW;AAAA,IACZ;AAIA,UAAM,aAAa,YAAY,IAAI,YAAY,IAAI;AACnD,QAAI,MAAM,wBAAwB,YAAY;AAC7C,YAAM,YAAY,SAAS,OAAO,CAAC,YAAY,eAAe,SAAS,YAAY,IAAI,CAAC;AACxF,UAAI,UAAU,WAAW,GAAG;AAC3B,YAAI,MAAM,sBAAsB;AAC/B,mBAAS,KAAK;AAAA,YACb,MAAM;AAAA,YACN,MAAM,YAAY;AAAA,YAClB,SAAS,SAAS,YAAY,IAAI,4BAA4B,SAAS,IAAI,CAAC,YAAY,QAAQ,MAAM,EAAE,KAAK,IAAI,CAAC;AAAA,UACnH,CAAC;AAAA,QACF;AACA;AAAA,MACD;AACA,UAAI,cAAc,CAAC,UAAU,KAAK,CAAC,YAAY,QAAQ,cAAc,gBAAgB,WAAW,OAAO,GAAG;AACzG,iBAAS,KAAK;AAAA,UACb,MAAM;AAAA,UACN,MAAM,YAAY;AAAA,UAClB,SAAS,SAAS,YAAY,IAAI,4BAA4B,WAAW,OAAO,oCAAoC,UAAU,IAAI,CAAC,YAAY,GAAG,QAAQ,MAAM,IAAI,QAAQ,cAAc,WAAW,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA,QACpN,CAAC;AAAA,MACF;AAAA,IACD;AAAA,EACD;AACA,SAAO,EAAE,OAAO,SAAS,WAAW,GAAG,SAAS;AACjD;AAEO,SAAS,gCAAgC,OAKvC;AACR,QAAM,SAAS,yBAAyB,KAAK;AAC7C,MAAI,OAAO,MAAO;AAClB,QAAM,IAAI,MAAM;AAAA,IACf,0BAA0B,MAAM,WAAW,SAAS;AAAA,IACpD,GAAG,OAAO,SAAS,IAAI,CAAC,YAAY,OAAO,QAAQ,OAAO,EAAE;AAAA,EAC7D,EAAE,KAAK,IAAI,CAAC;AACb;AAWA,IAAM,sBAAN,cAAkC,MAAM;AAAA,EACrB,OAAO;AAC1B;AAEA,SAAS,OAAO,WAAoB,SAAoC;AACvE,MAAI,CAAC,UAAW,OAAM,IAAI,oBAAoB,OAAO;AACtD;AAMO,SAAS,kBAA0C;AACzD,QAAM,aAAa;AACnB,SAAO;AAAA,IACN;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,SAAS,MAAM,KAAK,eAAe,YAAY,IAAI;AACzD,eAAO,OAAO,UAAU,MAAM,4BAA4B,OAAO,OAAO,KAAK,CAAC,kCAAkC;AAChH;AAAA,UACC,OAAO,WAAW,aAAa,OAAO,WAAW;AAAA,UACjD,yCAAyC,OAAO,MAAM;AAAA,QACvD;AAAA,MACD;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,eAAO,QAAQ,MAAM,KAAK,eAAe,YAAY,KAAK,GAAG,UAAU,WAAW,yCAAyC;AAC3H,eAAO,QAAQ,MAAM,KAAK,cAAc,YAAY,UAAU,GAAG,UAAU,UAAU,uCAAuC;AAC5H,eAAO,QAAQ,MAAM,KAAK,cAAc,YAAY,EAAE,GAAG,UAAU,UAAU,uCAAuC;AAAA,MACrH;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,UAAU,EAAE,cAAc,0BAA0B;AAC1D,cAAM,QAAQ,MAAM,KAAK,cAAc,YAAY,YAAY,OAAO;AACtE,cAAM,SAAS,MAAM,KAAK,cAAc,YAAY,YAAY,OAAO;AACvE,eAAO,MAAM,UAAU,OAAO,OAAO,iCAAiC,MAAM,KAAK,WAAW,OAAO,KAAK,GAAG;AAAA,MAC5G;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,KAAK,eAAe,YAAY,KAAK;AAAA,MAC5C;AAAA,IACD;AAAA,EACD;AACD;AAUO,SAAS,mBAAmB,UAIL;AAC7B,QAAM,SAAoC;AAAA,IACzC;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,SAAS,MAAM,KAAK,OAAO,kBAAkB;AACnD,eAAO,WAAW,MAAM,+DAA+D;AAAA,MACxF;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,eAAQ,MAAM,KAAK,OAAO,EAAE,MAAO,MAAM,wCAAwC;AAAA,MAClF;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,SAAS,MAAM,KAAK,OAAO,SAAS,eAAe;AACzD,eAAO,WAAW,MAAM,qCAAqC;AAC7D,eAAO,QAAQ,YAAY,SAAS,SAAS,SAAS,gBAAgB,QAAQ,OAAO,GAAG;AACxF,eAAO,QAAQ,aAAa,SAAS,SAAS,UAAU,iBAAiB,QAAQ,QAAQ,GAAG;AAAA,MAC7F;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,SAAS,MAAM,KAAK,OAAO,SAAS,eAAe;AACzD,eAAO,WAAW,MAAM,qCAAqC;AAC7D,YAAI,CAAC,OAAQ;AACb,eAAO,qBAAqB,SAAS,OAAO,SAAS,GAAG,cAAc,OAAO,SAAS,6BAA6B;AACnH,eAAO,OAAO,OAAO,WAAW,YAAY,OAAO,OAAO,SAAS,GAAG,wBAAwB;AAI9F,eAAO,QAAQ,KAAK,OAAO,QAAQ,GAAG,aAAa,OAAO,QAAQ,2CAA2C;AAC7G,eAAO,QAAQ,KAAK,OAAO,SAAS,GAAG,cAAc,OAAO,SAAS,2CAA2C;AAChH,eAAO,OAAO,OAAO,aAAa,YAAY,OAAO,SAAS,SAAS,GAAG,wBAAwB;AAClG;AAAA,UACC,OAAO,aAAa,iBAAiB,MAAM,QAAQ,OAAO,QAAQ;AAAA,UAClE;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,SAAS,MAAM,KAAK,OAAO,SAAS,eAAe;AACzD,eAAO,WAAW,MAAM,mEAAmE;AAC3F,YAAI,CAAC,OAAQ;AACb,cAAM,aAAa,KAAK,UAAU,MAAM;AACxC;AAAA,UACC,CAAC,WAAW,SAAS,SAAS,eAAe;AAAA,UAC7C;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,QAAQ,MAAM,KAAK,OAAO,SAAS,eAAe;AACxD,cAAM,SAAS,MAAM,KAAK,OAAO,SAAS,eAAe;AACzD,eAAO,OAAO,YAAY,QAAQ,SAAS,wDAAwD;AAAA,MACpG;AAAA,IACD;AAAA,EACD;AAEA,MAAI,SAAS,sBAAsB,QAAW;AAC7C,WAAO,KAAK;AAAA,MACX,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,oBAAoB,SAAS;AACnC,eAAQ,MAAM,KAAK,OAAO,iBAAiB,MAAO,MAAM,gDAAgD;AAAA,MACzG;AAAA,IACD,CAAC;AAAA,EACF;AAEA,SAAO;AACR;AAGO,SAAS,kBAAkB,UAGL;AAC5B,SAAO;AAAA,IACN;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,SAAS,MAAM,KAAK,QAAQ,EAAE,GAAG,SAAS,SAAS,KAAK,SAAS,UAAU,CAAC;AAClF,eAAO,WAAW,MAAM,uDAAuD;AAAA,MAChF;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,QAAQ,MAAM,KAAK,QAAQ,SAAS,OAAO;AACjD,cAAM,SAAS,MAAM,KAAK,QAAQ,SAAS,OAAO;AAClD,eAAO,UAAU,QAAQ,WAAW,MAAM,iCAAiC;AAC3E,eAAO,OAAO,aAAa,QAAQ,UAAU,iEAAiE;AAAA,MAC/G;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,SAAS,MAAM,KAAK,QAAQ,SAAS,OAAO;AAClD;AAAA,UACC,CAAC,KAAK,UAAU,UAAU,CAAC,CAAC,EAAE,SAAS,eAAe;AAAA,UACtD;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,EACD;AACD;AAGO,SAAS,mBAAmB,UAEL;AAC7B,SAAO;AAAA,IACN;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,YAAI,UAAU;AACd,YAAI;AACH,gBAAM,KAAK,OAAO,EAAE,GAAG,SAAS,SAAS,QAAQ,EAAE,GAAG,SAAS,QAAQ,QAAQ,QAAQ,KAAK,EAAE,CAAC;AAAA,QAChG,QAAQ;AACP,oBAAU;AAAA,QACX;AACA,eAAO,SAAS,+EAA+E;AAI/F,cAAM,UAAU,MAAM,KAAK,OAAO;AAAA,UACjC,GAAG,SAAS;AAAA,UACZ,gBAAgB,GAAG,SAAS,QAAQ,cAAc;AAAA,QACnD,CAAC;AACD;AAAA,UACC,QAAQ,YAAY;AAAA,UACpB,gCAAgC,QAAQ,OAAO;AAAA,QAChD;AAAA,MACD;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,YAAI,UAAU;AACd,YAAI;AACH,gBAAM,KAAK,OAAO,EAAE,GAAG,SAAS,SAAS,gBAAgB,GAAG,CAAC;AAAA,QAC9D,QAAQ;AACP,oBAAU;AAAA,QACX;AACA,eAAO,SAAS,+EAA+E;AAAA,MAChG;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,QAAQ,MAAM,KAAK,OAAO,SAAS,OAAO;AAChD,cAAM,SAAS,MAAM,KAAK,OAAO,SAAS,OAAO;AACjD;AAAA,UACC,MAAM,YAAY,OAAO;AAAA,UACzB,0BAA0B,MAAM,OAAO,WAAW,OAAO,OAAO;AAAA,QACjE;AAIA;AAAA,UACC,MAAM,YAAY,eAAe,MAAM,sBAAsB;AAAA,UAC7D;AAAA,QACD;AACA;AAAA,UACC,MAAM,sBAAsB,OAAO;AAAA,UACnC;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,SAAS,MAAM,KAAK,OAAO,SAAS,OAAO;AACjD;AAAA,UACC,OAAO,YAAY,eAAe,OAAO,YAAY,YAAY,OAAO,YAAY;AAAA,UACpF,YAAY,OAAO,OAAO;AAAA,QAC3B;AAAA,MACD;AAAA,IACD;AAAA,EACD;AACD;AAGO,SAAS,iBAAiB,UAEL;AAC3B,SAAO;AAAA,IACN;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,SAAS,MAAM,KAAK,MAAM,SAAS,KAAK;AAC9C;AAAA,UACC,OAAO,KAAK,SAAS;AAAA,UACrB;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,SAAS,MAAM,KAAK,MAAM,EAAE,GAAG,SAAS,OAAO,OAAO,EAAE,CAAC;AAC/D,eAAO,OAAO,KAAK,UAAU,GAAG,YAAY,OAAO,KAAK,MAAM,wBAAwB;AAAA,MACvF;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,SAAS,MAAM,KAAK,MAAM,SAAS,KAAK;AAC9C,mBAAW,OAAO,OAAO,MAAM;AAC9B,iBAAO,OAAO,IAAI,OAAO,YAAY,IAAI,GAAG,SAAS,GAAG,6BAA6B;AACrF;AAAA,YACC,OAAO,KAAK,GAAG,EAAE,MAAM,CAAC,QAAQ,QAAQ,QAAQ,QAAQ,OAAO;AAAA,YAC/D;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,EACD;AACD;AAGO,SAAS,yBAAyB,UAEL;AACnC,SAAO;AAAA,IACN;AAAA;AAAA;AAAA;AAAA,MAIC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,KAAK,OAAO,SAAS,KAAK;AAChC,cAAM,KAAK,OAAO,SAAS,KAAK;AAAA,MACjC;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,YAAI,UAAU;AACd,YAAI;AACH,gBAAM,KAAK,OAAO,EAAE,GAAG,SAAS,OAAO,SAAS,GAAG,CAAC;AAAA,QACrD,QAAQ;AACP,oBAAU;AAAA,QACX;AACA,eAAO,SAAS,yEAAyE;AAAA,MAC1F;AAAA,IACD;AAAA,EACD;AACD;AAEO,SAAS,uBAAuB,OAA8C;AACpF,SAAO;AAAA,IACN;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,SAAS,MAAM,KAAK,QAAQ,KAAK;AACvC,eAAO,MAAM,QAAQ,MAAM,KAAK,OAAO,SAAS,GAAG,UAAU,KAAK,yBAAyB;AAAA,MAC5F;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,mBAAW,SAAS,MAAM,KAAK,QAAQ,KAAK,GAAG;AAC9C;AAAA,YACC,OAAO,MAAM,UAAU,YAAY,CAAC,MAAM,KAAK,MAAM,MAAM,KAAK,CAAC;AAAA,YACjE,UAAU,MAAM,IAAI,sCAAsC,OAAO,MAAM,KAAK,CAAC;AAAA,UAC9E;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,SAAS,MAAM,KAAK,QAAQ,KAAK,GAAG,IAAI,CAAC,UAAU,MAAM,IAAI;AACnE,eAAO,IAAI,IAAI,KAAK,EAAE,SAAS,MAAM,QAAQ,0CAA0C;AAAA,MACxF;AAAA,IACD;AAAA,EACD;AACD;AAGA,eAAsB,gBAAuB,MAAa,QAAqH;AAC9K,QAAM,WAAmD,CAAC;AAC1D,aAAW,SAAS,QAAQ;AAC3B,QAAI;AACH,YAAM,MAAM,IAAI,IAAI;AAAA,IACrB,SAAS,OAAO;AACf,eAAS,KAAK,EAAE,IAAI,MAAM,IAAI,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE,CAAC;AAAA,IAChG;AAAA,EACD;AACA,SAAO,EAAE,QAAQ,SAAS,WAAW,GAAG,SAAS;AAClD;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../index.ts"],"sourcesContent":["/**\n * Port interfaces are declared here and implemented by vendor adapters elsewhere.\n * Nothing in this package imports a vendor SDK: a port is a shape, and an adapter\n * is anything that satisfies it. Where an open standard exists the port speaks it,\n * so the incumbent vendor is already just one provider behind the interface.\n */\n\n// ── Feature flags (OpenFeature-shaped) ──────────────────────────────────────\n\nexport type FlagValue = boolean | string | number | { [key: string]: unknown };\n\nexport interface EvaluationContext {\n\t/** Stable identifier for the subject of evaluation, usually a tenant or actor. */\n\ttargetingKey?: string;\n\t[attribute: string]: unknown;\n}\n\nexport type ResolutionReason = \"STATIC\" | \"DEFAULT\" | \"TARGETING_MATCH\" | \"SPLIT\" | \"CACHED\" | \"ERROR\";\n\nexport interface ResolutionDetails<T extends FlagValue> {\n\tvalue: T;\n\treason: ResolutionReason;\n\tvariant?: string;\n\terrorCode?: string;\n}\n\n/**\n * Structurally compatible with an OpenFeature provider's evaluation surface, so an\n * OpenFeature provider is a thin adapter rather than a translation layer.\n */\nexport interface FlagsPort {\n\tresolveBoolean(flagKey: string, defaultValue: boolean, context?: EvaluationContext): Promise<ResolutionDetails<boolean>>;\n\tresolveString(flagKey: string, defaultValue: string, context?: EvaluationContext): Promise<ResolutionDetails<string>>;\n\tresolveNumber(flagKey: string, defaultValue: number, context?: EvaluationContext): Promise<ResolutionDetails<number>>;\n}\n\n// ── Design tokens (W3C DTCG) ────────────────────────────────────────────────\n\nexport interface DtcgToken {\n\t$value: unknown;\n\t$type?: string;\n\t$description?: string;\n}\n\nexport interface DtcgGroup {\n\t$type?: string;\n\t$description?: string;\n\t[member: string]: DtcgToken | DtcgGroup | string | undefined;\n}\n\nexport interface ResolvedToken {\n\tname: string;\n\tvalue: unknown;\n\ttype?: string;\n\tdescription?: string;\n}\n\nexport interface DesignTokensPort {\n\t/** Resolved tokens for one theme. Aliases are already followed. */\n\tresolve(theme: string): Promise<ResolvedToken[]>;\n}\n\nconst ALIAS = /^\\{([^}]+)\\}$/;\n\nconst isToken = (value: unknown): value is DtcgToken =>\n\t!!value && typeof value === \"object\" && !Array.isArray(value) && \"$value\" in value;\n\nconst isGroup = (value: unknown): value is DtcgGroup =>\n\t!!value && typeof value === \"object\" && !Array.isArray(value) && !(\"$value\" in value);\n\n/**\n * Flattens a DTCG document and follows aliases. `$type` is inherited from the\n * nearest ancestor group that declares one, which is what the format specifies\n * and what makes a theme file readable.\n */\nexport function resolveDesignTokens(document: DtcgGroup): ResolvedToken[] {\n\tconst flat = new Map<string, { token: DtcgToken; type?: string }>();\n\n\tconst walk = (node: DtcgGroup, path: string[], inheritedType?: string): void => {\n\t\tconst groupType = typeof node.$type === \"string\" ? node.$type : inheritedType;\n\t\tfor (const [key, member] of Object.entries(node)) {\n\t\t\tif (key.startsWith(\"$\")) continue;\n\t\t\tconst next = [...path, key];\n\t\t\tif (isToken(member)) {\n\t\t\t\tflat.set(next.join(\".\"), { token: member, type: member.$type ?? groupType });\n\t\t\t} else if (isGroup(member)) {\n\t\t\t\twalk(member, next, groupType);\n\t\t\t}\n\t\t}\n\t};\n\twalk(document, []);\n\n\tconst resolving = new Set<string>();\n\tconst resolved = new Map<string, unknown>();\n\n\tconst valueOf = (name: string): unknown => {\n\t\tif (resolved.has(name)) return resolved.get(name);\n\t\tconst entry = flat.get(name);\n\t\tif (!entry) throw new Error(`Design token alias \"{${name}}\" does not resolve to a declared token.`);\n\t\tif (resolving.has(name)) {\n\t\t\tthrow new Error(`Design token alias cycle: ${[...resolving, name].join(\" -> \")}.`);\n\t\t}\n\t\tconst raw = entry.token.$value;\n\t\tif (typeof raw !== \"string\") {\n\t\t\tresolved.set(name, raw);\n\t\t\treturn raw;\n\t\t}\n\t\tconst alias = ALIAS.exec(raw.trim());\n\t\tif (!alias) {\n\t\t\tresolved.set(name, raw);\n\t\t\treturn raw;\n\t\t}\n\t\tresolving.add(name);\n\t\tconst target = valueOf(alias[1]!);\n\t\tresolving.delete(name);\n\t\tresolved.set(name, target);\n\t\treturn target;\n\t};\n\n\treturn [...flat.entries()].map(([name, entry]) => {\n\t\tconst value = valueOf(name);\n\t\treturn {\n\t\t\tname,\n\t\t\tvalue,\n\t\t\t...(entry.type === undefined ? {} : { type: entry.type }),\n\t\t\t...(entry.token.$description === undefined ? {} : { description: entry.token.$description }),\n\t\t};\n\t});\n}\n\n// ── Identity (OAuth2 / OIDC-shaped) ─────────────────────────────────────────\n\n/**\n * Actor kinds a verified credential can resolve to. This mirrors `ActorType` in\n * `@fabricorg/platform`, restated here so this package keeps zero runtime\n * dependencies. `identityPortChecks` asserts the two stay identical.\n */\nexport type IdentityActorType =\n\t| \"natural_person\"\n\t| \"agent\"\n\t| \"system\"\n\t| \"service_account\"\n\t| \"external_system\"\n\t| \"integration\";\n\nexport const IDENTITY_ACTOR_TYPES: readonly IdentityActorType[] = [\n\t\"natural_person\",\n\t\"agent\",\n\t\"system\",\n\t\"service_account\",\n\t\"external_system\",\n\t\"integration\",\n];\n\n/**\n * The scopes a credential covers. `\"tenant-wide\"` is spelled out rather than\n * left as an absent field, so a credential that simply forgot to carry space\n * coverage can never be read as covering everything.\n */\nexport type ActorSpaceCoverage = readonly string[] | \"tenant-wide\";\n\n/**\n * Identity resolved from a verified credential. Every governed action,\n * projection decision, grant and audit record derives from actor context, so\n * this is the shape a gateway must produce before the platform is called.\n *\n * It carries no credential material. `credentialId` is an opaque, non-secret\n * reference retained for audit, matching the convention used by\n * `authorizationBindingId`.\n */\nexport interface ActorClaims {\n\t/** Stable subject identifier; becomes `actorId` on a governed submission. */\n\tsubject: string;\n\tactorType: IdentityActorType;\n\ttenantId: string;\n\tspaceIds: ActorSpaceCoverage;\n\t/** Granted scopes, if the issuer expresses authority that way. */\n\tscopes?: readonly string[];\n\tissuer: string;\n\t/** RFC 3339 timestamps. */\n\tissuedAt: string;\n\texpiresAt: string;\n\t/** Opaque, non-secret reference to the presented credential, for audit. */\n\tcredentialId?: string;\n}\n\n/**\n * Verifies a presented credential and resolves it to actor claims.\n *\n * An implementation returns `null` for any credential it cannot positively\n * verify — expired, malformed, wrong issuer, bad signature. It never returns\n * partially trusted claims, and it never echoes credential material back.\n */\nexport interface IdentityPort {\n\tverify(credential: string): Promise<ActorClaims | null>;\n}\n\nexport type ActorScopeRejection =\n\t| \"malformed_claims\"\n\t| \"expired\"\n\t| \"not_yet_valid\"\n\t| \"tenant_mismatch\"\n\t| \"space_not_covered\"\n\t| \"unknown_actor_type\";\n\nexport class ActorScopeError extends Error {\n\toverride readonly name = \"ActorScopeError\";\n\tconstructor(\n\t\treadonly rejection: ActorScopeRejection,\n\t\tmessage: string,\n\t) {\n\t\tsuper(message);\n\t}\n}\n\n/**\n * Confirm verified claims actually cover the tenant and space being acted on.\n *\n * Verification proves who the caller is. It does not prove they may act here.\n * Calling this before a governed submission is what stops a valid credential\n * for one tenant from being replayed against another.\n */\nexport function assertActorClaimsCoverScope(\n\tclaims: ActorClaims,\n\tscope: { tenantId: string; spaceId: string },\n\tnow: Date = new Date(),\n): void {\n\t// Every comparison against an invalid clock is false, which would let an\n\t// expired credential through. Reject the clock before trusting it.\n\tconst currentTime = now.getTime();\n\tif (Number.isNaN(currentTime)) {\n\t\tthrow new ActorScopeError(\"malformed_claims\", \"Actor scope was evaluated against an invalid clock.\");\n\t}\n\n\tif (typeof claims.actorType !== \"string\" || !IDENTITY_ACTOR_TYPES.includes(claims.actorType)) {\n\t\tthrow new ActorScopeError(\"unknown_actor_type\", `Actor type \"${String(claims.actorType)}\" is not a known actor kind.`);\n\t}\n\tif (typeof claims.subject !== \"string\" || claims.subject.length === 0) {\n\t\tthrow new ActorScopeError(\"malformed_claims\", \"Actor claims carry no subject.\");\n\t}\n\tif (typeof claims.tenantId !== \"string\" || claims.tenantId.length === 0) {\n\t\tthrow new ActorScopeError(\"malformed_claims\", \"Actor claims carry no tenant.\");\n\t}\n\n\t// Date.parse accepts timezone-less strings and reads them in the host's\n\t// local zone, so the same credential would expire at different instants on\n\t// different machines. Require an explicit offset.\n\tconst issuedAt = parseRfc3339(claims.issuedAt);\n\tconst expiresAt = parseRfc3339(claims.expiresAt);\n\tif (issuedAt === undefined || expiresAt === undefined) {\n\t\tthrow new ActorScopeError(\"malformed_claims\", \"Actor claims carry an issuedAt or expiresAt that is not an RFC 3339 timestamp with an explicit offset.\");\n\t}\n\tif (currentTime >= expiresAt) {\n\t\tthrow new ActorScopeError(\"expired\", `Actor claims expired at ${claims.expiresAt}.`);\n\t}\n\tif (currentTime < issuedAt) {\n\t\tthrow new ActorScopeError(\"not_yet_valid\", `Actor claims are not valid until ${claims.issuedAt}.`);\n\t}\n\n\tif (claims.tenantId !== scope.tenantId) {\n\t\tthrow new ActorScopeError(\n\t\t\t\"tenant_mismatch\",\n\t\t\t`Actor claims cover tenant \"${claims.tenantId}\" but the request targets \"${scope.tenantId}\".`,\n\t\t);\n\t}\n\n\t// A malformed adapter returning a bare string would otherwise reach\n\t// String.prototype.includes, where \"space_10\" covers \"space_1\".\n\tif (claims.spaceIds === \"tenant-wide\") return;\n\tif (!Array.isArray(claims.spaceIds) || !claims.spaceIds.every((space) => typeof space === \"string\")) {\n\t\tthrow new ActorScopeError(\"malformed_claims\", 'Actor claims spaceIds must be an array of strings or the literal \"tenant-wide\".');\n\t}\n\tif (!claims.spaceIds.includes(scope.spaceId)) {\n\t\tthrow new ActorScopeError(\n\t\t\t\"space_not_covered\",\n\t\t\t`Actor claims do not cover space \"${scope.spaceId}\".`,\n\t\t);\n\t}\n}\n\n/** RFC 3339 with a mandatory offset, so an instant means the same thing everywhere. */\nconst RFC3339 = /^\\d{4}-\\d{2}-\\d{2}[Tt]\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:[Zz]|[+-]\\d{2}:\\d{2})$/;\n\nfunction parseRfc3339(value: string): number | undefined {\n\tif (typeof value !== \"string\" || !RFC3339.test(value)) return undefined;\n\tconst parsed = Date.parse(value);\n\treturn Number.isNaN(parsed) ? undefined : parsed;\n}\n\n/**\n * The actor fields a governed submission needs, derived from verified claims\n * after {@link assertActorClaimsCoverScope} has accepted them. Taking these\n * from claims rather than from request input is what keeps the audit trail\n * tied to something that was actually proven.\n */\nexport function actorContextFromClaims(\n\tclaims: ActorClaims,\n\tscope: { tenantId: string; spaceId: string },\n\tnow: Date = new Date(),\n): { actorId: string; actorType: IdentityActorType; tenantId: string; spaceId: string } {\n\tassertActorClaimsCoverScope(claims, scope, now);\n\treturn {\n\t\tactorId: claims.subject,\n\t\tactorType: claims.actorType,\n\t\ttenantId: claims.tenantId,\n\t\tspaceId: scope.spaceId,\n\t};\n}\n\n// ── Content (headless CMS-shaped) ───────────────────────────────────────────\n\n/**\n * A resolved piece of authored content.\n *\n * Content is copy and layout, never permission. A content system deciding what\n * a screen says is expected; a content system deciding what a screen may reach\n * is the failure this whole boundary exists to prevent, which is why nothing\n * here carries a capability reference.\n */\nexport interface ContentEntry {\n\tkey: string;\n\tlocale: string;\n\t/** Opaque revision, stable for identical content. Use it for cache keys. */\n\trevision: string;\n\tvalue: JsonLike;\n}\n\nexport type JsonLike = string | number | boolean | null | JsonLike[] | { [key: string]: JsonLike };\n\nexport interface ContentQuery {\n\tkey: string;\n\tlocale: string;\n\t/** Optional variant, for an experiment arm already enumerated in a release. */\n\tvariant?: string;\n}\n\nexport interface ContentPort {\n\t/** Resolves to `null` when the key is not authored, rather than inventing a default. */\n\tresolve(query: ContentQuery): Promise<ContentEntry | null>;\n}\n\n// ── Payments ────────────────────────────────────────────────────────────────\n\n/**\n * Money as an integer in the currency's minor unit.\n *\n * Never a float. A payment expressed as 10.1 is a payment that will eventually\n * be off by a cent, and reconciling that costs more than the type ever did.\n */\nexport interface MinorUnitAmount {\n\t/** Integer in the minor unit: 1050 is USD 10.50. */\n\tamount: number;\n\t/** ISO 4217 alphabetic code. */\n\tcurrency: string;\n}\n\n/**\n * The outcome of asking a provider to move money.\n *\n * `ambiguous` is the one that matters and the one most interfaces omit. A\n * timeout tells you nothing about whether the charge landed, and guessing is\n * how a customer gets billed twice. It maps onto the platform's own\n * `AdapterOutcomeKind`, so an ambiguous payment routes to reconciliation with\n * durable evidence instead of being retried.\n */\nexport type PaymentOutcome = \"succeeded\" | \"failed\" | \"ambiguous\";\n\nexport interface PaymentResult {\n\toutcome: PaymentOutcome;\n\t/** The provider's own identifier, for reconciliation. Required when known. */\n\tproviderReference?: string;\n\t/** Provider-supplied reason, for evidence rather than for branching. */\n\treason?: string;\n}\n\nexport interface PaymentRequest {\n\t/** Caller-stable key. The same key must never move money twice. */\n\tidempotencyKey: string;\n\tamount: MinorUnitAmount;\n}\n\nexport interface PaymentsPort {\n\tcharge(request: PaymentRequest): Promise<PaymentResult>;\n}\n\n// ── Search and recommendation ───────────────────────────────────────────────\n\n/**\n * A latency-critical read path, deliberately outside the governed pipeline.\n *\n * Search results are pointers, not authority. An identifier appearing in a\n * result set says the index knows about it, never that this actor may read it,\n * so anything the viewer then opens still goes through `ProjectionHost`.\n */\nexport interface SearchHit {\n\t/** Identifier a governed read can resolve. Never the record itself. */\n\tid: string;\n\tscore: number;\n}\n\nexport interface SearchQuery {\n\ttext: string;\n\tlimit: number;\n\t/** Narrowing the index can apply cheaply. Never a substitute for authorization. */\n\tfilters?: Record<string, string>;\n}\n\nexport interface SearchPort {\n\tquery(query: SearchQuery): Promise<{ hits: SearchHit[]; total: number }>;\n}\n\n// ── Completion ingress ──────────────────────────────────────────────────────\n//\n// An external system that finished work the host handed it calls back. The\n// host's completion ingress settles the invocation by reference, but it takes\n// invocation, tenant, space, and provider as trusted arguments. What sits in\n// front of it is the adapter this port describes: it verifies the callback,\n// resolves the external reference through server-held state, and derives\n// every scope field from that state. Authentication schemes are the\n// provider's business, so the suite proves behaviour and prescribes no\n// mechanism.\n\nexport interface CompletionIngressCallback {\n\t/** Which external system this callback claims to come from. */\n\tprovider: string;\n\t/** Whatever the provider presents to prove itself: a signature, a token, a certificate identity. Opaque here. */\n\tcredential: unknown;\n\t/** The callback body as received. */\n\tpayload: unknown;\n\t/** RFC 3339 instant the callback was received. */\n\treceivedAt: string;\n}\n\nexport interface CompletionIngressScope {\n\ttenantId: string;\n\tspaceId: string;\n\tactionInvocationId: string;\n}\n\nexport type CompletionIngressRefusal =\n\t| \"invalid_credential\"\n\t| \"malformed\"\n\t| \"unknown_reference\"\n\t| \"provider_mismatch\"\n\t| \"scope_mismatch\"\n\t| \"not_settled\";\n\n/** How the host answered once the adapter forwarded a verified completion. */\nexport type CompletionIngressOutcome = \"completed\" | \"failed\" | \"replayed\" | \"reconciliation_required\";\n\nexport interface CompletionIngressAccepted {\n\taccepted: true;\n\t/** Derived from server-held state, never from the payload. */\n\tscope: CompletionIngressScope;\n\tprovider: string;\n\texternalReference: string;\n\toutcome: CompletionIngressOutcome;\n\t/** Secret-free record of what was verified and forwarded. */\n\taudit: Record<string, unknown>;\n}\n\nexport interface CompletionIngressRefused {\n\taccepted: false;\n\trefusal: CompletionIngressRefusal;\n\t/** Secret-free record of what was refused and why. Refusals are auditable too. */\n\taudit: Record<string, unknown>;\n}\n\nexport type CompletionIngressResult = CompletionIngressAccepted | CompletionIngressRefused;\n\nexport interface CompletionIngressPort {\n\treceive(callback: CompletionIngressCallback): Promise<CompletionIngressResult>;\n}\n\nexport interface CompletionIngressFixtures {\n\tprovider: string;\n\t/** A different provider the same reference must not be accepted from. */\n\totherProvider: string;\n\t/** A credential the adapter verifies for `provider` within `expectedScope.tenantId`. */\n\tvalidCredential: unknown;\n\tinvalidCredential: unknown;\n\t/** A reference the adapter's server-held binding resolves to `expectedScope`. */\n\tboundReference: string;\n\texpectedScope: CompletionIngressScope;\n\t/** A reference bound to a different tenant than `validCredential` is good for. */\n\tforeignReference: string;\n\t/** The scope `foreignReference` resolves to: a real binding, so a claimed scope can name something that exists. */\n\tforeignScope: CompletionIngressScope;\n\t/** A credential the adapter verifies for `provider` within `foreignScope.tenantId`, proving the foreign binding is live. */\n\tforeignCredential: unknown;\n\tunknownReference: string;\n\t/**\n\t * Build a payload as the provider would send it. `evidence` varies the\n\t * result the callback carries; `claimedScope` is scope the sender asserts\n\t * and the adapter must never trust.\n\t */\n\tpayload(input: { reference: string; evidence: string; claimedScope?: CompletionIngressScope }): unknown;\n\t/** Strings that must never appear in any audit record: secrets, signing keys, raw credentials. */\n\tsecrets: readonly string[];\n\t/**\n\t * What the host behind the adapter actually did. The port surface cannot\n\t * tell a first completion from an absorbed replay, since the host answers\n\t * both with the settled invocation, so the suite asks the fixture how many\n\t * times the reference was settled for real.\n\t */\n\tobserved: { settlements(reference: string): Promise<number> | number };\n\t/** Put the adapter, its bindings, and the host it forwards to back to a fresh state. */\n\treset(): Promise<void> | void;\n}\n\nconst RECEIVED_AT = \"2026-09-02T10:00:00Z\";\n\nfunction auditIsSecretFree(result: CompletionIngressResult, secrets: readonly string[], where: string): void {\n\texpect(result.audit !== null && typeof result.audit === \"object\", `${where}: no audit record was produced`);\n\tconst serialized = JSON.stringify(result.audit);\n\tfor (const secret of secrets) {\n\t\tif (secret.length === 0) continue;\n\t\texpect(!serialized.includes(secret), `${where}: the audit record contains a secret`);\n\t}\n}\n\nfunction sameScope(left: CompletionIngressScope, right: CompletionIngressScope): boolean {\n\treturn left.tenantId === right.tenantId && left.spaceId === right.spaceId && left.actionInvocationId === right.actionInvocationId;\n}\n\n/**\n * Every completion-ingress adapter must pass these. They prove the adapter\n * derives scope from what the server holds, refuses what it cannot verify,\n * forwards repeats and contradictions to the host's judgement, keeps secrets\n * out of its evidence, and holds up when callbacks arrive together.\n */\nexport function completionIngressPortChecks(fixtures: CompletionIngressFixtures): PortCheck<CompletionIngressPort>[] {\n\tconst callback = (input: { reference: string; evidence: string; claimedScope?: CompletionIngressScope; provider?: string; credential?: unknown }): CompletionIngressCallback => ({\n\t\tprovider: input.provider ?? fixtures.provider,\n\t\tcredential: input.credential === undefined ? fixtures.validCredential : input.credential,\n\t\tpayload: fixtures.payload({ reference: input.reference, evidence: input.evidence, ...(input.claimedScope ? { claimedScope: input.claimedScope } : {}) }),\n\t\treceivedAt: RECEIVED_AT,\n\t});\n\treturn [\n\t\t{\n\t\t\tid: \"completion-ingress.derives-scope-from-server-state\",\n\t\t\ttitle: \"a verified callback is forwarded under the scope the server-held binding resolves, and the outcome is the host's\",\n\t\t\tasync run(port) {\n\t\t\t\tawait fixtures.reset();\n\t\t\t\tconst result = await port.receive(callback({ reference: fixtures.boundReference, evidence: \"a\" }));\n\t\t\t\texpect(result.accepted, `a verified callback was refused: ${result.accepted ? \"\" : result.refusal}`);\n\t\t\t\tif (!result.accepted) return;\n\t\t\t\texpect(sameScope(result.scope, fixtures.expectedScope), \"the forwarded scope is not the one the binding resolves\");\n\t\t\t\texpect(result.externalReference === fixtures.boundReference, \"the forwarded reference is not the bound one\");\n\t\t\t\texpect(result.provider === fixtures.provider, \"the forwarded provider is not the verified one\");\n\t\t\t\texpect(result.outcome === \"completed\" || result.outcome === \"failed\", `a first completion reported \"${result.outcome}\"`);\n\t\t\t\tauditIsSecretFree(result, fixtures.secrets, \"accepted callback\");\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"completion-ingress.rejects-invalid-credential\",\n\t\t\ttitle: \"an unverifiable credential is refused before anything is resolved or forwarded\",\n\t\t\tasync run(port) {\n\t\t\t\tawait fixtures.reset();\n\t\t\t\tconst result = await port.receive(callback({ reference: fixtures.boundReference, evidence: \"a\", credential: fixtures.invalidCredential }));\n\t\t\t\texpect(!result.accepted && result.refusal === \"invalid_credential\", \"an invalid credential was not refused as invalid_credential\");\n\t\t\t\tauditIsSecretFree(result, fixtures.secrets, \"refused credential\");\n\t\t\t\t// The invocation must still be untouched: a later valid callback is a first completion.\n\t\t\t\tconst later = await port.receive(callback({ reference: fixtures.boundReference, evidence: \"a\" }));\n\t\t\t\texpect(later.accepted && (later.outcome === \"completed\" || later.outcome === \"failed\"), \"the refused callback reached the host\");\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"completion-ingress.rejects-unknown-reference\",\n\t\t\ttitle: \"a reference no binding resolves is refused rather than guessed at\",\n\t\t\tasync run(port) {\n\t\t\t\tawait fixtures.reset();\n\t\t\t\tconst result = await port.receive(callback({ reference: fixtures.unknownReference, evidence: \"a\" }));\n\t\t\t\texpect(!result.accepted && result.refusal === \"unknown_reference\", \"an unknown reference was not refused as unknown_reference\");\n\t\t\t\tauditIsSecretFree(result, fixtures.secrets, \"unknown reference\");\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"completion-ingress.ignores-claimed-scope\",\n\t\t\ttitle: \"scope asserted in the payload never becomes the forwarded scope\",\n\t\t\tasync run(port) {\n\t\t\t\tawait fixtures.reset();\n\t\t\t\t// The claimed scope is a real binding elsewhere, so an adapter that\n\t\t\t\t// trusts the payload only when the claim resolves is caught too.\n\t\t\t\tconst result = await port.receive(callback({ reference: fixtures.boundReference, evidence: \"a\", claimedScope: fixtures.foreignScope }));\n\t\t\t\tif (result.accepted) {\n\t\t\t\t\texpect(sameScope(result.scope, fixtures.expectedScope), \"the sender's claimed scope was forwarded\");\n\t\t\t\t} else {\n\t\t\t\t\texpect(result.refusal === \"scope_mismatch\" || result.refusal === \"malformed\", `a claimed scope was refused as \"${result.refusal}\"`);\n\t\t\t\t}\n\t\t\t\tauditIsSecretFree(result, fixtures.secrets, \"claimed scope\");\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"completion-ingress.rejects-provider-mismatch\",\n\t\t\ttitle: \"a reference bound to one provider is not accepted from another\",\n\t\t\tasync run(port) {\n\t\t\t\tawait fixtures.reset();\n\t\t\t\tconst result = await port.receive(callback({ reference: fixtures.boundReference, evidence: \"a\", provider: fixtures.otherProvider }));\n\t\t\t\texpect(!result.accepted, \"a callback from the wrong provider was accepted\");\n\t\t\t\texpect(!result.accepted && (result.refusal === \"provider_mismatch\" || result.refusal === \"invalid_credential\"), \"the wrong provider was refused for another reason\");\n\t\t\t\tauditIsSecretFree(result, fixtures.secrets, \"provider mismatch\");\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"completion-ingress.rejects-cross-tenant-reference\",\n\t\t\ttitle: \"a credential good for one tenant cannot complete another tenant's reference\",\n\t\t\tasync run(port) {\n\t\t\t\tawait fixtures.reset();\n\t\t\t\t// First prove the foreign binding is live, or a refusal below would\n\t\t\t\t// be \"unknown\" for the wrong reason.\n\t\t\t\tconst theirs = await port.receive(callback({ reference: fixtures.foreignReference, evidence: \"a\", credential: fixtures.foreignCredential }));\n\t\t\t\texpect(theirs.accepted, \"the foreign reference does not resolve for its own tenant, so the fixture proves nothing\");\n\t\t\t\tif (theirs.accepted) expect(sameScope(theirs.scope, fixtures.foreignScope), \"the foreign reference resolved to an unexpected scope\");\n\t\t\t\tawait fixtures.reset();\n\t\t\t\tconst result = await port.receive(callback({ reference: fixtures.foreignReference, evidence: \"a\" }));\n\t\t\t\texpect(!result.accepted, \"another tenant's reference was accepted\");\n\t\t\t\texpect(!result.accepted && (result.refusal === \"scope_mismatch\" || result.refusal === \"unknown_reference\" || result.refusal === \"invalid_credential\"), \"the foreign reference was refused for another reason\");\n\t\t\t\tauditIsSecretFree(result, fixtures.secrets, \"cross-tenant reference\");\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"completion-ingress.absorbs-exact-replay\",\n\t\t\ttitle: \"the same callback twice is accepted twice with the same scope, and the second is a replay\",\n\t\t\tasync run(port) {\n\t\t\t\tawait fixtures.reset();\n\t\t\t\tconst first = await port.receive(callback({ reference: fixtures.boundReference, evidence: \"a\" }));\n\t\t\t\tconst second = await port.receive(callback({ reference: fixtures.boundReference, evidence: \"a\" }));\n\t\t\t\texpect(first.accepted && second.accepted, \"an exact replay was refused\");\n\t\t\t\tif (!first.accepted || !second.accepted) return;\n\t\t\t\texpect(sameScope(first.scope, second.scope), \"a replay was forwarded under a different scope\");\n\t\t\t\texpect(second.outcome === \"replayed\" || second.outcome === first.outcome, `a replay reported \"${second.outcome}\" after \"${first.outcome}\"`);\n\t\t\t\texpect((await fixtures.observed.settlements(fixtures.boundReference)) === 1, \"an exact replay settled the invocation a second time\");\n\t\t\t\tauditIsSecretFree(second, fixtures.secrets, \"replay\");\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"completion-ingress.routes-changed-evidence\",\n\t\t\ttitle: \"the same reference with different evidence is a contradiction the host reconciles, not a replay\",\n\t\t\tasync run(port) {\n\t\t\t\tawait fixtures.reset();\n\t\t\t\tconst first = await port.receive(callback({ reference: fixtures.boundReference, evidence: \"a\" }));\n\t\t\t\tconst changed = await port.receive(callback({ reference: fixtures.boundReference, evidence: \"b\" }));\n\t\t\t\texpect(first.accepted, \"the first callback was refused\");\n\t\t\t\texpect(changed.accepted, \"changed evidence was refused instead of routed to reconciliation\");\n\t\t\t\tif (!changed.accepted) return;\n\t\t\t\texpect(changed.outcome === \"reconciliation_required\", `changed evidence reported \"${changed.outcome}\"`);\n\t\t\t\tauditIsSecretFree(changed, fixtures.secrets, \"changed evidence\");\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"completion-ingress.refusals-are-auditable\",\n\t\t\ttitle: \"every refusal leaves a secret-free audit record naming the refusal\",\n\t\t\tasync run(port) {\n\t\t\t\tawait fixtures.reset();\n\t\t\t\tconst results = await Promise.all([\n\t\t\t\t\tport.receive(callback({ reference: fixtures.boundReference, evidence: \"a\", credential: fixtures.invalidCredential })),\n\t\t\t\t\tport.receive(callback({ reference: fixtures.unknownReference, evidence: \"a\" })),\n\t\t\t\t\tport.receive(callback({ reference: fixtures.boundReference, evidence: \"a\", provider: fixtures.otherProvider })),\n\t\t\t\t]);\n\t\t\t\tfor (const result of results) {\n\t\t\t\t\texpect(!result.accepted, \"a refusal case was accepted\");\n\t\t\t\t\tif (result.accepted) continue;\n\t\t\t\t\texpect(Object.keys(result.audit).length > 0, \"a refusal produced an empty audit record\");\n\t\t\t\t\t// A floor, not a schema: the record has to say why, in the same\n\t\t\t\t\t// words the result does. The shape of the record is the adapter's.\n\t\t\t\t\texpect(JSON.stringify(result.audit).includes(result.refusal), \"the audit record does not name the refusal\");\n\t\t\t\t\tauditIsSecretFree(result, fixtures.secrets, `refusal ${result.refusal}`);\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"completion-ingress.holds-under-concurrent-callbacks\",\n\t\t\ttitle: \"identical callbacks arriving together are all accepted under one scope, with exactly one first completion\",\n\t\t\tasync run(port) {\n\t\t\t\tawait fixtures.reset();\n\t\t\t\tconst results = await Promise.all(Array.from({ length: 8 }, () => port.receive(callback({ reference: fixtures.boundReference, evidence: \"a\" }))));\n\t\t\t\tconst accepted = results.filter((result): result is CompletionIngressAccepted => result.accepted);\n\t\t\t\texpect(accepted.length === results.length, `${results.length - accepted.length} of ${results.length} concurrent callbacks were refused`);\n\t\t\t\texpect(accepted.every((result) => sameScope(result.scope, fixtures.expectedScope)), \"concurrent callbacks were forwarded under different scopes\");\n\t\t\t\tconst settled = accepted.filter((result) => result.outcome === \"completed\" || result.outcome === \"failed\");\n\t\t\t\texpect(settled.length >= 1, \"no concurrent callback settled the invocation\");\n\t\t\t\texpect(accepted.every((result) => result.outcome !== \"reconciliation_required\"), \"identical concurrent callbacks were reported as contradicting each other\");\n\t\t\t\texpect((await fixtures.observed.settlements(fixtures.boundReference)) === 1, \"concurrent identical callbacks settled the invocation more than once\");\n\t\t\t},\n\t\t},\n\t];\n}\n\n// ── Customer relationship ───────────────────────────────────────────────────\n\n/**\n * An outbound record of something that already happened.\n *\n * A CRM is downstream of the governed pipeline, never upstream of it. It is\n * told; it does not decide. Keeping this one-way is what stops a marketing\n * system becoming a source of business truth.\n */\nexport interface CustomerEvent {\n\t/** Stable key so redelivery does not duplicate the record. */\n\teventId: string;\n\tsubjectId: string;\n\ttype: string;\n\toccurredAt: string;\n\tattributes?: Record<string, JsonLike>;\n}\n\nexport interface CustomerRecordPort {\n\trecord(event: CustomerEvent): Promise<void>;\n}\n\n// ── Defining a port ─────────────────────────────────────────────────────────\n\n/**\n * A port, as a first-class thing rather than a name in a string.\n *\n * Fabric ships a handful of port definitions because they speak open standards\n * and everyone needs them. It cannot ship the rest: an enterprise integrates\n * hundreds of external systems, and a framework that requires a pull request\n * for each one is not a framework. A vertical, a partner or a vendor defines\n * its own port with {@link definePort} and every mechanism here applies to it\n * unchanged — Fabric never learns what the system behind it is.\n *\n * The definition binds an id to the suite that certifies an adapter for it.\n * That binding is the point: without it, \"this port is satisfied\" only ever\n * meant \"somebody registered something claiming to be it\".\n */\nexport interface PortDefinition<TPort, TFixtures = void> {\n\t/**\n\t * Namespaced identifier, for example `fabric.flags` or `acme.docusign`.\n\t * Namespacing is required so a port defined outside this repository cannot\n\t * collide with one defined inside it.\n\t */\n\tid: string;\n\t/**\n\t * Version of the port contract itself, not of any adapter.\n\t *\n\t * Bump it when the interface changes shape. Certification is recorded\n\t * against a version, so raising it correctly invalidates every adapter\n\t * certified against the old contract instead of silently carrying them\n\t * forward.\n\t */\n\tversion: string;\n\t/** The open standard this port speaks, where one exists. */\n\tstandard?: { name: string; version?: string };\n\t/** One-line statement of what an adapter behind this port is responsible for. */\n\tdescription: string;\n\t/** The suite every adapter must pass. */\n\tchecks(fixtures: TFixtures): readonly PortCheck<TPort>[];\n}\n\n// Segments after the first take exactly the manifest's grammar, so every\n// namespaced name a capability can declare is a name a port can define. The\n// one shape a manifest permits that this does not is a *dotless* name such as\n// \"flags\", by design: namespacing is what keeps a port defined outside this\n// repository from colliding with one defined inside it, and a dotless\n// requirement has no namespace to protect.\nconst PORT_ID = /^[a-z][a-z0-9-]*(?:\\.[a-z0-9-]+)+$/;\n\n/**\n * Declare a port. Validates the definition itself, because a malformed port\n * definition produces adapters that certify against nothing.\n */\nexport function definePort<TPort, TFixtures = void>(\n\tdefinition: PortDefinition<TPort, TFixtures>,\n): PortDefinition<TPort, TFixtures> {\n\tif (!PORT_ID.test(definition.id)) {\n\t\tthrow new Error(`Port id \"${definition.id}\" must be namespaced lowercase, for example \"acme.docusign\".`);\n\t}\n\tif (!/^\\d+\\.\\d+\\.\\d+$/.test(definition.version)) {\n\t\tthrow new Error(`Port \"${definition.id}\" version must be a semver version.`);\n\t}\n\tif (!definition.description.trim()) {\n\t\tthrow new Error(`Port \"${definition.id}\" must describe what an adapter behind it is responsible for.`);\n\t}\n\tif (typeof definition.checks !== \"function\") {\n\t\tthrow new Error(`Port \"${definition.id}\" must supply a conformance suite.`);\n\t}\n\treturn definition;\n}\n\n/**\n * Confirm a port's suite can actually fail, and that its check ids are unique.\n *\n * A suite whose checks all pass against a deliberately broken adapter certifies\n * nothing while looking rigorous, which is worse than having no suite at all.\n * Run this against a stub that does the wrong thing when you author a port.\n */\nexport async function assertPortSuiteHasTeeth<TPort, TFixtures>(\n\tdefinition: PortDefinition<TPort, TFixtures>,\n\tfixtures: TFixtures,\n\tbrokenAdapters: TPort | readonly TPort[],\n): Promise<void> {\n\tconst checks = definition.checks(fixtures);\n\tif (checks.length === 0) {\n\t\tthrow new Error(`Port \"${definition.id}\" declares no checks, so no adapter can be certified against it.`);\n\t}\n\tconst ids = new Set<string>();\n\tfor (const check of checks) {\n\t\tif (ids.has(check.id)) throw new Error(`Port \"${definition.id}\" declares check \"${check.id}\" twice.`);\n\t\tids.add(check.id);\n\t}\n\t// Every check must be caught by *some* adapter in the set, not all of them\n\t// by one. Demanding a single stub fail every check is unsatisfiable for any\n\t// suite containing a fixture-liveness guard, because such a guard bites on\n\t// the complement of what the checks it guards bite on: an adapter returning\n\t// nothing trips the guard, and an adapter returning something malformed\n\t// trips the checks. Supply one adapter per way of being wrong.\n\tconst adapters = Array.isArray(brokenAdapters) ? brokenAdapters : [brokenAdapters as TPort];\n\tif (adapters.length === 0) {\n\t\tthrow new Error(`Port \"${definition.id}\" needs at least one deliberately broken adapter to prove its suite bites.`);\n\t}\n\n\tconst uncaught = new Set(checks.map((check) => check.id));\n\tfor (const adapter of adapters) {\n\t\tfor (const check of checks) {\n\t\t\tif (!uncaught.has(check.id)) continue;\n\t\t\ttry {\n\t\t\t\tawait check.run(adapter);\n\t\t\t} catch {\n\t\t\t\tuncaught.delete(check.id);\n\t\t\t}\n\t\t}\n\t}\n\tif (uncaught.size > 0) {\n\t\tthrow new Error(\n\t\t\t`Port \"${definition.id}\" has ${uncaught.size} check(s) that no supplied broken adapter trips, so they prove nothing: ${[...uncaught].join(\", \")}.`,\n\t\t);\n\t}\n}\n\n// ── Certifying an adapter ───────────────────────────────────────────────────\n\n/** Evidence that an adapter passed a port's suite, and which contract it passed. */\nexport interface AdapterCertification {\n\tportId: string;\n\t/** Port contract version the adapter was certified against. */\n\tportVersion: string;\n\tchecks: string[];\n\tcertifiedAt: string;\n}\n\nexport interface CertifiedAdapter extends RegisteredAdapter {\n\tcertification: AdapterCertification;\n}\n\n/**\n * Run a port's suite against an adapter and record what it passed.\n *\n * Registration is a claim; certification is evidence. Deployment gates can then\n * require the second rather than accepting the first.\n */\nexport async function certifyAdapter<TPort, TFixtures>(input: {\n\tdefinition: PortDefinition<TPort, TFixtures>;\n\tfixtures: TFixtures;\n\tadapter: TPort;\n\tvendor: string;\n\tversion?: string;\n\tnow?: Date;\n}): Promise<CertifiedAdapter> {\n\t// Validate the definition here too: a definition not built through\n\t// definePort can carry a version like \"1.0\", and the certification it\n\t// produces is then reported downstream as missing rather than malformed.\n\tdefinePort(input.definition);\n\tconst checks = input.definition.checks(input.fixtures);\n\tif (checks.length === 0) {\n\t\tthrow new Error(`Port \"${input.definition.id}\" declares no checks, so no adapter can be certified against it.`);\n\t}\n\tconst passed: string[] = [];\n\tfor (const check of checks) {\n\t\ttry {\n\t\t\tawait check.run(input.adapter);\n\t\t} catch (error) {\n\t\t\tthrow new Error(\n\t\t\t\t`Adapter \"${input.vendor}\" failed port \"${input.definition.id}\" check \"${check.id}\": ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t);\n\t\t}\n\t\tpassed.push(check.id);\n\t}\n\treturn {\n\t\tport: input.definition.id,\n\t\tvendor: input.vendor,\n\t\t...(input.version === undefined ? {} : { version: input.version }),\n\t\t...(input.definition.standard ? { standard: input.definition.standard } : {}),\n\t\tcertification: {\n\t\t\tportId: input.definition.id,\n\t\t\tportVersion: input.definition.version,\n\t\t\tchecks: passed,\n\t\t\tcertifiedAt: (input.now ?? new Date()).toISOString(),\n\t\t},\n\t};\n}\n\n/**\n * Whether an adapter carries certification evidence *for this port*.\n *\n * Testing only that a `certification` property exists made the evidence a claim\n * again: any hand-written object with the right property name satisfied the\n * gate. The evidence has to be internally consistent and about the port being\n * required, or it is decoration.\n */\nfunction isCertifiedFor(adapter: RegisteredAdapter, portName: string): adapter is CertifiedAdapter {\n\tconst certification = (adapter as CertifiedAdapter).certification;\n\tif (!certification || typeof certification !== \"object\") return false;\n\tif (certification.portId !== portName) return false;\n\tif (certification.portId !== adapter.port) return false;\n\tif (!/^\\d+\\.\\d+\\.\\d+$/.test(certification.portVersion ?? \"\")) return false;\n\tif (!Array.isArray(certification.checks) || certification.checks.length === 0) return false;\n\tif (Number.isNaN(Date.parse(certification.certifiedAt ?? \"\"))) return false;\n\treturn true;\n}\n\n// ── Requirement satisfaction ────────────────────────────────────────────────\n\nexport interface PortRequirement {\n\tname: string;\n\tversion?: string;\n\tstandard?: { name: string; version?: string };\n}\n\n/** The subset of capability metadata that declares what ports it needs. */\nexport interface PortRequiringCapability {\n\tnamespace: string;\n\trequirements?: { ports?: PortRequirement[] };\n}\n\nexport interface RegisteredAdapter {\n\t/** Port this adapter implements, matching the requirement's `name`. */\n\tport: string;\n\tvendor: string;\n\tversion?: string;\n\tstandard?: { name: string; version?: string };\n}\n\nexport type PortFindingCode =\n\t| \"unsatisfied_port\"\n\t| \"standard_not_spoken\"\n\t| \"version_mismatch\"\n\t| \"uncertified_adapter\"\n\t| \"stale_certification\";\n\nexport interface PortFinding {\n\tcode: PortFindingCode;\n\tport: string;\n\tmessage: string;\n}\n\nexport interface PortValidationResult {\n\tvalid: boolean;\n\tfindings: PortFinding[];\n}\n\n/**\n * Checks that every port a capability declares is backed by a registered adapter.\n * `CapabilityPortRequirement` is otherwise a name that resolves against nothing;\n * this is what turns the declaration into a deployment-time gate.\n *\n * Version matching is exact. Range negotiation belongs to whatever installs the\n * adapters, and pretending to do semver here would be worse than not doing it.\n */\nexport function validatePortRequirements(input: {\n\tcapability: PortRequiringCapability;\n\tadapters: readonly RegisteredAdapter[];\n\t/**\n\t * Port definitions in force. Supplying them checks that whatever\n\t * certification is present was issued against the current contract version.\n\t *\n\t * They do not by themselves require certification to exist: pass\n\t * `requireCertification` for that. Definitions alone catch a stale\n\t * certification, not a missing one, and an adapter carrying none passes.\n\t */\n\tdefinitions?: readonly PortDefinition<never, never>[];\n\t/** Require certification for every required port. Defaults to false. */\n\trequireCertification?: boolean;\n}): PortValidationResult {\n\tconst definitions = new Map((input.definitions ?? []).map((definition) => [definition.id, definition]));\n\tconst findings: PortFinding[] = [];\n\tfor (const requirement of input.capability.requirements?.ports ?? []) {\n\t\tconst candidates = input.adapters.filter((adapter) => adapter.port === requirement.name);\n\t\tif (candidates.length === 0) {\n\t\t\tfindings.push({\n\t\t\t\tcode: \"unsatisfied_port\",\n\t\t\t\tport: requirement.name,\n\t\t\t\tmessage: `capability \"${input.capability.namespace}\" requires port \"${requirement.name}\" and no adapter is registered for it`,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\t// Narrowed as each constraint is applied, so one adapter cannot satisfy\n\t\t// the standard while a different one satisfies the version.\n\t\tlet eligible = candidates;\n\t\tif (requirement.standard) {\n\t\t\teligible = eligible.filter((adapter) => adapter.standard?.name === requirement.standard!.name);\n\t\t\tif (eligible.length === 0) {\n\t\t\t\tfindings.push({\n\t\t\t\t\tcode: \"standard_not_spoken\",\n\t\t\t\t\tport: requirement.name,\n\t\t\t\t\tmessage: `port \"${requirement.name}\" must speak \"${requirement.standard.name}\"; registered adapters are ${candidates.map((adapter) => `${adapter.vendor}(${adapter.standard?.name ?? \"no standard\"})`).join(\", \")}`,\n\t\t\t\t});\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (requirement.standard.version) {\n\t\t\t\tconst atVersion = eligible.filter((adapter) => adapter.standard?.version === requirement.standard!.version);\n\t\t\t\tif (atVersion.length === 0) {\n\t\t\t\t\tfindings.push({\n\t\t\t\t\t\tcode: \"standard_not_spoken\",\n\t\t\t\t\t\tport: requirement.name,\n\t\t\t\t\t\tmessage: `port \"${requirement.name}\" must speak \"${requirement.standard.name}\" version \"${requirement.standard.version}\"; registered adapters speak ${eligible.map((adapter) => adapter.standard?.version ?? \"an unstated version\").join(\", \")}`,\n\t\t\t\t\t});\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\teligible = atVersion;\n\t\t\t}\n\t\t}\n\t\tif (requirement.version) {\n\t\t\tconst atVersion = eligible.filter((adapter) => adapter.version === requirement.version);\n\t\t\tif (atVersion.length === 0) {\n\t\t\t\tfindings.push({\n\t\t\t\t\tcode: \"version_mismatch\",\n\t\t\t\t\tport: requirement.name,\n\t\t\t\t\tmessage: `port \"${requirement.name}\" requires version \"${requirement.version}\"; eligible adapters are ${eligible.map((adapter) => `${adapter.vendor}@${adapter.version ?? \"unversioned\"}`).join(\", \")}`,\n\t\t\t\t});\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\teligible = atVersion;\n\t\t}\n\n\t\t// Registration is a claim. Certification is evidence that the adapter\n\t\t// passed the port's own suite, against the contract version in force.\n\t\tconst definition = definitions.get(requirement.name);\n\t\tif (input.requireCertification || definition) {\n\t\t\tconst certified = eligible.filter((adapter) => isCertifiedFor(adapter, requirement.name));\n\t\t\tif (certified.length === 0) {\n\t\t\t\tif (input.requireCertification) {\n\t\t\t\t\tfindings.push({\n\t\t\t\t\t\tcode: \"uncertified_adapter\",\n\t\t\t\t\t\tport: requirement.name,\n\t\t\t\t\t\tmessage: `port \"${requirement.name}\" has eligible adapters (${eligible.map((adapter) => adapter.vendor).join(\", \")}) but none carries certification evidence`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (definition && !certified.some((adapter) => adapter.certification.portVersion === definition.version)) {\n\t\t\t\tfindings.push({\n\t\t\t\t\tcode: \"stale_certification\",\n\t\t\t\t\tport: requirement.name,\n\t\t\t\t\tmessage: `port \"${requirement.name}\" is at contract version ${definition.version}; adapters are certified against ${certified.map((adapter) => `${adapter.vendor}@${adapter.certification.portVersion}`).join(\", \")}`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\treturn { valid: findings.length === 0, findings };\n}\n\nexport function assertPortRequirementsSatisfied(input: {\n\tcapability: PortRequiringCapability;\n\tadapters: readonly RegisteredAdapter[];\n\tdefinitions?: readonly PortDefinition<never, never>[];\n\trequireCertification?: boolean;\n}): void {\n\tconst result = validatePortRequirements(input);\n\tif (result.valid) return;\n\tthrow new Error([\n\t\t`Port requirements for \"${input.capability.namespace}\" are not satisfied:`,\n\t\t...result.findings.map((finding) => ` - ${finding.message}`),\n\t].join(\"\\n\"));\n}\n\n// ── Adapter contract kit ────────────────────────────────────────────────────\n\nexport interface PortCheck<TPort> {\n\tid: string;\n\ttitle: string;\n\t/** Throws on failure, exactly as an assertion would. */\n\trun(port: TPort): Promise<void>;\n}\n\nclass PortContractFailure extends Error {\n\toverride readonly name = \"PortContractFailure\";\n}\n\nfunction expect(condition: unknown, message: string): asserts condition {\n\tif (!condition) throw new PortContractFailure(message);\n}\n\n/**\n * Every flags adapter must pass these, so swapping vendors is an adapter build\n * plus a configuration change rather than a migration.\n */\nexport function flagsPortChecks(): PortCheck<FlagsPort>[] {\n\tconst unknownKey = \"fabric.contract.definitely-not-configured\";\n\treturn [\n\t\t{\n\t\t\tid: \"flags.default-on-unknown-key\",\n\t\t\ttitle: \"an unknown flag resolves to the supplied default rather than throwing\",\n\t\t\tasync run(port) {\n\t\t\t\tconst result = await port.resolveBoolean(unknownKey, true);\n\t\t\t\texpect(result.value === true, `an unknown flag returned ${String(result.value)} instead of the supplied default`);\n\t\t\t\texpect(\n\t\t\t\t\tresult.reason === \"DEFAULT\" || result.reason === \"ERROR\",\n\t\t\t\t\t`an unknown flag resolved with reason \"${result.reason}\"; a default or error was expected`,\n\t\t\t\t);\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"flags.default-is-typed\",\n\t\t\ttitle: \"each typed resolver returns its own type\",\n\t\t\tasync run(port) {\n\t\t\t\texpect(typeof (await port.resolveBoolean(unknownKey, false)).value === \"boolean\", \"resolveBoolean did not return a boolean\");\n\t\t\t\texpect(typeof (await port.resolveString(unknownKey, \"fallback\")).value === \"string\", \"resolveString did not return a string\");\n\t\t\t\texpect(typeof (await port.resolveNumber(unknownKey, 42)).value === \"number\", \"resolveNumber did not return a number\");\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"flags.evaluation-is-pure\",\n\t\t\ttitle: \"the same key and context resolve the same way twice\",\n\t\t\tasync run(port) {\n\t\t\t\tconst context = { targetingKey: \"fabric-contract-subject\" };\n\t\t\t\tconst first = await port.resolveString(unknownKey, \"fallback\", context);\n\t\t\t\tconst second = await port.resolveString(unknownKey, \"fallback\", context);\n\t\t\t\texpect(first.value === second.value, `the same evaluation returned \"${first.value}\" then \"${second.value}\"`);\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"flags.tolerates-absent-context\",\n\t\t\ttitle: \"evaluation without a context does not throw\",\n\t\t\tasync run(port) {\n\t\t\t\tawait port.resolveBoolean(unknownKey, false);\n\t\t\t},\n\t\t},\n\t];\n}\n\n/**\n * The suite an identity adapter must pass before it can stand behind\n * `IdentityPort`. Every check here is a fail-closed property: the cost of\n * getting one wrong is a credential being trusted further than it proves.\n *\n * `validCredential` must be a credential the adapter verifies successfully,\n * and `expected` the claims it should resolve to.\n */\nexport function identityPortChecks(fixtures: {\n\tvalidCredential: string;\n\texpected: Pick<ActorClaims, \"subject\" | \"tenantId\">;\n\texpiredCredential?: string;\n}): PortCheck<IdentityPort>[] {\n\tconst checks: PortCheck<IdentityPort>[] = [\n\t\t{\n\t\t\tid: \"identity.rejects-garbage\",\n\t\t\ttitle: \"an unverifiable credential resolves to null rather than partial claims\",\n\t\t\tasync run(port) {\n\t\t\t\tconst result = await port.verify(\"not-a-credential\");\n\t\t\t\texpect(result === null, \"an unverifiable credential resolved to claims instead of null\");\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"identity.rejects-empty\",\n\t\t\ttitle: \"an empty credential resolves to null\",\n\t\t\tasync run(port) {\n\t\t\t\texpect((await port.verify(\"\")) === null, \"an empty credential resolved to claims\");\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"identity.resolves-valid\",\n\t\t\ttitle: \"a valid credential resolves to the expected subject and tenant\",\n\t\t\tasync run(port) {\n\t\t\t\tconst claims = await port.verify(fixtures.validCredential);\n\t\t\t\texpect(claims !== null, \"a valid credential failed to verify\");\n\t\t\t\texpect(claims?.subject === fixtures.expected.subject, `subject was \"${claims?.subject}\"`);\n\t\t\t\texpect(claims?.tenantId === fixtures.expected.tenantId, `tenantId was \"${claims?.tenantId}\"`);\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"identity.claims-are-complete\",\n\t\t\ttitle: \"resolved claims carry every field the platform derives actor context from\",\n\t\t\tasync run(port) {\n\t\t\t\tconst claims = await port.verify(fixtures.validCredential);\n\t\t\t\texpect(claims !== null, \"a valid credential failed to verify\");\n\t\t\t\tif (!claims) return;\n\t\t\t\texpect(IDENTITY_ACTOR_TYPES.includes(claims.actorType), `actorType \"${claims.actorType}\" is not a known actor kind`);\n\t\t\t\texpect(typeof claims.issuer === \"string\" && claims.issuer.length > 0, \"claims carry no issuer\");\n\t\t\t\t// The same grammar assertActorClaimsCoverScope enforces. Certifying\n\t\t\t\t// a looser one produces an adapter that passes here and is refused\n\t\t\t\t// on every request.\n\t\t\t\texpect(RFC3339.test(claims.issuedAt), `issuedAt \"${claims.issuedAt}\" is not RFC 3339 with an explicit offset`);\n\t\t\t\texpect(RFC3339.test(claims.expiresAt), `expiresAt \"${claims.expiresAt}\" is not RFC 3339 with an explicit offset`);\n\t\t\t\texpect(typeof claims.tenantId === \"string\" && claims.tenantId.length > 0, \"claims carry no tenant\");\n\t\t\t\texpect(\n\t\t\t\t\tclaims.spaceIds === \"tenant-wide\" || Array.isArray(claims.spaceIds),\n\t\t\t\t\t\"spaceIds must be an explicit list or the literal \\\"tenant-wide\\\"\",\n\t\t\t\t);\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"identity.carries-no-credential-material\",\n\t\t\ttitle: \"resolved claims never echo the credential back\",\n\t\t\tasync run(port) {\n\t\t\t\tconst claims = await port.verify(fixtures.validCredential);\n\t\t\t\texpect(claims !== null, \"a valid credential failed to verify, so this check proved nothing\");\n\t\t\t\tif (!claims) return;\n\t\t\t\tconst serialized = JSON.stringify(claims);\n\t\t\t\texpect(\n\t\t\t\t\t!serialized.includes(fixtures.validCredential),\n\t\t\t\t\t\"resolved claims contain the presented credential; claims must carry an opaque reference instead\",\n\t\t\t\t);\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"identity.verification-is-stable\",\n\t\t\ttitle: \"the same credential resolves the same subject twice\",\n\t\t\tasync run(port) {\n\t\t\t\tconst first = await port.verify(fixtures.validCredential);\n\t\t\t\tconst second = await port.verify(fixtures.validCredential);\n\t\t\t\texpect(first?.subject === second?.subject, \"the same credential resolved to two different subjects\");\n\t\t\t},\n\t\t},\n\t];\n\n\tif (fixtures.expiredCredential !== undefined) {\n\t\tchecks.push({\n\t\t\tid: \"identity.rejects-expired\",\n\t\t\ttitle: \"an expired credential resolves to null rather than stale claims\",\n\t\t\tasync run(port) {\n\t\t\t\tconst expiredCredential = fixtures.expiredCredential as string;\n\t\t\t\texpect((await port.verify(expiredCredential)) === null, \"an expired credential still resolved to claims\");\n\t\t\t},\n\t\t});\n\t}\n\n\treturn checks;\n}\n\n/** The suite a content adapter must pass. */\nexport function contentPortChecks(fixtures: {\n\tpresent: ContentQuery;\n\tabsentKey: string;\n}): PortCheck<ContentPort>[] {\n\treturn [\n\t\t{\n\t\t\tid: \"content.missing-resolves-null\",\n\t\t\ttitle: \"an unauthored key resolves to null rather than an invented default\",\n\t\t\tasync run(port) {\n\t\t\t\tconst result = await port.resolve({ ...fixtures.present, key: fixtures.absentKey });\n\t\t\t\texpect(result === null, \"an unauthored key resolved to content instead of null\");\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"content.revision-is-stable\",\n\t\t\ttitle: \"identical content resolves the same revision twice\",\n\t\t\tasync run(port) {\n\t\t\t\tconst first = await port.resolve(fixtures.present);\n\t\t\t\tconst second = await port.resolve(fixtures.present);\n\t\t\t\texpect(first !== null && second !== null, \"the fixture key is not authored\");\n\t\t\t\texpect(first?.revision === second?.revision, \"the same content reported two revisions, so it cannot be cached\");\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"content.carries-no-capability-reference\",\n\t\t\ttitle: \"authored content never carries a capability reference\",\n\t\t\tasync run(port) {\n\t\t\t\tconst result = await port.resolve(fixtures.present);\n\t\t\t\texpect(\n\t\t\t\t\t!JSON.stringify(result ?? {}).includes(\"capability://\"),\n\t\t\t\t\t\"content carried a capability reference; what a screen may reach is decided by a release, not by an author\",\n\t\t\t\t);\n\t\t\t},\n\t\t},\n\t];\n}\n\n/** The suite a payments adapter must pass. */\nexport function paymentsPortChecks(fixtures: {\n\trequest: PaymentRequest;\n}): PortCheck<PaymentsPort>[] {\n\treturn [\n\t\t{\n\t\t\tid: \"payments.rejects-non-integer-amount\",\n\t\t\ttitle: \"a fractional minor-unit amount is refused rather than rounded\",\n\t\t\tasync run(port) {\n\t\t\t\tlet refused = false;\n\t\t\t\ttry {\n\t\t\t\t\tawait port.charge({ ...fixtures.request, amount: { ...fixtures.request.amount, amount: 10.5 } });\n\t\t\t\t} catch {\n\t\t\t\t\trefused = true;\n\t\t\t\t}\n\t\t\t\texpect(refused, \"a fractional minor-unit amount was accepted; money is an integer or it drifts\");\n\t\t\t\t// The same request without the fraction must actually charge, or an\n\t\t\t\t// adapter that refuses everything, or succeeds at nothing, passes\n\t\t\t\t// every check in this suite.\n\t\t\t\tconst control = await port.charge({\n\t\t\t\t\t...fixtures.request,\n\t\t\t\t\tidempotencyKey: `${fixtures.request.idempotencyKey}:integer-probe`,\n\t\t\t\t});\n\t\t\t\texpect(\n\t\t\t\t\tcontrol.outcome === \"succeeded\",\n\t\t\t\t\t`the fixture charge resolved \"${control.outcome}\"; a suite run against an adapter that never succeeds certifies nothing`,\n\t\t\t\t);\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"payments.requires-idempotency-key\",\n\t\t\ttitle: \"a charge without a stable key is refused\",\n\t\t\tasync run(port) {\n\t\t\t\tlet refused = false;\n\t\t\t\ttry {\n\t\t\t\t\tawait port.charge({ ...fixtures.request, idempotencyKey: \"\" });\n\t\t\t\t} catch {\n\t\t\t\t\trefused = true;\n\t\t\t\t}\n\t\t\t\texpect(refused, \"a charge with no idempotency key was accepted; a retry would move money twice\");\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"payments.same-key-moves-money-once\",\n\t\t\ttitle: \"the same idempotency key resolves to the same provider reference\",\n\t\t\tasync run(port) {\n\t\t\t\tconst first = await port.charge(fixtures.request);\n\t\t\t\tconst second = await port.charge(fixtures.request);\n\t\t\t\texpect(\n\t\t\t\t\tfirst.outcome === second.outcome,\n\t\t\t\t\t`the same key produced \"${first.outcome}\" then \"${second.outcome}\"`,\n\t\t\t\t);\n\t\t\t\t// Without a reference there is nothing to compare, and a\n\t\t\t\t// double-charger would pass on outcome equality alone. A\n\t\t\t\t// succeeded charge must be identifiable or it cannot be reconciled.\n\t\t\t\texpect(\n\t\t\t\t\tfirst.outcome !== \"succeeded\" || first.providerReference !== undefined,\n\t\t\t\t\t\"a succeeded charge carried no provider reference, so a retry cannot be told from a second charge\",\n\t\t\t\t);\n\t\t\t\texpect(\n\t\t\t\t\tfirst.providerReference === second.providerReference,\n\t\t\t\t\t\"the same key produced two provider references, so a retry charged twice\",\n\t\t\t\t);\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"payments.outcome-is-declared\",\n\t\t\ttitle: \"an outcome is one of the three the platform can act on\",\n\t\t\tasync run(port) {\n\t\t\t\tconst result = await port.charge(fixtures.request);\n\t\t\t\texpect(\n\t\t\t\t\tresult.outcome === \"succeeded\" || result.outcome === \"failed\" || result.outcome === \"ambiguous\",\n\t\t\t\t\t`outcome \"${result.outcome}\" is not one the platform can reconcile`,\n\t\t\t\t);\n\t\t\t},\n\t\t},\n\t];\n}\n\n/** The suite a search adapter must pass. */\nexport function searchPortChecks(fixtures: {\n\tquery: SearchQuery;\n}): PortCheck<SearchPort>[] {\n\treturn [\n\t\t{\n\t\t\tid: \"search.fixture-returns-hits\",\n\t\t\ttitle: \"the fixture query matches something, so the checks below are not vacuous\",\n\t\t\tasync run(port) {\n\t\t\t\tconst result = await port.query(fixtures.query);\n\t\t\t\texpect(\n\t\t\t\t\tresult.hits.length > 0,\n\t\t\t\t\t\"the fixture query returned nothing, so every check below passes without exercising the adapter\",\n\t\t\t\t);\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"search.respects-limit\",\n\t\t\ttitle: \"a result set never exceeds the requested limit\",\n\t\t\tasync run(port) {\n\t\t\t\tconst result = await port.query({ ...fixtures.query, limit: 1 });\n\t\t\t\texpect(result.hits.length <= 1, `returned ${result.hits.length} hits for a limit of 1`);\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"search.returns-identifiers-not-records\",\n\t\t\ttitle: \"a hit carries an identifier a governed read can resolve, not the record\",\n\t\t\tasync run(port) {\n\t\t\t\tconst result = await port.query(fixtures.query);\n\t\t\t\tfor (const hit of result.hits) {\n\t\t\t\t\texpect(typeof hit.id === \"string\" && hit.id.length > 0, \"a hit carried no identifier\");\n\t\t\t\t\texpect(\n\t\t\t\t\t\tObject.keys(hit).every((key) => key === \"id\" || key === \"score\"),\n\t\t\t\t\t\t\"a hit carried record fields; search results are pointers, and reading one still goes through ProjectionHost\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t];\n}\n\n/** The suite a customer-record adapter must pass. */\nexport function customerRecordPortChecks(fixtures: {\n\tevent: CustomerEvent;\n}): PortCheck<CustomerRecordPort>[] {\n\treturn [\n\t\t{\n\t\t\t// This proves redelivery does not *fail*. Whether it duplicates is not\n\t\t\t// observable through this port, which has no read side by design, so\n\t\t\t// the suite says what it can and does not imply more.\n\t\t\tid: \"crm.redelivery-does-not-fail\",\n\t\t\ttitle: \"recording the same event twice is not an error\",\n\t\t\tasync run(port) {\n\t\t\t\tawait port.record(fixtures.event);\n\t\t\t\tawait port.record(fixtures.event);\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"crm.rejects-unidentified-event\",\n\t\t\ttitle: \"an event with no stable id is refused\",\n\t\t\tasync run(port) {\n\t\t\t\tlet refused = false;\n\t\t\t\ttry {\n\t\t\t\t\tawait port.record({ ...fixtures.event, eventId: \"\" });\n\t\t\t\t} catch {\n\t\t\t\t\trefused = true;\n\t\t\t\t}\n\t\t\t\texpect(refused, \"an event with no id was accepted; redelivery would duplicate the record\");\n\t\t\t},\n\t\t},\n\t];\n}\n\nexport function designTokensPortChecks(theme: string): PortCheck<DesignTokensPort>[] {\n\treturn [\n\t\t{\n\t\t\tid: \"tokens.theme-resolves\",\n\t\t\ttitle: \"a known theme resolves to at least one token\",\n\t\t\tasync run(port) {\n\t\t\t\tconst tokens = await port.resolve(theme);\n\t\t\t\texpect(Array.isArray(tokens) && tokens.length > 0, `theme \"${theme}\" resolved to no tokens`);\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"tokens.no-unresolved-aliases\",\n\t\t\ttitle: \"no resolved token still carries an alias\",\n\t\t\tasync run(port) {\n\t\t\t\tfor (const token of await port.resolve(theme)) {\n\t\t\t\t\texpect(\n\t\t\t\t\t\ttypeof token.value !== \"string\" || !ALIAS.test(token.value.trim()),\n\t\t\t\t\t\t`token \"${token.name}\" resolved to the unfollowed alias ${String(token.value)}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tid: \"tokens.names-are-unique\",\n\t\t\ttitle: \"token names are unique within a theme\",\n\t\t\tasync run(port) {\n\t\t\t\tconst names = (await port.resolve(theme)).map((token) => token.name);\n\t\t\t\texpect(new Set(names).size === names.length, \"the theme resolved duplicate token names\");\n\t\t\t},\n\t\t},\n\t];\n}\n\n/** Runs a contract suite and returns every failure, rather than stopping at the first. */\nexport async function runPortContract<TPort>(port: TPort, checks: readonly PortCheck<TPort>[]): Promise<{ passed: boolean; failures: Array<{ id: string; message: string }> }> {\n\tconst failures: Array<{ id: string; message: string }> = [];\n\tfor (const check of checks) {\n\t\ttry {\n\t\t\tawait check.run(port);\n\t\t} catch (error) {\n\t\t\tfailures.push({ id: check.id, message: error instanceof Error ? error.message : String(error) });\n\t\t}\n\t}\n\treturn { passed: failures.length === 0, failures };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA8DA,IAAM,QAAQ;AAEd,IAAM,UAAU,CAAC,UAChB,CAAC,CAAC,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,KAAK,YAAY;AAE9E,IAAM,UAAU,CAAC,UAChB,CAAC,CAAC,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,KAAK,EAAE,YAAY;AAOzE,SAAS,oBAAoB,UAAsC;AACzE,QAAM,OAAO,oBAAI,IAAiD;AAElE,QAAM,OAAO,CAAC,MAAiB,MAAgB,kBAAiC;AAC/E,UAAM,YAAY,OAAO,KAAK,UAAU,WAAW,KAAK,QAAQ;AAChE,eAAW,CAAC,KAAK,MAAM,KAAK,OAAO,QAAQ,IAAI,GAAG;AACjD,UAAI,IAAI,WAAW,GAAG,EAAG;AACzB,YAAM,OAAO,CAAC,GAAG,MAAM,GAAG;AAC1B,UAAI,QAAQ,MAAM,GAAG;AACpB,aAAK,IAAI,KAAK,KAAK,GAAG,GAAG,EAAE,OAAO,QAAQ,MAAM,OAAO,SAAS,UAAU,CAAC;AAAA,MAC5E,WAAW,QAAQ,MAAM,GAAG;AAC3B,aAAK,QAAQ,MAAM,SAAS;AAAA,MAC7B;AAAA,IACD;AAAA,EACD;AACA,OAAK,UAAU,CAAC,CAAC;AAEjB,QAAM,YAAY,oBAAI,IAAY;AAClC,QAAM,WAAW,oBAAI,IAAqB;AAE1C,QAAM,UAAU,CAAC,SAA0B;AAC1C,QAAI,SAAS,IAAI,IAAI,EAAG,QAAO,SAAS,IAAI,IAAI;AAChD,UAAM,QAAQ,KAAK,IAAI,IAAI;AAC3B,QAAI,CAAC,MAAO,OAAM,IAAI,MAAM,wBAAwB,IAAI,0CAA0C;AAClG,QAAI,UAAU,IAAI,IAAI,GAAG;AACxB,YAAM,IAAI,MAAM,6BAA6B,CAAC,GAAG,WAAW,IAAI,EAAE,KAAK,MAAM,CAAC,GAAG;AAAA,IAClF;AACA,UAAM,MAAM,MAAM,MAAM;AACxB,QAAI,OAAO,QAAQ,UAAU;AAC5B,eAAS,IAAI,MAAM,GAAG;AACtB,aAAO;AAAA,IACR;AACA,UAAM,QAAQ,MAAM,KAAK,IAAI,KAAK,CAAC;AACnC,QAAI,CAAC,OAAO;AACX,eAAS,IAAI,MAAM,GAAG;AACtB,aAAO;AAAA,IACR;AACA,cAAU,IAAI,IAAI;AAClB,UAAM,SAAS,QAAQ,MAAM,CAAC,CAAE;AAChC,cAAU,OAAO,IAAI;AACrB,aAAS,IAAI,MAAM,MAAM;AACzB,WAAO;AAAA,EACR;AAEA,SAAO,CAAC,GAAG,KAAK,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM;AACjD,UAAM,QAAQ,QAAQ,IAAI;AAC1B,WAAO;AAAA,MACN;AAAA,MACA;AAAA,MACA,GAAI,MAAM,SAAS,SAAY,CAAC,IAAI,EAAE,MAAM,MAAM,KAAK;AAAA,MACvD,GAAI,MAAM,MAAM,iBAAiB,SAAY,CAAC,IAAI,EAAE,aAAa,MAAM,MAAM,aAAa;AAAA,IAC3F;AAAA,EACD,CAAC;AACF;AAiBO,IAAM,uBAAqD;AAAA,EACjE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD;AAqDO,IAAM,kBAAN,cAA8B,MAAM;AAAA,EAE1C,YACU,WACT,SACC;AACD,UAAM,OAAO;AAHJ;AAAA,EAIV;AAAA,EAJU;AAAA,EAFQ,OAAO;AAO1B;AASO,SAAS,4BACf,QACA,OACA,MAAY,oBAAI,KAAK,GACd;AAGP,QAAM,cAAc,IAAI,QAAQ;AAChC,MAAI,OAAO,MAAM,WAAW,GAAG;AAC9B,UAAM,IAAI,gBAAgB,oBAAoB,qDAAqD;AAAA,EACpG;AAEA,MAAI,OAAO,OAAO,cAAc,YAAY,CAAC,qBAAqB,SAAS,OAAO,SAAS,GAAG;AAC7F,UAAM,IAAI,gBAAgB,sBAAsB,eAAe,OAAO,OAAO,SAAS,CAAC,8BAA8B;AAAA,EACtH;AACA,MAAI,OAAO,OAAO,YAAY,YAAY,OAAO,QAAQ,WAAW,GAAG;AACtE,UAAM,IAAI,gBAAgB,oBAAoB,gCAAgC;AAAA,EAC/E;AACA,MAAI,OAAO,OAAO,aAAa,YAAY,OAAO,SAAS,WAAW,GAAG;AACxE,UAAM,IAAI,gBAAgB,oBAAoB,+BAA+B;AAAA,EAC9E;AAKA,QAAM,WAAW,aAAa,OAAO,QAAQ;AAC7C,QAAM,YAAY,aAAa,OAAO,SAAS;AAC/C,MAAI,aAAa,UAAa,cAAc,QAAW;AACtD,UAAM,IAAI,gBAAgB,oBAAoB,wGAAwG;AAAA,EACvJ;AACA,MAAI,eAAe,WAAW;AAC7B,UAAM,IAAI,gBAAgB,WAAW,2BAA2B,OAAO,SAAS,GAAG;AAAA,EACpF;AACA,MAAI,cAAc,UAAU;AAC3B,UAAM,IAAI,gBAAgB,iBAAiB,oCAAoC,OAAO,QAAQ,GAAG;AAAA,EAClG;AAEA,MAAI,OAAO,aAAa,MAAM,UAAU;AACvC,UAAM,IAAI;AAAA,MACT;AAAA,MACA,8BAA8B,OAAO,QAAQ,8BAA8B,MAAM,QAAQ;AAAA,IAC1F;AAAA,EACD;AAIA,MAAI,OAAO,aAAa,cAAe;AACvC,MAAI,CAAC,MAAM,QAAQ,OAAO,QAAQ,KAAK,CAAC,OAAO,SAAS,MAAM,CAAC,UAAU,OAAO,UAAU,QAAQ,GAAG;AACpG,UAAM,IAAI,gBAAgB,oBAAoB,iFAAiF;AAAA,EAChI;AACA,MAAI,CAAC,OAAO,SAAS,SAAS,MAAM,OAAO,GAAG;AAC7C,UAAM,IAAI;AAAA,MACT;AAAA,MACA,oCAAoC,MAAM,OAAO;AAAA,IAClD;AAAA,EACD;AACD;AAGA,IAAM,UAAU;AAEhB,SAAS,aAAa,OAAmC;AACxD,MAAI,OAAO,UAAU,YAAY,CAAC,QAAQ,KAAK,KAAK,EAAG,QAAO;AAC9D,QAAM,SAAS,KAAK,MAAM,KAAK;AAC/B,SAAO,OAAO,MAAM,MAAM,IAAI,SAAY;AAC3C;AAQO,SAAS,uBACf,QACA,OACA,MAAY,oBAAI,KAAK,GACkE;AACvF,8BAA4B,QAAQ,OAAO,GAAG;AAC9C,SAAO;AAAA,IACN,SAAS,OAAO;AAAA,IAChB,WAAW,OAAO;AAAA,IAClB,UAAU,OAAO;AAAA,IACjB,SAAS,MAAM;AAAA,EAChB;AACD;AA2MA,IAAM,cAAc;AAEpB,SAAS,kBAAkB,QAAiC,SAA4B,OAAqB;AAC5G,SAAO,OAAO,UAAU,QAAQ,OAAO,OAAO,UAAU,UAAU,GAAG,KAAK,gCAAgC;AAC1G,QAAM,aAAa,KAAK,UAAU,OAAO,KAAK;AAC9C,aAAW,UAAU,SAAS;AAC7B,QAAI,OAAO,WAAW,EAAG;AACzB,WAAO,CAAC,WAAW,SAAS,MAAM,GAAG,GAAG,KAAK,sCAAsC;AAAA,EACpF;AACD;AAEA,SAAS,UAAU,MAA8B,OAAwC;AACxF,SAAO,KAAK,aAAa,MAAM,YAAY,KAAK,YAAY,MAAM,WAAW,KAAK,uBAAuB,MAAM;AAChH;AAQO,SAAS,4BAA4B,UAAyE;AACpH,QAAM,WAAW,CAAC,WAA+J;AAAA,IAChL,UAAU,MAAM,YAAY,SAAS;AAAA,IACrC,YAAY,MAAM,eAAe,SAAY,SAAS,kBAAkB,MAAM;AAAA,IAC9E,SAAS,SAAS,QAAQ,EAAE,WAAW,MAAM,WAAW,UAAU,MAAM,UAAU,GAAI,MAAM,eAAe,EAAE,cAAc,MAAM,aAAa,IAAI,CAAC,EAAG,CAAC;AAAA,IACvJ,YAAY;AAAA,EACb;AACA,SAAO;AAAA,IACN;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,SAAS,MAAM;AACrB,cAAM,SAAS,MAAM,KAAK,QAAQ,SAAS,EAAE,WAAW,SAAS,gBAAgB,UAAU,IAAI,CAAC,CAAC;AACjG,eAAO,OAAO,UAAU,oCAAoC,OAAO,WAAW,KAAK,OAAO,OAAO,EAAE;AACnG,YAAI,CAAC,OAAO,SAAU;AACtB,eAAO,UAAU,OAAO,OAAO,SAAS,aAAa,GAAG,yDAAyD;AACjH,eAAO,OAAO,sBAAsB,SAAS,gBAAgB,8CAA8C;AAC3G,eAAO,OAAO,aAAa,SAAS,UAAU,gDAAgD;AAC9F,eAAO,OAAO,YAAY,eAAe,OAAO,YAAY,UAAU,gCAAgC,OAAO,OAAO,GAAG;AACvH,0BAAkB,QAAQ,SAAS,SAAS,mBAAmB;AAAA,MAChE;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,SAAS,MAAM;AACrB,cAAM,SAAS,MAAM,KAAK,QAAQ,SAAS,EAAE,WAAW,SAAS,gBAAgB,UAAU,KAAK,YAAY,SAAS,kBAAkB,CAAC,CAAC;AACzI,eAAO,CAAC,OAAO,YAAY,OAAO,YAAY,sBAAsB,6DAA6D;AACjI,0BAAkB,QAAQ,SAAS,SAAS,oBAAoB;AAEhE,cAAM,QAAQ,MAAM,KAAK,QAAQ,SAAS,EAAE,WAAW,SAAS,gBAAgB,UAAU,IAAI,CAAC,CAAC;AAChG,eAAO,MAAM,aAAa,MAAM,YAAY,eAAe,MAAM,YAAY,WAAW,uCAAuC;AAAA,MAChI;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,SAAS,MAAM;AACrB,cAAM,SAAS,MAAM,KAAK,QAAQ,SAAS,EAAE,WAAW,SAAS,kBAAkB,UAAU,IAAI,CAAC,CAAC;AACnG,eAAO,CAAC,OAAO,YAAY,OAAO,YAAY,qBAAqB,2DAA2D;AAC9H,0BAAkB,QAAQ,SAAS,SAAS,mBAAmB;AAAA,MAChE;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,SAAS,MAAM;AAGrB,cAAM,SAAS,MAAM,KAAK,QAAQ,SAAS,EAAE,WAAW,SAAS,gBAAgB,UAAU,KAAK,cAAc,SAAS,aAAa,CAAC,CAAC;AACtI,YAAI,OAAO,UAAU;AACpB,iBAAO,UAAU,OAAO,OAAO,SAAS,aAAa,GAAG,0CAA0C;AAAA,QACnG,OAAO;AACN,iBAAO,OAAO,YAAY,oBAAoB,OAAO,YAAY,aAAa,mCAAmC,OAAO,OAAO,GAAG;AAAA,QACnI;AACA,0BAAkB,QAAQ,SAAS,SAAS,eAAe;AAAA,MAC5D;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,SAAS,MAAM;AACrB,cAAM,SAAS,MAAM,KAAK,QAAQ,SAAS,EAAE,WAAW,SAAS,gBAAgB,UAAU,KAAK,UAAU,SAAS,cAAc,CAAC,CAAC;AACnI,eAAO,CAAC,OAAO,UAAU,iDAAiD;AAC1E,eAAO,CAAC,OAAO,aAAa,OAAO,YAAY,uBAAuB,OAAO,YAAY,uBAAuB,mDAAmD;AACnK,0BAAkB,QAAQ,SAAS,SAAS,mBAAmB;AAAA,MAChE;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,SAAS,MAAM;AAGrB,cAAM,SAAS,MAAM,KAAK,QAAQ,SAAS,EAAE,WAAW,SAAS,kBAAkB,UAAU,KAAK,YAAY,SAAS,kBAAkB,CAAC,CAAC;AAC3I,eAAO,OAAO,UAAU,0FAA0F;AAClH,YAAI,OAAO,SAAU,QAAO,UAAU,OAAO,OAAO,SAAS,YAAY,GAAG,uDAAuD;AACnI,cAAM,SAAS,MAAM;AACrB,cAAM,SAAS,MAAM,KAAK,QAAQ,SAAS,EAAE,WAAW,SAAS,kBAAkB,UAAU,IAAI,CAAC,CAAC;AACnG,eAAO,CAAC,OAAO,UAAU,yCAAyC;AAClE,eAAO,CAAC,OAAO,aAAa,OAAO,YAAY,oBAAoB,OAAO,YAAY,uBAAuB,OAAO,YAAY,uBAAuB,sDAAsD;AAC7M,0BAAkB,QAAQ,SAAS,SAAS,wBAAwB;AAAA,MACrE;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,SAAS,MAAM;AACrB,cAAM,QAAQ,MAAM,KAAK,QAAQ,SAAS,EAAE,WAAW,SAAS,gBAAgB,UAAU,IAAI,CAAC,CAAC;AAChG,cAAM,SAAS,MAAM,KAAK,QAAQ,SAAS,EAAE,WAAW,SAAS,gBAAgB,UAAU,IAAI,CAAC,CAAC;AACjG,eAAO,MAAM,YAAY,OAAO,UAAU,6BAA6B;AACvE,YAAI,CAAC,MAAM,YAAY,CAAC,OAAO,SAAU;AACzC,eAAO,UAAU,MAAM,OAAO,OAAO,KAAK,GAAG,gDAAgD;AAC7F,eAAO,OAAO,YAAY,cAAc,OAAO,YAAY,MAAM,SAAS,sBAAsB,OAAO,OAAO,YAAY,MAAM,OAAO,GAAG;AAC1I,eAAQ,MAAM,SAAS,SAAS,YAAY,SAAS,cAAc,MAAO,GAAG,sDAAsD;AACnI,0BAAkB,QAAQ,SAAS,SAAS,QAAQ;AAAA,MACrD;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,SAAS,MAAM;AACrB,cAAM,QAAQ,MAAM,KAAK,QAAQ,SAAS,EAAE,WAAW,SAAS,gBAAgB,UAAU,IAAI,CAAC,CAAC;AAChG,cAAM,UAAU,MAAM,KAAK,QAAQ,SAAS,EAAE,WAAW,SAAS,gBAAgB,UAAU,IAAI,CAAC,CAAC;AAClG,eAAO,MAAM,UAAU,gCAAgC;AACvD,eAAO,QAAQ,UAAU,kEAAkE;AAC3F,YAAI,CAAC,QAAQ,SAAU;AACvB,eAAO,QAAQ,YAAY,2BAA2B,8BAA8B,QAAQ,OAAO,GAAG;AACtG,0BAAkB,SAAS,SAAS,SAAS,kBAAkB;AAAA,MAChE;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,SAAS,MAAM;AACrB,cAAM,UAAU,MAAM,QAAQ,IAAI;AAAA,UACjC,KAAK,QAAQ,SAAS,EAAE,WAAW,SAAS,gBAAgB,UAAU,KAAK,YAAY,SAAS,kBAAkB,CAAC,CAAC;AAAA,UACpH,KAAK,QAAQ,SAAS,EAAE,WAAW,SAAS,kBAAkB,UAAU,IAAI,CAAC,CAAC;AAAA,UAC9E,KAAK,QAAQ,SAAS,EAAE,WAAW,SAAS,gBAAgB,UAAU,KAAK,UAAU,SAAS,cAAc,CAAC,CAAC;AAAA,QAC/G,CAAC;AACD,mBAAW,UAAU,SAAS;AAC7B,iBAAO,CAAC,OAAO,UAAU,6BAA6B;AACtD,cAAI,OAAO,SAAU;AACrB,iBAAO,OAAO,KAAK,OAAO,KAAK,EAAE,SAAS,GAAG,0CAA0C;AAGvF,iBAAO,KAAK,UAAU,OAAO,KAAK,EAAE,SAAS,OAAO,OAAO,GAAG,4CAA4C;AAC1G,4BAAkB,QAAQ,SAAS,SAAS,WAAW,OAAO,OAAO,EAAE;AAAA,QACxE;AAAA,MACD;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,SAAS,MAAM;AACrB,cAAM,UAAU,MAAM,QAAQ,IAAI,MAAM,KAAK,EAAE,QAAQ,EAAE,GAAG,MAAM,KAAK,QAAQ,SAAS,EAAE,WAAW,SAAS,gBAAgB,UAAU,IAAI,CAAC,CAAC,CAAC,CAAC;AAChJ,cAAM,WAAW,QAAQ,OAAO,CAAC,WAAgD,OAAO,QAAQ;AAChG,eAAO,SAAS,WAAW,QAAQ,QAAQ,GAAG,QAAQ,SAAS,SAAS,MAAM,OAAO,QAAQ,MAAM,oCAAoC;AACvI,eAAO,SAAS,MAAM,CAAC,WAAW,UAAU,OAAO,OAAO,SAAS,aAAa,CAAC,GAAG,4DAA4D;AAChJ,cAAM,UAAU,SAAS,OAAO,CAAC,WAAW,OAAO,YAAY,eAAe,OAAO,YAAY,QAAQ;AACzG,eAAO,QAAQ,UAAU,GAAG,+CAA+C;AAC3E,eAAO,SAAS,MAAM,CAAC,WAAW,OAAO,YAAY,yBAAyB,GAAG,0EAA0E;AAC3J,eAAQ,MAAM,SAAS,SAAS,YAAY,SAAS,cAAc,MAAO,GAAG,sEAAsE;AAAA,MACpJ;AAAA,IACD;AAAA,EACD;AACD;AAsEA,IAAM,UAAU;AAMT,SAAS,WACf,YACmC;AACnC,MAAI,CAAC,QAAQ,KAAK,WAAW,EAAE,GAAG;AACjC,UAAM,IAAI,MAAM,YAAY,WAAW,EAAE,8DAA8D;AAAA,EACxG;AACA,MAAI,CAAC,kBAAkB,KAAK,WAAW,OAAO,GAAG;AAChD,UAAM,IAAI,MAAM,SAAS,WAAW,EAAE,qCAAqC;AAAA,EAC5E;AACA,MAAI,CAAC,WAAW,YAAY,KAAK,GAAG;AACnC,UAAM,IAAI,MAAM,SAAS,WAAW,EAAE,+DAA+D;AAAA,EACtG;AACA,MAAI,OAAO,WAAW,WAAW,YAAY;AAC5C,UAAM,IAAI,MAAM,SAAS,WAAW,EAAE,oCAAoC;AAAA,EAC3E;AACA,SAAO;AACR;AASA,eAAsB,wBACrB,YACA,UACA,gBACgB;AAChB,QAAM,SAAS,WAAW,OAAO,QAAQ;AACzC,MAAI,OAAO,WAAW,GAAG;AACxB,UAAM,IAAI,MAAM,SAAS,WAAW,EAAE,kEAAkE;AAAA,EACzG;AACA,QAAM,MAAM,oBAAI,IAAY;AAC5B,aAAW,SAAS,QAAQ;AAC3B,QAAI,IAAI,IAAI,MAAM,EAAE,EAAG,OAAM,IAAI,MAAM,SAAS,WAAW,EAAE,qBAAqB,MAAM,EAAE,UAAU;AACpG,QAAI,IAAI,MAAM,EAAE;AAAA,EACjB;AAOA,QAAM,WAAW,MAAM,QAAQ,cAAc,IAAI,iBAAiB,CAAC,cAAuB;AAC1F,MAAI,SAAS,WAAW,GAAG;AAC1B,UAAM,IAAI,MAAM,SAAS,WAAW,EAAE,4EAA4E;AAAA,EACnH;AAEA,QAAM,WAAW,IAAI,IAAI,OAAO,IAAI,CAAC,UAAU,MAAM,EAAE,CAAC;AACxD,aAAW,WAAW,UAAU;AAC/B,eAAW,SAAS,QAAQ;AAC3B,UAAI,CAAC,SAAS,IAAI,MAAM,EAAE,EAAG;AAC7B,UAAI;AACH,cAAM,MAAM,IAAI,OAAO;AAAA,MACxB,QAAQ;AACP,iBAAS,OAAO,MAAM,EAAE;AAAA,MACzB;AAAA,IACD;AAAA,EACD;AACA,MAAI,SAAS,OAAO,GAAG;AACtB,UAAM,IAAI;AAAA,MACT,SAAS,WAAW,EAAE,SAAS,SAAS,IAAI,2EAA2E,CAAC,GAAG,QAAQ,EAAE,KAAK,IAAI,CAAC;AAAA,IAChJ;AAAA,EACD;AACD;AAuBA,eAAsB,eAAiC,OAOzB;AAI7B,aAAW,MAAM,UAAU;AAC3B,QAAM,SAAS,MAAM,WAAW,OAAO,MAAM,QAAQ;AACrD,MAAI,OAAO,WAAW,GAAG;AACxB,UAAM,IAAI,MAAM,SAAS,MAAM,WAAW,EAAE,kEAAkE;AAAA,EAC/G;AACA,QAAM,SAAmB,CAAC;AAC1B,aAAW,SAAS,QAAQ;AAC3B,QAAI;AACH,YAAM,MAAM,IAAI,MAAM,OAAO;AAAA,IAC9B,SAAS,OAAO;AACf,YAAM,IAAI;AAAA,QACT,YAAY,MAAM,MAAM,kBAAkB,MAAM,WAAW,EAAE,YAAY,MAAM,EAAE,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,MAC9I;AAAA,IACD;AACA,WAAO,KAAK,MAAM,EAAE;AAAA,EACrB;AACA,SAAO;AAAA,IACN,MAAM,MAAM,WAAW;AAAA,IACvB,QAAQ,MAAM;AAAA,IACd,GAAI,MAAM,YAAY,SAAY,CAAC,IAAI,EAAE,SAAS,MAAM,QAAQ;AAAA,IAChE,GAAI,MAAM,WAAW,WAAW,EAAE,UAAU,MAAM,WAAW,SAAS,IAAI,CAAC;AAAA,IAC3E,eAAe;AAAA,MACd,QAAQ,MAAM,WAAW;AAAA,MACzB,aAAa,MAAM,WAAW;AAAA,MAC9B,QAAQ;AAAA,MACR,cAAc,MAAM,OAAO,oBAAI,KAAK,GAAG,YAAY;AAAA,IACpD;AAAA,EACD;AACD;AAUA,SAAS,eAAe,SAA4B,UAA+C;AAClG,QAAM,gBAAiB,QAA6B;AACpD,MAAI,CAAC,iBAAiB,OAAO,kBAAkB,SAAU,QAAO;AAChE,MAAI,cAAc,WAAW,SAAU,QAAO;AAC9C,MAAI,cAAc,WAAW,QAAQ,KAAM,QAAO;AAClD,MAAI,CAAC,kBAAkB,KAAK,cAAc,eAAe,EAAE,EAAG,QAAO;AACrE,MAAI,CAAC,MAAM,QAAQ,cAAc,MAAM,KAAK,cAAc,OAAO,WAAW,EAAG,QAAO;AACtF,MAAI,OAAO,MAAM,KAAK,MAAM,cAAc,eAAe,EAAE,CAAC,EAAG,QAAO;AACtE,SAAO;AACR;AAkDO,SAAS,yBAAyB,OAchB;AACxB,QAAM,cAAc,IAAI,KAAK,MAAM,eAAe,CAAC,GAAG,IAAI,CAAC,eAAe,CAAC,WAAW,IAAI,UAAU,CAAC,CAAC;AACtG,QAAM,WAA0B,CAAC;AACjC,aAAW,eAAe,MAAM,WAAW,cAAc,SAAS,CAAC,GAAG;AACrE,UAAM,aAAa,MAAM,SAAS,OAAO,CAAC,YAAY,QAAQ,SAAS,YAAY,IAAI;AACvF,QAAI,WAAW,WAAW,GAAG;AAC5B,eAAS,KAAK;AAAA,QACb,MAAM;AAAA,QACN,MAAM,YAAY;AAAA,QAClB,SAAS,eAAe,MAAM,WAAW,SAAS,oBAAoB,YAAY,IAAI;AAAA,MACvF,CAAC;AACD;AAAA,IACD;AAGA,QAAI,WAAW;AACf,QAAI,YAAY,UAAU;AACzB,iBAAW,SAAS,OAAO,CAAC,YAAY,QAAQ,UAAU,SAAS,YAAY,SAAU,IAAI;AAC7F,UAAI,SAAS,WAAW,GAAG;AAC1B,iBAAS,KAAK;AAAA,UACb,MAAM;AAAA,UACN,MAAM,YAAY;AAAA,UAClB,SAAS,SAAS,YAAY,IAAI,iBAAiB,YAAY,SAAS,IAAI,8BAA8B,WAAW,IAAI,CAAC,YAAY,GAAG,QAAQ,MAAM,IAAI,QAAQ,UAAU,QAAQ,aAAa,GAAG,EAAE,KAAK,IAAI,CAAC;AAAA,QAClN,CAAC;AACD;AAAA,MACD;AACA,UAAI,YAAY,SAAS,SAAS;AACjC,cAAM,YAAY,SAAS,OAAO,CAAC,YAAY,QAAQ,UAAU,YAAY,YAAY,SAAU,OAAO;AAC1G,YAAI,UAAU,WAAW,GAAG;AAC3B,mBAAS,KAAK;AAAA,YACb,MAAM;AAAA,YACN,MAAM,YAAY;AAAA,YAClB,SAAS,SAAS,YAAY,IAAI,iBAAiB,YAAY,SAAS,IAAI,cAAc,YAAY,SAAS,OAAO,gCAAgC,SAAS,IAAI,CAAC,YAAY,QAAQ,UAAU,WAAW,qBAAqB,EAAE,KAAK,IAAI,CAAC;AAAA,UAC/O,CAAC;AACD;AAAA,QACD;AACA,mBAAW;AAAA,MACZ;AAAA,IACD;AACA,QAAI,YAAY,SAAS;AACxB,YAAM,YAAY,SAAS,OAAO,CAAC,YAAY,QAAQ,YAAY,YAAY,OAAO;AACtF,UAAI,UAAU,WAAW,GAAG;AAC3B,iBAAS,KAAK;AAAA,UACb,MAAM;AAAA,UACN,MAAM,YAAY;AAAA,UAClB,SAAS,SAAS,YAAY,IAAI,uBAAuB,YAAY,OAAO,4BAA4B,SAAS,IAAI,CAAC,YAAY,GAAG,QAAQ,MAAM,IAAI,QAAQ,WAAW,aAAa,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA,QACtM,CAAC;AACD;AAAA,MACD;AACA,iBAAW;AAAA,IACZ;AAIA,UAAM,aAAa,YAAY,IAAI,YAAY,IAAI;AACnD,QAAI,MAAM,wBAAwB,YAAY;AAC7C,YAAM,YAAY,SAAS,OAAO,CAAC,YAAY,eAAe,SAAS,YAAY,IAAI,CAAC;AACxF,UAAI,UAAU,WAAW,GAAG;AAC3B,YAAI,MAAM,sBAAsB;AAC/B,mBAAS,KAAK;AAAA,YACb,MAAM;AAAA,YACN,MAAM,YAAY;AAAA,YAClB,SAAS,SAAS,YAAY,IAAI,4BAA4B,SAAS,IAAI,CAAC,YAAY,QAAQ,MAAM,EAAE,KAAK,IAAI,CAAC;AAAA,UACnH,CAAC;AAAA,QACF;AACA;AAAA,MACD;AACA,UAAI,cAAc,CAAC,UAAU,KAAK,CAAC,YAAY,QAAQ,cAAc,gBAAgB,WAAW,OAAO,GAAG;AACzG,iBAAS,KAAK;AAAA,UACb,MAAM;AAAA,UACN,MAAM,YAAY;AAAA,UAClB,SAAS,SAAS,YAAY,IAAI,4BAA4B,WAAW,OAAO,oCAAoC,UAAU,IAAI,CAAC,YAAY,GAAG,QAAQ,MAAM,IAAI,QAAQ,cAAc,WAAW,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA,QACpN,CAAC;AAAA,MACF;AAAA,IACD;AAAA,EACD;AACA,SAAO,EAAE,OAAO,SAAS,WAAW,GAAG,SAAS;AACjD;AAEO,SAAS,gCAAgC,OAKvC;AACR,QAAM,SAAS,yBAAyB,KAAK;AAC7C,MAAI,OAAO,MAAO;AAClB,QAAM,IAAI,MAAM;AAAA,IACf,0BAA0B,MAAM,WAAW,SAAS;AAAA,IACpD,GAAG,OAAO,SAAS,IAAI,CAAC,YAAY,OAAO,QAAQ,OAAO,EAAE;AAAA,EAC7D,EAAE,KAAK,IAAI,CAAC;AACb;AAWA,IAAM,sBAAN,cAAkC,MAAM;AAAA,EACrB,OAAO;AAC1B;AAEA,SAAS,OAAO,WAAoB,SAAoC;AACvE,MAAI,CAAC,UAAW,OAAM,IAAI,oBAAoB,OAAO;AACtD;AAMO,SAAS,kBAA0C;AACzD,QAAM,aAAa;AACnB,SAAO;AAAA,IACN;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,SAAS,MAAM,KAAK,eAAe,YAAY,IAAI;AACzD,eAAO,OAAO,UAAU,MAAM,4BAA4B,OAAO,OAAO,KAAK,CAAC,kCAAkC;AAChH;AAAA,UACC,OAAO,WAAW,aAAa,OAAO,WAAW;AAAA,UACjD,yCAAyC,OAAO,MAAM;AAAA,QACvD;AAAA,MACD;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,eAAO,QAAQ,MAAM,KAAK,eAAe,YAAY,KAAK,GAAG,UAAU,WAAW,yCAAyC;AAC3H,eAAO,QAAQ,MAAM,KAAK,cAAc,YAAY,UAAU,GAAG,UAAU,UAAU,uCAAuC;AAC5H,eAAO,QAAQ,MAAM,KAAK,cAAc,YAAY,EAAE,GAAG,UAAU,UAAU,uCAAuC;AAAA,MACrH;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,UAAU,EAAE,cAAc,0BAA0B;AAC1D,cAAM,QAAQ,MAAM,KAAK,cAAc,YAAY,YAAY,OAAO;AACtE,cAAM,SAAS,MAAM,KAAK,cAAc,YAAY,YAAY,OAAO;AACvE,eAAO,MAAM,UAAU,OAAO,OAAO,iCAAiC,MAAM,KAAK,WAAW,OAAO,KAAK,GAAG;AAAA,MAC5G;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,KAAK,eAAe,YAAY,KAAK;AAAA,MAC5C;AAAA,IACD;AAAA,EACD;AACD;AAUO,SAAS,mBAAmB,UAIL;AAC7B,QAAM,SAAoC;AAAA,IACzC;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,SAAS,MAAM,KAAK,OAAO,kBAAkB;AACnD,eAAO,WAAW,MAAM,+DAA+D;AAAA,MACxF;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,eAAQ,MAAM,KAAK,OAAO,EAAE,MAAO,MAAM,wCAAwC;AAAA,MAClF;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,SAAS,MAAM,KAAK,OAAO,SAAS,eAAe;AACzD,eAAO,WAAW,MAAM,qCAAqC;AAC7D,eAAO,QAAQ,YAAY,SAAS,SAAS,SAAS,gBAAgB,QAAQ,OAAO,GAAG;AACxF,eAAO,QAAQ,aAAa,SAAS,SAAS,UAAU,iBAAiB,QAAQ,QAAQ,GAAG;AAAA,MAC7F;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,SAAS,MAAM,KAAK,OAAO,SAAS,eAAe;AACzD,eAAO,WAAW,MAAM,qCAAqC;AAC7D,YAAI,CAAC,OAAQ;AACb,eAAO,qBAAqB,SAAS,OAAO,SAAS,GAAG,cAAc,OAAO,SAAS,6BAA6B;AACnH,eAAO,OAAO,OAAO,WAAW,YAAY,OAAO,OAAO,SAAS,GAAG,wBAAwB;AAI9F,eAAO,QAAQ,KAAK,OAAO,QAAQ,GAAG,aAAa,OAAO,QAAQ,2CAA2C;AAC7G,eAAO,QAAQ,KAAK,OAAO,SAAS,GAAG,cAAc,OAAO,SAAS,2CAA2C;AAChH,eAAO,OAAO,OAAO,aAAa,YAAY,OAAO,SAAS,SAAS,GAAG,wBAAwB;AAClG;AAAA,UACC,OAAO,aAAa,iBAAiB,MAAM,QAAQ,OAAO,QAAQ;AAAA,UAClE;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,SAAS,MAAM,KAAK,OAAO,SAAS,eAAe;AACzD,eAAO,WAAW,MAAM,mEAAmE;AAC3F,YAAI,CAAC,OAAQ;AACb,cAAM,aAAa,KAAK,UAAU,MAAM;AACxC;AAAA,UACC,CAAC,WAAW,SAAS,SAAS,eAAe;AAAA,UAC7C;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,QAAQ,MAAM,KAAK,OAAO,SAAS,eAAe;AACxD,cAAM,SAAS,MAAM,KAAK,OAAO,SAAS,eAAe;AACzD,eAAO,OAAO,YAAY,QAAQ,SAAS,wDAAwD;AAAA,MACpG;AAAA,IACD;AAAA,EACD;AAEA,MAAI,SAAS,sBAAsB,QAAW;AAC7C,WAAO,KAAK;AAAA,MACX,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,oBAAoB,SAAS;AACnC,eAAQ,MAAM,KAAK,OAAO,iBAAiB,MAAO,MAAM,gDAAgD;AAAA,MACzG;AAAA,IACD,CAAC;AAAA,EACF;AAEA,SAAO;AACR;AAGO,SAAS,kBAAkB,UAGL;AAC5B,SAAO;AAAA,IACN;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,SAAS,MAAM,KAAK,QAAQ,EAAE,GAAG,SAAS,SAAS,KAAK,SAAS,UAAU,CAAC;AAClF,eAAO,WAAW,MAAM,uDAAuD;AAAA,MAChF;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,QAAQ,MAAM,KAAK,QAAQ,SAAS,OAAO;AACjD,cAAM,SAAS,MAAM,KAAK,QAAQ,SAAS,OAAO;AAClD,eAAO,UAAU,QAAQ,WAAW,MAAM,iCAAiC;AAC3E,eAAO,OAAO,aAAa,QAAQ,UAAU,iEAAiE;AAAA,MAC/G;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,SAAS,MAAM,KAAK,QAAQ,SAAS,OAAO;AAClD;AAAA,UACC,CAAC,KAAK,UAAU,UAAU,CAAC,CAAC,EAAE,SAAS,eAAe;AAAA,UACtD;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,EACD;AACD;AAGO,SAAS,mBAAmB,UAEL;AAC7B,SAAO;AAAA,IACN;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,YAAI,UAAU;AACd,YAAI;AACH,gBAAM,KAAK,OAAO,EAAE,GAAG,SAAS,SAAS,QAAQ,EAAE,GAAG,SAAS,QAAQ,QAAQ,QAAQ,KAAK,EAAE,CAAC;AAAA,QAChG,QAAQ;AACP,oBAAU;AAAA,QACX;AACA,eAAO,SAAS,+EAA+E;AAI/F,cAAM,UAAU,MAAM,KAAK,OAAO;AAAA,UACjC,GAAG,SAAS;AAAA,UACZ,gBAAgB,GAAG,SAAS,QAAQ,cAAc;AAAA,QACnD,CAAC;AACD;AAAA,UACC,QAAQ,YAAY;AAAA,UACpB,gCAAgC,QAAQ,OAAO;AAAA,QAChD;AAAA,MACD;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,YAAI,UAAU;AACd,YAAI;AACH,gBAAM,KAAK,OAAO,EAAE,GAAG,SAAS,SAAS,gBAAgB,GAAG,CAAC;AAAA,QAC9D,QAAQ;AACP,oBAAU;AAAA,QACX;AACA,eAAO,SAAS,+EAA+E;AAAA,MAChG;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,QAAQ,MAAM,KAAK,OAAO,SAAS,OAAO;AAChD,cAAM,SAAS,MAAM,KAAK,OAAO,SAAS,OAAO;AACjD;AAAA,UACC,MAAM,YAAY,OAAO;AAAA,UACzB,0BAA0B,MAAM,OAAO,WAAW,OAAO,OAAO;AAAA,QACjE;AAIA;AAAA,UACC,MAAM,YAAY,eAAe,MAAM,sBAAsB;AAAA,UAC7D;AAAA,QACD;AACA;AAAA,UACC,MAAM,sBAAsB,OAAO;AAAA,UACnC;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,SAAS,MAAM,KAAK,OAAO,SAAS,OAAO;AACjD;AAAA,UACC,OAAO,YAAY,eAAe,OAAO,YAAY,YAAY,OAAO,YAAY;AAAA,UACpF,YAAY,OAAO,OAAO;AAAA,QAC3B;AAAA,MACD;AAAA,IACD;AAAA,EACD;AACD;AAGO,SAAS,iBAAiB,UAEL;AAC3B,SAAO;AAAA,IACN;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,SAAS,MAAM,KAAK,MAAM,SAAS,KAAK;AAC9C;AAAA,UACC,OAAO,KAAK,SAAS;AAAA,UACrB;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,SAAS,MAAM,KAAK,MAAM,EAAE,GAAG,SAAS,OAAO,OAAO,EAAE,CAAC;AAC/D,eAAO,OAAO,KAAK,UAAU,GAAG,YAAY,OAAO,KAAK,MAAM,wBAAwB;AAAA,MACvF;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,SAAS,MAAM,KAAK,MAAM,SAAS,KAAK;AAC9C,mBAAW,OAAO,OAAO,MAAM;AAC9B,iBAAO,OAAO,IAAI,OAAO,YAAY,IAAI,GAAG,SAAS,GAAG,6BAA6B;AACrF;AAAA,YACC,OAAO,KAAK,GAAG,EAAE,MAAM,CAAC,QAAQ,QAAQ,QAAQ,QAAQ,OAAO;AAAA,YAC/D;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,EACD;AACD;AAGO,SAAS,yBAAyB,UAEL;AACnC,SAAO;AAAA,IACN;AAAA;AAAA;AAAA;AAAA,MAIC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,KAAK,OAAO,SAAS,KAAK;AAChC,cAAM,KAAK,OAAO,SAAS,KAAK;AAAA,MACjC;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,YAAI,UAAU;AACd,YAAI;AACH,gBAAM,KAAK,OAAO,EAAE,GAAG,SAAS,OAAO,SAAS,GAAG,CAAC;AAAA,QACrD,QAAQ;AACP,oBAAU;AAAA,QACX;AACA,eAAO,SAAS,yEAAyE;AAAA,MAC1F;AAAA,IACD;AAAA,EACD;AACD;AAEO,SAAS,uBAAuB,OAA8C;AACpF,SAAO;AAAA,IACN;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,SAAS,MAAM,KAAK,QAAQ,KAAK;AACvC,eAAO,MAAM,QAAQ,MAAM,KAAK,OAAO,SAAS,GAAG,UAAU,KAAK,yBAAyB;AAAA,MAC5F;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,mBAAW,SAAS,MAAM,KAAK,QAAQ,KAAK,GAAG;AAC9C;AAAA,YACC,OAAO,MAAM,UAAU,YAAY,CAAC,MAAM,KAAK,MAAM,MAAM,KAAK,CAAC;AAAA,YACjE,UAAU,MAAM,IAAI,sCAAsC,OAAO,MAAM,KAAK,CAAC;AAAA,UAC9E;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,IACA;AAAA,MACC,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM,IAAI,MAAM;AACf,cAAM,SAAS,MAAM,KAAK,QAAQ,KAAK,GAAG,IAAI,CAAC,UAAU,MAAM,IAAI;AACnE,eAAO,IAAI,IAAI,KAAK,EAAE,SAAS,MAAM,QAAQ,0CAA0C;AAAA,MACxF;AAAA,IACD;AAAA,EACD;AACD;AAGA,eAAsB,gBAAuB,MAAa,QAAqH;AAC9K,QAAM,WAAmD,CAAC;AAC1D,aAAW,SAAS,QAAQ;AAC3B,QAAI;AACH,YAAM,MAAM,IAAI,IAAI;AAAA,IACrB,SAAS,OAAO;AACf,eAAS,KAAK,EAAE,IAAI,MAAM,IAAI,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE,CAAC;AAAA,IAChG;AAAA,EACD;AACA,SAAO,EAAE,QAAQ,SAAS,WAAW,GAAG,SAAS;AAClD;","names":[]}
|