@cotal-ai/manager 0.16.0 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/attach-endpoint.d.ts +53 -59
- package/dist/attach-endpoint.d.ts.map +1 -1
- package/dist/attach-endpoint.js +120 -244
- package/dist/attach-endpoint.js.map +1 -1
- package/dist/commands.js +88 -8
- package/dist/commands.js.map +1 -1
- package/dist/console/app.js +68 -30
- package/dist/console/index.html +3 -2
- package/dist/console/session-bundle.js +9736 -0
- package/dist/console-crypto-shim.d.ts +16 -0
- package/dist/console-crypto-shim.d.ts.map +1 -0
- package/dist/console-crypto-shim.js +20 -0
- package/dist/console-crypto-shim.js.map +1 -0
- package/dist/console-session-entry.d.ts +2 -0
- package/dist/console-session-entry.d.ts.map +1 -0
- package/dist/console-session-entry.js +26 -0
- package/dist/console-session-entry.js.map +1 -0
- package/dist/endpoint-evict.d.ts +29 -0
- package/dist/endpoint-evict.d.ts.map +1 -0
- package/dist/endpoint-evict.js +80 -0
- package/dist/endpoint-evict.js.map +1 -0
- package/dist/holder-liveness.d.ts +40 -0
- package/dist/holder-liveness.d.ts.map +1 -0
- package/dist/holder-liveness.js +98 -0
- package/dist/holder-liveness.js.map +1 -0
- package/dist/manager-service-contract.d.ts +132 -0
- package/dist/manager-service-contract.d.ts.map +1 -0
- package/dist/manager-service-contract.js +332 -0
- package/dist/manager-service-contract.js.map +1 -0
- package/dist/manager.d.ts +519 -22
- package/dist/manager.d.ts.map +1 -1
- package/dist/manager.js +2273 -262
- package/dist/manager.js.map +1 -1
- package/dist/reconcile-gate.d.ts +82 -0
- package/dist/reconcile-gate.d.ts.map +1 -0
- package/dist/reconcile-gate.js +118 -0
- package/dist/reconcile-gate.js.map +1 -0
- package/dist/runtime/pty.d.ts.map +1 -1
- package/dist/runtime/pty.js +15 -2
- package/dist/runtime/pty.js.map +1 -1
- package/dist/session/bridge.d.ts +63 -0
- package/dist/session/bridge.d.ts.map +1 -0
- package/dist/session/bridge.js +157 -0
- package/dist/session/bridge.js.map +1 -0
- package/dist/session/establish.d.ts +212 -0
- package/dist/session/establish.d.ts.map +1 -0
- package/dist/session/establish.js +174 -0
- package/dist/session/establish.js.map +1 -0
- package/dist/session/index.d.ts +12 -0
- package/dist/session/index.d.ts.map +1 -0
- package/dist/session/index.js +15 -0
- package/dist/session/index.js.map +1 -0
- package/dist/session/plane.d.ts +120 -0
- package/dist/session/plane.d.ts.map +1 -0
- package/dist/session/plane.js +327 -0
- package/dist/session/plane.js.map +1 -0
- package/dist/static-lifecycle.d.ts +97 -0
- package/dist/static-lifecycle.d.ts.map +1 -0
- package/dist/static-lifecycle.js +262 -0
- package/dist/static-lifecycle.js.map +1 -0
- package/package.json +10 -6
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A build-time `node:crypto` shim for the console session bundle (P2 item 6). The core §13.6 rail
|
|
3
|
+
* (endpoint-session-rail) + terminal-frame codec (session-terminal-frames) transitively import
|
|
4
|
+
* `node:crypto` at MODULE level — via endpoint-envelope → canonical.js (`createHash`) and
|
|
5
|
+
* endpoint-subjects → subjects.js (`randomBytes`) — but they NEVER invoke hashing or uid-minting at
|
|
6
|
+
* runtime (the rail moves bytes + derives subjects; the grant mint/verify that hashes stays on the
|
|
7
|
+
* node side). esbuild aliases `node:crypto` to this so the module-level imports RESOLVE for the
|
|
8
|
+
* browser.
|
|
9
|
+
*
|
|
10
|
+
* Both entries THROW LOUD if ever called: a reached call means the browser bundle started
|
|
11
|
+
* hashing / uid-minting, which is a bug (the wrong code got pulled in), never a silent degrade — so
|
|
12
|
+
* this is a fail-loud boundary, not a fallback.
|
|
13
|
+
*/
|
|
14
|
+
export declare function randomBytes(): never;
|
|
15
|
+
export declare function createHash(): never;
|
|
16
|
+
//# sourceMappingURL=console-crypto-shim.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"console-crypto-shim.d.ts","sourceRoot":"","sources":["../src/console-crypto-shim.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,IAAI,KAAK,CAEnC;AAED,wBAAgB,UAAU,IAAI,KAAK,CAElC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A build-time `node:crypto` shim for the console session bundle (P2 item 6). The core §13.6 rail
|
|
3
|
+
* (endpoint-session-rail) + terminal-frame codec (session-terminal-frames) transitively import
|
|
4
|
+
* `node:crypto` at MODULE level — via endpoint-envelope → canonical.js (`createHash`) and
|
|
5
|
+
* endpoint-subjects → subjects.js (`randomBytes`) — but they NEVER invoke hashing or uid-minting at
|
|
6
|
+
* runtime (the rail moves bytes + derives subjects; the grant mint/verify that hashes stays on the
|
|
7
|
+
* node side). esbuild aliases `node:crypto` to this so the module-level imports RESOLVE for the
|
|
8
|
+
* browser.
|
|
9
|
+
*
|
|
10
|
+
* Both entries THROW LOUD if ever called: a reached call means the browser bundle started
|
|
11
|
+
* hashing / uid-minting, which is a bug (the wrong code got pulled in), never a silent degrade — so
|
|
12
|
+
* this is a fail-loud boundary, not a fallback.
|
|
13
|
+
*/
|
|
14
|
+
export function randomBytes() {
|
|
15
|
+
throw new Error("node:crypto.randomBytes is not available in the console session bundle (the §13.6 rail/codec never mint uids in-browser; a reached call is a bug)");
|
|
16
|
+
}
|
|
17
|
+
export function createHash() {
|
|
18
|
+
throw new Error("node:crypto.createHash is not available in the console session bundle (the §13.6 rail/codec never hash in-browser; a reached call is a bug)");
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=console-crypto-shim.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"console-crypto-shim.js","sourceRoot":"","sources":["../src/console-crypto-shim.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,WAAW;IACzB,MAAM,IAAI,KAAK,CAAC,mJAAmJ,CAAC,CAAC;AACvK,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,MAAM,IAAI,KAAK,CAAC,6IAA6I,CAAC,CAAC;AACjK,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"console-session-entry.d.ts","sourceRoot":"","sources":["../src/console-session-entry.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The manager console's browser session-client bundle ENTRY (P2 item 6). esbuild bundles this (and
|
|
3
|
+
* ONLY this: the browser-safe core subpath + nats-core's ws connect) into
|
|
4
|
+
* `dist/console/session-bundle.js`, served as a static asset. It runs IN THE BROWSER — the manager's
|
|
5
|
+
* node side never imports it (nats-core's ws path is baked into the bundle at build time; node rides
|
|
6
|
+
* `@nats-io/transport-node`).
|
|
7
|
+
*
|
|
8
|
+
* It exposes the core §13.6 rail + terminal-frame codec + `wsconnect` on one global so the console
|
|
9
|
+
* page can open a mesh session CALLER without a module loader: connect over the broker's websocket
|
|
10
|
+
* listener with the per-session, rails-only credential the loopback face hands it, open the caller
|
|
11
|
+
* rail with the redeemed grant, and drive xterm — the SAME core rail code the manager serves.
|
|
12
|
+
*/
|
|
13
|
+
import { wsconnect, credsAuthenticator } from "@nats-io/nats-core";
|
|
14
|
+
import { openSessionRail, encodeTerminalData, terminalFrameBytes, decodeTerminalFrame, } from "@cotal-ai/core/session-browser";
|
|
15
|
+
// A single browser global (no module system in the served console page). `credsAuthenticator` lets
|
|
16
|
+
// the page present the per-session, rails-only caller credential the loopback face minted (static
|
|
17
|
+
// mesh); an open mesh hands empty creds and the page connects bare.
|
|
18
|
+
globalThis.CotalSession = {
|
|
19
|
+
wsconnect,
|
|
20
|
+
credsAuthenticator,
|
|
21
|
+
openSessionRail,
|
|
22
|
+
encodeTerminalData,
|
|
23
|
+
terminalFrameBytes,
|
|
24
|
+
decodeTerminalFrame,
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=console-session-entry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"console-session-entry.js","sourceRoot":"","sources":["../src/console-session-entry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,gCAAgC,CAAC;AAExC,mGAAmG;AACnG,kGAAkG;AAClG,oEAAoE;AACnE,UAAmD,CAAC,YAAY,GAAG;IAClE,SAAS;IACT,kBAAkB;IAClB,eAAe;IACf,kBAAkB;IAClB,kBAAkB;IAClB,mBAAmB;CACpB,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The manager's VERIFIED-EVICTION seam for its own endpoint-registration barrier (SPEC 13.1, P2
|
|
3
|
+
* item 3, slice 3a). A restart re-registers the SAME logical instanceId with an ADVANCED epoch, and
|
|
4
|
+
* §13.1 requires the SUPERSEDED serve family to die BEFORE the new authority is visible — so the
|
|
5
|
+
* registration barrier's PHASE 2 must VERIFY-EVICT the predecessor's serve principal. The `$SYS`
|
|
6
|
+
* scan → KICK → verify capability lives with the DELIVERY DAEMON (co-located with the broker), never
|
|
7
|
+
* in this process (the manager holds the DATA signing seed; the D5 rail-split keeps `$SYS` material
|
|
8
|
+
* out of any seed-holder). This reaches the daemon over the privileged `ctl.delivery-admin` rail
|
|
9
|
+
* with a per-call SCOPED `endpoint-evictor` credential (pub the delivery-admin subject + reply +
|
|
10
|
+
* `$JS.API.INFO`, nothing else — narrower than the `supervisor` profile auth's barrier-evict reuses).
|
|
11
|
+
*
|
|
12
|
+
* NO-ORACLE = LOUD (no-fallbacks): if the daemon is unreachable the evictor THROWS an error NAMING
|
|
13
|
+
* THE CURE, so the barrier's PHASE-2 failure carries it and the gate stays frozen for reconciliation
|
|
14
|
+
* — a crash-restart on an auth mesh NEVER skips eviction. A reachable daemon that reports the
|
|
15
|
+
* principal still connected (or a garbled/contradictory result) returns `false` (not verified),
|
|
16
|
+
* which the barrier also treats as fail-closed. Verified-gone is conclusive only as (scan complete,
|
|
17
|
+
* none remain).
|
|
18
|
+
*/
|
|
19
|
+
import { type SpaceAuth } from "@cotal-ai/core";
|
|
20
|
+
/** Build the registration barrier's `evict(holderPrincipal) → verifiedGone` over the delivery
|
|
21
|
+
* daemon's `ctl.delivery-admin` rail. Per-call connection (eviction is a rare, heavyweight barrier
|
|
22
|
+
* step; a standing privileged connection would be a wider surface holding nothing). */
|
|
23
|
+
export declare function makeManagerEndpointEvictor(opts: {
|
|
24
|
+
space: string;
|
|
25
|
+
servers: string;
|
|
26
|
+
auth: SpaceAuth;
|
|
27
|
+
log: (line: string) => void;
|
|
28
|
+
}): (holderPrincipal: string) => Promise<boolean>;
|
|
29
|
+
//# sourceMappingURL=endpoint-evict.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"endpoint-evict.d.ts","sourceRoot":"","sources":["../src/endpoint-evict.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAA8D,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE5G;;wFAEwF;AACxF,wBAAgB,0BAA0B,CAAC,IAAI,EAAE;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,SAAS,CAAC;IAChB,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B,GAAG,CAAC,eAAe,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CA0DhD"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The manager's VERIFIED-EVICTION seam for its own endpoint-registration barrier (SPEC 13.1, P2
|
|
3
|
+
* item 3, slice 3a). A restart re-registers the SAME logical instanceId with an ADVANCED epoch, and
|
|
4
|
+
* §13.1 requires the SUPERSEDED serve family to die BEFORE the new authority is visible — so the
|
|
5
|
+
* registration barrier's PHASE 2 must VERIFY-EVICT the predecessor's serve principal. The `$SYS`
|
|
6
|
+
* scan → KICK → verify capability lives with the DELIVERY DAEMON (co-located with the broker), never
|
|
7
|
+
* in this process (the manager holds the DATA signing seed; the D5 rail-split keeps `$SYS` material
|
|
8
|
+
* out of any seed-holder). This reaches the daemon over the privileged `ctl.delivery-admin` rail
|
|
9
|
+
* with a per-call SCOPED `endpoint-evictor` credential (pub the delivery-admin subject + reply +
|
|
10
|
+
* `$JS.API.INFO`, nothing else — narrower than the `supervisor` profile auth's barrier-evict reuses).
|
|
11
|
+
*
|
|
12
|
+
* NO-ORACLE = LOUD (no-fallbacks): if the daemon is unreachable the evictor THROWS an error NAMING
|
|
13
|
+
* THE CURE, so the barrier's PHASE-2 failure carries it and the gate stays frozen for reconciliation
|
|
14
|
+
* — a crash-restart on an auth mesh NEVER skips eviction. A reachable daemon that reports the
|
|
15
|
+
* principal still connected (or a garbled/contradictory result) returns `false` (not verified),
|
|
16
|
+
* which the barrier also treats as fail-closed. Verified-gone is conclusive only as (scan complete,
|
|
17
|
+
* none remain).
|
|
18
|
+
*/
|
|
19
|
+
import { CotalEndpoint, mintCreds, newIdentity } from "@cotal-ai/core";
|
|
20
|
+
/** Build the registration barrier's `evict(holderPrincipal) → verifiedGone` over the delivery
|
|
21
|
+
* daemon's `ctl.delivery-admin` rail. Per-call connection (eviction is a rare, heavyweight barrier
|
|
22
|
+
* step; a standing privileged connection would be a wider surface holding nothing). */
|
|
23
|
+
export function makeManagerEndpointEvictor(opts) {
|
|
24
|
+
return async (principal) => {
|
|
25
|
+
const id = newIdentity();
|
|
26
|
+
let ep;
|
|
27
|
+
try {
|
|
28
|
+
// A per-eviction SCOPED cred for ONE ~15s delivery-admin call (60s TTL bounds a copied cred to
|
|
29
|
+
// a minute). endpoint-evictor holds EXACTLY its own delivery-admin request+reply rail — no
|
|
30
|
+
// lease, presence, store, consumer, KV, or executing right.
|
|
31
|
+
const creds = await mintCreds(opts.auth, id, "endpoint-evictor", { expiresInSeconds: 60 });
|
|
32
|
+
ep = new CotalEndpoint({
|
|
33
|
+
space: opts.space,
|
|
34
|
+
servers: opts.servers,
|
|
35
|
+
creds,
|
|
36
|
+
card: { id: id.id, name: "manager-endpoint-evict", kind: "endpoint" },
|
|
37
|
+
channels: [],
|
|
38
|
+
consume: false,
|
|
39
|
+
watchChannels: false,
|
|
40
|
+
watchPresence: false,
|
|
41
|
+
registerPresence: false,
|
|
42
|
+
});
|
|
43
|
+
ep.on("error", () => { });
|
|
44
|
+
await ep.start();
|
|
45
|
+
const r = await ep.requestDeliveryAdmin("evictPrincipal", { principal }, 15_000);
|
|
46
|
+
if (!r.ok) {
|
|
47
|
+
// The daemon is REACHABLE but refused (e.g. the principal is still connected — a genuine live
|
|
48
|
+
// predecessor). Not verified gone → fail-closed (the barrier leaves the gate frozen).
|
|
49
|
+
opts.log(`manager-endpoint-evict: ${principal}: the delivery daemon refused the eviction: ${r.error ?? "(no error copy)"}`);
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
const d = r.data;
|
|
53
|
+
if (d === undefined || d === null || d.principal !== principal ||
|
|
54
|
+
typeof d.kicked !== "number" || !Number.isSafeInteger(d.kicked) || d.kicked < 0 ||
|
|
55
|
+
typeof d.remaining !== "number" || !Number.isSafeInteger(d.remaining) || d.remaining < 0 ||
|
|
56
|
+
typeof d.verifiedGone !== "boolean" || typeof d.scanComplete !== "boolean") {
|
|
57
|
+
opts.log(`manager-endpoint-evict: ${principal}: garbled or foreign eviction result (${JSON.stringify(r.data ?? null)}); a result that does not verifiably describe this principal never authorizes`);
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
// An internally CONTRADICTORY success never authorizes (verified-gone is (scan complete, none remain)).
|
|
61
|
+
if (d.verifiedGone === true && (d.scanComplete !== true || d.remaining !== 0)) {
|
|
62
|
+
opts.log(`manager-endpoint-evict: ${principal}: verifiedGone with scanComplete=${String(d.scanComplete)} remaining=${d.remaining}; a contradictory result never authorizes`);
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
return d.verifiedGone === true;
|
|
66
|
+
}
|
|
67
|
+
catch (e) {
|
|
68
|
+
// NO-ORACLE = LOUD (pin 3, SPEC 13.1, no-fallbacks): the delivery-admin rail is unreachable, so
|
|
69
|
+
// eviction is UNKNOWN. THROW naming the cure so the barrier's PHASE-2 error carries it and the
|
|
70
|
+
// gate stays frozen — never a silent skip that could resurrect old-epoch authority.
|
|
71
|
+
throw new Error(`the delivery daemon is not reachable on the ctl.delivery-admin rail (${e instanceof Error ? e.message : String(e)}); ` +
|
|
72
|
+
`a restart on an auth mesh cannot verify-evict the superseded serve family principal "${principal}" without the liveness oracle. ` +
|
|
73
|
+
`Start the delivery daemon (\`cotal up\` runs it) and retry — eviction is never skipped (SPEC 13.1)`);
|
|
74
|
+
}
|
|
75
|
+
finally {
|
|
76
|
+
await ep?.stop().catch(() => { });
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=endpoint-evict.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"endpoint-evict.js","sourceRoot":"","sources":["../src/endpoint-evict.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The gate reconciler's AFFIRMATIVE freeze-holder check (Cotal #391), over the delivery daemon's
|
|
3
|
+
* `ctl.delivery-admin` rail — the READ twin of {@link makeManagerEndpointEvictor}, and deliberately
|
|
4
|
+
* shaped like it so the two guards of the same repair read the same way.
|
|
5
|
+
*
|
|
6
|
+
* The `$SYS` CONNZ capability lives with the DELIVERY DAEMON (co-located with the broker), never in
|
|
7
|
+
* a seed-holding process — the same D5 rail-split the evictor obeys. This reaches it with a
|
|
8
|
+
* per-call SCOPED `endpoint-evictor` credential: pub the delivery-admin subject + reply +
|
|
9
|
+
* `$JS.API.INFO`, nothing else. That credential names eviction because it is the rail's existing
|
|
10
|
+
* scope; the VERB it calls here is read-only, and the daemon-side executor opens only the CONNZ
|
|
11
|
+
* observer cred — the kick-capable evictor cred is never read on that path.
|
|
12
|
+
*
|
|
13
|
+
* EVERY FAILURE IS A REFUSAL, NEVER A PASS. Unlike the evictor — whose no-oracle case throws so the
|
|
14
|
+
* barrier fails closed — this returns a STRUCTURED verdict, because the reconciler must tell the
|
|
15
|
+
* operator WHICH condition refused. The mapping is total and there is no branch that infers death:
|
|
16
|
+
* - a reachable daemon's `live` / `gone` / `unknown` verdict passes through as-is;
|
|
17
|
+
* - a daemon refusal, an unreachable rail, or a REQUEST TIMEOUT is `unestablishable` — a timeout
|
|
18
|
+
* is the canonical "absence of evidence", and reading it as death is the exact defect this
|
|
19
|
+
* command exists to avoid;
|
|
20
|
+
* - a garbled reply, or one that does not ECHO the principal asked about, is `unestablishable` —
|
|
21
|
+
* a result that does not verifiably describe THIS principal never authorizes.
|
|
22
|
+
*/
|
|
23
|
+
import { type SpaceAuth } from "@cotal-ai/core";
|
|
24
|
+
import type { HolderLiveness } from "./reconcile-gate.js";
|
|
25
|
+
/**
|
|
26
|
+
* Map a delivery-admin reply to the reconciler's verdict — the whole trust-boundary decision, as
|
|
27
|
+
* ONE pure function so the rail probe and the tests exercise the SAME mapping rather than two
|
|
28
|
+
* copies that can drift. Every non-verdict is `unestablishable`; nothing here can yield `gone`
|
|
29
|
+
* except an oracle that affirmatively said so under a complete sweep.
|
|
30
|
+
*/
|
|
31
|
+
export declare function holderLivenessFromReply(data: unknown, principal: string): HolderLiveness;
|
|
32
|
+
/** Build the reconciler's `probeHolder(principal) → verdict`. Per-call connection, exactly as the
|
|
33
|
+
* evictor does: a standing privileged connection would be a wider surface holding nothing. */
|
|
34
|
+
export declare function makeManagerHolderLivenessProbe(opts: {
|
|
35
|
+
space: string;
|
|
36
|
+
servers: string;
|
|
37
|
+
auth: SpaceAuth;
|
|
38
|
+
log: (line: string) => void;
|
|
39
|
+
}): (principal: string) => Promise<HolderLiveness>;
|
|
40
|
+
//# sourceMappingURL=holder-liveness.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"holder-liveness.d.ts","sourceRoot":"","sources":["../src/holder-liveness.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAAuE,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;AACrH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,cAAc,CAoBxF;AAED;+FAC+F;AAC/F,wBAAgB,8BAA8B,CAAC,IAAI,EAAE;IACnD,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,SAAS,CAAC;IAChB,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B,GAAG,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,CA2CjD"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The gate reconciler's AFFIRMATIVE freeze-holder check (Cotal #391), over the delivery daemon's
|
|
3
|
+
* `ctl.delivery-admin` rail — the READ twin of {@link makeManagerEndpointEvictor}, and deliberately
|
|
4
|
+
* shaped like it so the two guards of the same repair read the same way.
|
|
5
|
+
*
|
|
6
|
+
* The `$SYS` CONNZ capability lives with the DELIVERY DAEMON (co-located with the broker), never in
|
|
7
|
+
* a seed-holding process — the same D5 rail-split the evictor obeys. This reaches it with a
|
|
8
|
+
* per-call SCOPED `endpoint-evictor` credential: pub the delivery-admin subject + reply +
|
|
9
|
+
* `$JS.API.INFO`, nothing else. That credential names eviction because it is the rail's existing
|
|
10
|
+
* scope; the VERB it calls here is read-only, and the daemon-side executor opens only the CONNZ
|
|
11
|
+
* observer cred — the kick-capable evictor cred is never read on that path.
|
|
12
|
+
*
|
|
13
|
+
* EVERY FAILURE IS A REFUSAL, NEVER A PASS. Unlike the evictor — whose no-oracle case throws so the
|
|
14
|
+
* barrier fails closed — this returns a STRUCTURED verdict, because the reconciler must tell the
|
|
15
|
+
* operator WHICH condition refused. The mapping is total and there is no branch that infers death:
|
|
16
|
+
* - a reachable daemon's `live` / `gone` / `unknown` verdict passes through as-is;
|
|
17
|
+
* - a daemon refusal, an unreachable rail, or a REQUEST TIMEOUT is `unestablishable` — a timeout
|
|
18
|
+
* is the canonical "absence of evidence", and reading it as death is the exact defect this
|
|
19
|
+
* command exists to avoid;
|
|
20
|
+
* - a garbled reply, or one that does not ECHO the principal asked about, is `unestablishable` —
|
|
21
|
+
* a result that does not verifiably describe THIS principal never authorizes.
|
|
22
|
+
*/
|
|
23
|
+
import { CotalEndpoint, mintCreds, newIdentity, parsePrincipalLivenessResult } from "@cotal-ai/core";
|
|
24
|
+
/**
|
|
25
|
+
* Map a delivery-admin reply to the reconciler's verdict — the whole trust-boundary decision, as
|
|
26
|
+
* ONE pure function so the rail probe and the tests exercise the SAME mapping rather than two
|
|
27
|
+
* copies that can drift. Every non-verdict is `unestablishable`; nothing here can yield `gone`
|
|
28
|
+
* except an oracle that affirmatively said so under a complete sweep.
|
|
29
|
+
*/
|
|
30
|
+
export function holderLivenessFromReply(data, principal) {
|
|
31
|
+
// Closed + ECHO-BOUND parse: the reply crosses a trust boundary, and one that describes a
|
|
32
|
+
// different principal (or no principal) tells us nothing about ours.
|
|
33
|
+
const parsed = parsePrincipalLivenessResult(data, principal);
|
|
34
|
+
if (parsed === undefined)
|
|
35
|
+
return {
|
|
36
|
+
state: "unestablishable",
|
|
37
|
+
detail: `garbled or foreign liveness result (${JSON.stringify(data ?? null)}); a result that does not verifiably describe "${principal}" never authorizes`,
|
|
38
|
+
};
|
|
39
|
+
// An internally CONTRADICTORY success never authorizes: `gone` is (sweep complete, none remain),
|
|
40
|
+
// so `gone` under an incomplete sweep is a broken oracle, not a verdict.
|
|
41
|
+
if (parsed.state === "gone" && parsed.sweepComplete !== true)
|
|
42
|
+
return {
|
|
43
|
+
state: "unestablishable",
|
|
44
|
+
detail: "the oracle reported gone with sweepComplete=false; a contradictory result never authorizes",
|
|
45
|
+
};
|
|
46
|
+
return {
|
|
47
|
+
state: parsed.state,
|
|
48
|
+
detail: `delivery-daemon CONNZ sweep, sweepComplete=${String(parsed.sweepComplete)}${parsed.note ? `: ${parsed.note}` : ""}`,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/** Build the reconciler's `probeHolder(principal) → verdict`. Per-call connection, exactly as the
|
|
52
|
+
* evictor does: a standing privileged connection would be a wider surface holding nothing. */
|
|
53
|
+
export function makeManagerHolderLivenessProbe(opts) {
|
|
54
|
+
return async (principal) => {
|
|
55
|
+
const id = newIdentity();
|
|
56
|
+
let ep;
|
|
57
|
+
try {
|
|
58
|
+
const creds = await mintCreds(opts.auth, id, "endpoint-evictor", { expiresInSeconds: 60 });
|
|
59
|
+
ep = new CotalEndpoint({
|
|
60
|
+
space: opts.space,
|
|
61
|
+
servers: opts.servers,
|
|
62
|
+
creds,
|
|
63
|
+
card: { id: id.id, name: "manager-holder-liveness", kind: "endpoint" },
|
|
64
|
+
channels: [],
|
|
65
|
+
consume: false,
|
|
66
|
+
watchChannels: false,
|
|
67
|
+
watchPresence: false,
|
|
68
|
+
registerPresence: false,
|
|
69
|
+
});
|
|
70
|
+
ep.on("error", () => { });
|
|
71
|
+
await ep.start();
|
|
72
|
+
const r = await ep.requestDeliveryAdmin("principalLiveness", { principal }, 15_000);
|
|
73
|
+
if (!r.ok)
|
|
74
|
+
return {
|
|
75
|
+
state: "unestablishable",
|
|
76
|
+
detail: `the delivery daemon refused the liveness query: ${r.error ?? "(no error copy)"}`,
|
|
77
|
+
};
|
|
78
|
+
const verdict = holderLivenessFromReply(r.data, principal);
|
|
79
|
+
opts.log(`manager-holder-liveness: ${principal}: ${verdict.state} (${verdict.detail})`);
|
|
80
|
+
return verdict;
|
|
81
|
+
}
|
|
82
|
+
catch (e) {
|
|
83
|
+
// The rail is unreachable, or the request TIMED OUT. Both are UNKNOWABILITY, and neither is
|
|
84
|
+
// death: this is the branch a mutation would have to corrupt to turn verify-dead into
|
|
85
|
+
// assume-dead-on-timeout, and it is the reason the reconciler refuses instead of proceeding.
|
|
86
|
+
return {
|
|
87
|
+
state: "unestablishable",
|
|
88
|
+
detail: `the delivery daemon is not reachable on the ctl.delivery-admin rail (${e instanceof Error ? e.message : String(e)}); ` +
|
|
89
|
+
`without the liveness oracle the freeze-holder "${principal}" cannot be proven gone. ` +
|
|
90
|
+
"Start the delivery daemon (`cotal up` runs it) and re-run — this repair never infers death from silence",
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
finally {
|
|
94
|
+
await ep?.stop().catch(() => { });
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=holder-liveness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"holder-liveness.js","sourceRoot":"","sources":["../src/holder-liveness.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The manager's v0.4 SERVICE CONTRACT (control-surface P2 item 1): the §13.7 cluster document +
|
|
3
|
+
* compiled command contracts that let the manager register as an ordinary `service` endpoint and
|
|
4
|
+
* serve typed commands on the `ep.*` rails, dual-served beside its bespoke
|
|
5
|
+
* `ctl.<tier>.<owner>.<actor>` control subjects until 1d deletes those.
|
|
6
|
+
*
|
|
7
|
+
* This module is PURE DATA + schema (no broker, no barrier, no wire I/O): the content-addressed
|
|
8
|
+
* cluster document (the authority for every command's served shape) and the provenance-branded
|
|
9
|
+
* `compileContract` pairs each `EpCommandDef` must carry. The registration/serve WIRING lives in
|
|
10
|
+
* the manager (`registerManagerService`).
|
|
11
|
+
*
|
|
12
|
+
* REVISION 2 (slice 1b): the FULL op fan-out. Every served `ctl` op maps to a typed command; the
|
|
13
|
+
* v0.3 op names map onto the Appendix-B caller vocabulary where one exists (`start` -> `spawn`;
|
|
14
|
+
* the named `stop` -> `despawn` — on the v0.3 surface a named stop and a despawn are the same
|
|
15
|
+
* terminal; the self no-name `stop` -> `stop` with authz-mode `self`; the per-agent `status`
|
|
16
|
+
* read -> `inspect`, distinct from the 1a manager-level `status`). Targeting: `despawn`/`attach`
|
|
17
|
+
* ride owner mode (the target block names the agent's principal + lifecycle uid; the fresh
|
|
18
|
+
* resolver checks currency). `child` mode is DELIBERATELY NOT DECLARED anywhere — the panel's 1b
|
|
19
|
+
* gate requires a DURABLE spawner record before child mode exists, so it fails closed by absence
|
|
20
|
+
* until that record lands; own-child narrowing on despawn/attach meanwhile rides the SAME
|
|
21
|
+
* `authorizeNamedControl` policy the ctl privileged tier runs (in-memory spawner, identical
|
|
22
|
+
* source both doors). `ledger` mode is likewise absent (admin != ledger in static mode): every
|
|
23
|
+
* admin-class command is untargeted + capability-gated — the broker grant (who holds the
|
|
24
|
+
* request-publish row) stays the load-bearing tier boundary, exactly as the ctl cred layer is
|
|
25
|
+
* today; the 1c migration table names who mints which capability.
|
|
26
|
+
*
|
|
27
|
+
* Capability labels (describe/grant vocabulary, one per tier class):
|
|
28
|
+
* manager.read status / ps / inspect / models (read-only)
|
|
29
|
+
* manager.spawn spawn (privileged-grade creation)
|
|
30
|
+
* manager.lifecycle despawn / attach (owner-mode terminal/interactive)
|
|
31
|
+
* manager.self stop (self-mode halt; baseline)
|
|
32
|
+
* manager.persona definePersona (privileged-grade; ownership-checked)
|
|
33
|
+
* manager.admin purge / launch / resume family (operator instruments only)
|
|
34
|
+
*/
|
|
35
|
+
import { type CompiledContract, type EpAuthzMode, type EpCommandDef, type EpServeContext } from "@cotal-ai/core";
|
|
36
|
+
/** The manager's endpoint NAME — a core single-label name (needs OPERATOR name authority at
|
|
37
|
+
* registration; the manager holds the space signing seed, so it self-authorizes). */
|
|
38
|
+
export declare const MANAGER_ENDPOINT = "manager";
|
|
39
|
+
/** The manager cluster document's URN (§13.7 content-addressed authority). */
|
|
40
|
+
export declare const MANAGER_CLUSTER_URN = "ai.cotal.manager";
|
|
41
|
+
/** The typed shape a `status` invocation returns (the compiled output contract validates it). */
|
|
42
|
+
export interface ManagerStatus {
|
|
43
|
+
instanceId: string;
|
|
44
|
+
runtime: string;
|
|
45
|
+
agentCount: number;
|
|
46
|
+
uptimeMs: number;
|
|
47
|
+
}
|
|
48
|
+
/** Per-command compiled contract pairs, exported for CALLERS (`epCall` pins the same digests the
|
|
49
|
+
* cluster document registers; the generic invoke CLI compiles these from the STORE instead). */
|
|
50
|
+
export declare const MANAGER_CONTRACTS: Readonly<Record<string, {
|
|
51
|
+
input: CompiledContract;
|
|
52
|
+
output: CompiledContract;
|
|
53
|
+
}>>;
|
|
54
|
+
/** Every §13.7 contract artifact the manager PUBLISHES to the EPC store at registration (P2 item
|
|
55
|
+
* 1, 1c): each DISTINCT schema root plus its single-member closure manifest — the two artifacts
|
|
56
|
+
* a caller fetches at a command's input/output CLOSURE digest (`fetchContractClosure` walks
|
|
57
|
+
* manifest → root) to recompile the digest-matching validators. The cluster document + ITS
|
|
58
|
+
* manifest ride separately ({@link managerClusterArtifacts}). */
|
|
59
|
+
export declare function managerContractArtifactValues(): unknown[];
|
|
60
|
+
/** The 1a `status` pair, kept as a named export (existing callers/smokes). */
|
|
61
|
+
export declare const MANAGER_STATUS_CONTRACT: {
|
|
62
|
+
input: CompiledContract;
|
|
63
|
+
output: CompiledContract;
|
|
64
|
+
};
|
|
65
|
+
/** The §13.7 cluster DOCUMENT: the content-addressed authority for the manager's served command
|
|
66
|
+
* surface. Revisions: 3 = the 1c any-mode despawn/attach admission; 4 = item-2's spawn-as-action;
|
|
67
|
+
* 5 = item-6's `attach` output flip (ws:// URL → the holder-bound §13.6 session grant).
|
|
68
|
+
*
|
|
69
|
+
* 6 = `launch` accepts the inline `spec` of a remote manifest deploy. The handler branch for it
|
|
70
|
+
* merged in ahead of the schema, so the compiled contract refused every request that carried the
|
|
71
|
+
* field and the feature was unreachable through this door (executed: the compiled input validator
|
|
72
|
+
* returned false for `{runId, name, spec}` while the CLI sends exactly that). ONE revision 6
|
|
73
|
+
* covers the whole branch: when the journal-action work lands, its `action` marker and
|
|
74
|
+
* `readinessDeadlineMs` declaration join THIS revision rather than minting a seventh. */
|
|
75
|
+
export declare function managerClusterDocument(): {
|
|
76
|
+
urn: string;
|
|
77
|
+
revision: number;
|
|
78
|
+
attributes: never[];
|
|
79
|
+
events: never[];
|
|
80
|
+
commands: Array<{
|
|
81
|
+
name: string;
|
|
82
|
+
class: "ephemeral";
|
|
83
|
+
targeted: boolean;
|
|
84
|
+
modes?: EpAuthzMode[];
|
|
85
|
+
capability: string;
|
|
86
|
+
inputDigest: string;
|
|
87
|
+
outputDigest: string;
|
|
88
|
+
}>;
|
|
89
|
+
};
|
|
90
|
+
/** The two-digest §13.7 content addressing for the manager document: the registered CLOSURE digest
|
|
91
|
+
* names a `{v:1, root:<artifactDigest>, members:[]}` manifest whose root names the DOCUMENT. Both
|
|
92
|
+
* artifacts are published to the `epc` store at their own digest; `clusterDigests` in the service
|
|
93
|
+
* spec carries the closure digest. Returned together so the manager publishes both then registers
|
|
94
|
+
* under the closure digest. */
|
|
95
|
+
export declare function managerClusterArtifacts(): {
|
|
96
|
+
document: ReturnType<typeof managerClusterDocument>;
|
|
97
|
+
rootDigest: string;
|
|
98
|
+
manifest: {
|
|
99
|
+
v: 1;
|
|
100
|
+
root: string;
|
|
101
|
+
members: string[];
|
|
102
|
+
};
|
|
103
|
+
closureDigest: string;
|
|
104
|
+
};
|
|
105
|
+
/** The handlers the manager supplies to back each served command. Each receives the serve
|
|
106
|
+
* CONTEXT (the broker-authenticated subject shape beside the validated args/target) so the
|
|
107
|
+
* manager can run its shared admission chokepoint and derive the caller principal; each returns
|
|
108
|
+
* the command's output value (the compiled output contract validates it at the serve boundary).
|
|
109
|
+
* Kept as a narrow interface so the contract module stays broker-free. */
|
|
110
|
+
export interface ManagerServiceHandlers {
|
|
111
|
+
status(ctx: EpServeContext): ManagerStatus | Promise<ManagerStatus>;
|
|
112
|
+
ps(ctx: EpServeContext): unknown | Promise<unknown>;
|
|
113
|
+
inspect(ctx: EpServeContext): unknown | Promise<unknown>;
|
|
114
|
+
models(ctx: EpServeContext): unknown | Promise<unknown>;
|
|
115
|
+
spawn(ctx: EpServeContext): unknown | Promise<unknown>;
|
|
116
|
+
despawn(ctx: EpServeContext): unknown | Promise<unknown>;
|
|
117
|
+
attach(ctx: EpServeContext): unknown | Promise<unknown>;
|
|
118
|
+
stopSelf(ctx: EpServeContext): unknown | Promise<unknown>;
|
|
119
|
+
definePersona(ctx: EpServeContext): unknown | Promise<unknown>;
|
|
120
|
+
purge(ctx: EpServeContext): unknown | Promise<unknown>;
|
|
121
|
+
launch(ctx: EpServeContext): unknown | Promise<unknown>;
|
|
122
|
+
resumePreserved(ctx: EpServeContext): unknown | Promise<unknown>;
|
|
123
|
+
commitResume(ctx: EpServeContext): unknown | Promise<unknown>;
|
|
124
|
+
finalizeResume(ctx: EpServeContext): unknown | Promise<unknown>;
|
|
125
|
+
preparePreservation(ctx: EpServeContext): unknown | Promise<unknown>;
|
|
126
|
+
commitPreservation(ctx: EpServeContext): unknown | Promise<unknown>;
|
|
127
|
+
abortPreservation(ctx: EpServeContext): unknown | Promise<unknown>;
|
|
128
|
+
}
|
|
129
|
+
/** Build the `EpCommandDef[]` `serveEndpoint` consumes: each command's provenance-branded compiled
|
|
130
|
+
* contracts (matching the document's pinned digests exactly) plus its handler. */
|
|
131
|
+
export declare function managerCommandDefs(handlers: ManagerServiceHandlers): EpCommandDef[];
|
|
132
|
+
//# sourceMappingURL=manager-service-contract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager-service-contract.d.ts","sourceRoot":"","sources":["../src/manager-service-contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,OAAO,EAIL,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,cAAc,EACpB,MAAM,gBAAgB,CAAC;AAExB;sFACsF;AACtF,eAAO,MAAM,gBAAgB,YAAY,CAAC;AAE1C,8EAA8E;AAC9E,eAAO,MAAM,mBAAmB,qBAAqB,CAAC;AAqBtD,iGAAiG;AACjG,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AA2OD;iGACiG;AACjG,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,gBAAgB,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAA;CAAE,CAAC,CACrF,CAAC;AAE1B;;;;kEAIkE;AAClE,wBAAgB,6BAA6B,IAAI,OAAO,EAAE,CAYzD;AAED,8EAA8E;AAC9E,eAAO,MAAM,uBAAuB,EAAE;IAAE,KAAK,EAAE,gBAAgB,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAA;CAA6B,CAAC;AAEvH;;;;;;;;;0FAS0F;AAC1F,wBAAgB,sBAAsB,IAAI;IACxC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,KAAK,EAAE,CAAC;IACpB,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,QAAQ,EAAE,KAAK,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,WAAW,CAAC;QACnB,QAAQ,EAAE,OAAO,CAAC;QAClB,KAAK,CAAC,EAAE,WAAW,EAAE,CAAC;QACtB,UAAU,EAAE,MAAM,CAAC;QACnB,WAAW,EAAE,MAAM,CAAC;QACpB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC,CAAC;CACJ,CAgBA;AAED;;;;gCAIgC;AAChC,wBAAgB,uBAAuB,IAAI;IACzC,QAAQ,EAAE,UAAU,CAAC,OAAO,sBAAsB,CAAC,CAAC;IACpD,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE;QAAE,CAAC,EAAE,CAAC,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IACpD,aAAa,EAAE,MAAM,CAAC;CACvB,CAMA;AAED;;;;2EAI2E;AAC3E,MAAM,WAAW,sBAAsB;IACrC,MAAM,CAAC,GAAG,EAAE,cAAc,GAAG,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IACpE,EAAE,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACpD,OAAO,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACzD,MAAM,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACxD,KAAK,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACvD,OAAO,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACzD,MAAM,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACxD,QAAQ,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1D,aAAa,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/D,KAAK,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACvD,MAAM,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACxD,eAAe,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACjE,YAAY,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9D,cAAc,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAChE,mBAAmB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACrE,kBAAkB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACpE,iBAAiB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACpE;AAED;mFACmF;AACnF,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,sBAAsB,GAAG,YAAY,EAAE,CAMnF"}
|