@cotal-ai/core 0.12.0 → 0.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/acls.d.ts +31 -7
- package/dist/acls.d.ts.map +1 -1
- package/dist/acls.js +105 -17
- package/dist/acls.js.map +1 -1
- package/dist/agent-file.js +1 -1
- package/dist/agent-file.js.map +1 -1
- package/dist/auth-provider.d.ts +8 -0
- package/dist/auth-provider.d.ts.map +1 -1
- package/dist/auth-provider.js.map +1 -1
- package/dist/backup.d.ts.map +1 -1
- package/dist/backup.js +6 -4
- package/dist/backup.js.map +1 -1
- package/dist/broker-floor.d.ts +34 -0
- package/dist/broker-floor.d.ts.map +1 -0
- package/dist/broker-floor.js +39 -0
- package/dist/broker-floor.js.map +1 -0
- package/dist/canonical.d.ts +24 -0
- package/dist/canonical.d.ts.map +1 -0
- package/dist/canonical.js +159 -0
- package/dist/canonical.js.map +1 -0
- package/dist/connector.d.ts +4 -0
- package/dist/connector.d.ts.map +1 -1
- package/dist/endpoint-action.d.ts +424 -0
- package/dist/endpoint-action.d.ts.map +1 -0
- package/dist/endpoint-action.js +910 -0
- package/dist/endpoint-action.js.map +1 -0
- package/dist/endpoint-binding.d.ts +344 -0
- package/dist/endpoint-binding.d.ts.map +1 -0
- package/dist/endpoint-binding.js +753 -0
- package/dist/endpoint-binding.js.map +1 -0
- package/dist/endpoint-checkpoint.d.ts +292 -0
- package/dist/endpoint-checkpoint.d.ts.map +1 -0
- package/dist/endpoint-checkpoint.js +818 -0
- package/dist/endpoint-checkpoint.js.map +1 -0
- package/dist/endpoint-cluster.d.ts +95 -0
- package/dist/endpoint-cluster.d.ts.map +1 -0
- package/dist/endpoint-cluster.js +194 -0
- package/dist/endpoint-cluster.js.map +1 -0
- package/dist/endpoint-contract-store.d.ts +90 -0
- package/dist/endpoint-contract-store.d.ts.map +1 -0
- package/dist/endpoint-contract-store.js +348 -0
- package/dist/endpoint-contract-store.js.map +1 -0
- package/dist/endpoint-envelope.d.ts +165 -0
- package/dist/endpoint-envelope.d.ts.map +1 -0
- package/dist/endpoint-envelope.js +346 -0
- package/dist/endpoint-envelope.js.map +1 -0
- package/dist/endpoint-grants.d.ts +123 -0
- package/dist/endpoint-grants.d.ts.map +1 -0
- package/dist/endpoint-grants.js +215 -0
- package/dist/endpoint-grants.js.map +1 -0
- package/dist/endpoint-guard.d.ts +222 -0
- package/dist/endpoint-guard.d.ts.map +1 -0
- package/dist/endpoint-guard.js +468 -0
- package/dist/endpoint-guard.js.map +1 -0
- package/dist/endpoint-handle.d.ts +176 -0
- package/dist/endpoint-handle.d.ts.map +1 -0
- package/dist/endpoint-handle.js +608 -0
- package/dist/endpoint-handle.js.map +1 -0
- package/dist/endpoint-journal.d.ts +225 -0
- package/dist/endpoint-journal.d.ts.map +1 -0
- package/dist/endpoint-journal.js +431 -0
- package/dist/endpoint-journal.js.map +1 -0
- package/dist/endpoint-receipt.d.ts +225 -0
- package/dist/endpoint-receipt.d.ts.map +1 -0
- package/dist/endpoint-receipt.js +417 -0
- package/dist/endpoint-receipt.js.map +1 -0
- package/dist/endpoint-records.d.ts +243 -0
- package/dist/endpoint-records.d.ts.map +1 -0
- package/dist/endpoint-records.js +591 -0
- package/dist/endpoint-records.js.map +1 -0
- package/dist/endpoint-serve.d.ts +176 -0
- package/dist/endpoint-serve.d.ts.map +1 -0
- package/dist/endpoint-serve.js +446 -0
- package/dist/endpoint-serve.js.map +1 -0
- package/dist/endpoint-service.d.ts +518 -0
- package/dist/endpoint-service.d.ts.map +1 -0
- package/dist/endpoint-service.js +973 -0
- package/dist/endpoint-service.js.map +1 -0
- package/dist/endpoint-session.d.ts +398 -0
- package/dist/endpoint-session.d.ts.map +1 -0
- package/dist/endpoint-session.js +834 -0
- package/dist/endpoint-session.js.map +1 -0
- package/dist/endpoint-signing.d.ts +105 -0
- package/dist/endpoint-signing.d.ts.map +1 -0
- package/dist/endpoint-signing.js +190 -0
- package/dist/endpoint-signing.js.map +1 -0
- package/dist/endpoint-subjects.d.ts +222 -0
- package/dist/endpoint-subjects.d.ts.map +1 -0
- package/dist/endpoint-subjects.js +381 -0
- package/dist/endpoint-subjects.js.map +1 -0
- package/dist/endpoint-supervisor.d.ts +19 -0
- package/dist/endpoint-supervisor.d.ts.map +1 -0
- package/dist/endpoint-supervisor.js +12 -0
- package/dist/endpoint-supervisor.js.map +1 -0
- package/dist/endpoint-traits.d.ts +225 -0
- package/dist/endpoint-traits.d.ts.map +1 -0
- package/dist/endpoint-traits.js +469 -0
- package/dist/endpoint-traits.js.map +1 -0
- package/dist/endpoint-verbs.d.ts +277 -0
- package/dist/endpoint-verbs.d.ts.map +1 -0
- package/dist/endpoint-verbs.js +576 -0
- package/dist/endpoint-verbs.js.map +1 -0
- package/dist/endpoint-virtual.d.ts +308 -0
- package/dist/endpoint-virtual.d.ts.map +1 -0
- package/dist/endpoint-virtual.js +440 -0
- package/dist/endpoint-virtual.js.map +1 -0
- package/dist/endpoint-work.d.ts +304 -0
- package/dist/endpoint-work.d.ts.map +1 -0
- package/dist/endpoint-work.js +728 -0
- package/dist/endpoint-work.js.map +1 -0
- package/dist/endpoint.d.ts +66 -22
- package/dist/endpoint.d.ts.map +1 -1
- package/dist/endpoint.js +289 -89
- package/dist/endpoint.js.map +1 -1
- package/dist/evict.d.ts +95 -32
- package/dist/evict.d.ts.map +1 -1
- package/dist/evict.js +193 -3
- package/dist/evict.js.map +1 -1
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -1
- package/dist/lease.d.ts +4 -0
- package/dist/lease.d.ts.map +1 -1
- package/dist/lease.js.map +1 -1
- package/dist/members.d.ts +4 -4
- package/dist/members.d.ts.map +1 -1
- package/dist/members.js +12 -12
- package/dist/members.js.map +1 -1
- package/dist/provision.d.ts +70 -18
- package/dist/provision.d.ts.map +1 -1
- package/dist/provision.js +194 -33
- package/dist/provision.js.map +1 -1
- package/dist/safe-pattern.d.ts +33 -0
- package/dist/safe-pattern.d.ts.map +1 -0
- package/dist/safe-pattern.js +486 -0
- package/dist/safe-pattern.js.map +1 -0
- package/dist/schema-profile.d.ts +93 -0
- package/dist/schema-profile.d.ts.map +1 -0
- package/dist/schema-profile.js +284 -0
- package/dist/schema-profile.js.map +1 -0
- package/dist/streams.d.ts +13 -8
- package/dist/streams.d.ts.map +1 -1
- package/dist/streams.js +35 -18
- package/dist/streams.js.map +1 -1
- package/dist/subjects.d.ts +100 -40
- package/dist/subjects.d.ts.map +1 -1
- package/dist/subjects.js +136 -60
- package/dist/subjects.js.map +1 -1
- package/dist/types.d.ts +9 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -1
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** Digest identity form used everywhere a contract artifact is referenced: `sha256:<hex>`. */
|
|
2
|
+
export declare const DIGEST_PREFIX: "sha256:";
|
|
3
|
+
/** True iff `s` is a well-formed `sha256:<hex>` artifact digest. */
|
|
4
|
+
export declare function isContractDigest(s: string): boolean;
|
|
5
|
+
/** True iff the string is well-formed UTF-16 (no unpaired surrogate). A lone surrogate has NO
|
|
6
|
+
* UTF-8 byte encoding — encoders silently substitute U+FFFD, so two distinct malformed strings
|
|
7
|
+
* can collapse to one byte sequence; anything digest- or wire-bound must refuse them. */
|
|
8
|
+
export declare function isWellFormedUnicode(s: string): boolean;
|
|
9
|
+
/** RFC 8785 canonical JSON text of a value (strict: I-JSON enforced, no undefined→null). */
|
|
10
|
+
export declare function canonicalJson(value: unknown): string;
|
|
11
|
+
/** Content address of a contract artifact: `sha256:<hex>` over its RFC 8785 form (SPEC §13.7). */
|
|
12
|
+
export declare function contractDigest(value: unknown): string;
|
|
13
|
+
/** `sha256:<hex>` over RAW bytes (a string digests as its UTF-8 encoding), NEVER re-canonicalized:
|
|
14
|
+
* the digest form for artifacts carried as opaque bytes — the §13.3 `auth` slot (`authDigest`,
|
|
15
|
+
* digested exactly as carried) and the §13.4 raw stored submission bytes (`submissionDigest`).
|
|
16
|
+
* A string input MUST be well-formed UTF-16: a lone surrogate has no UTF-8 encoding, the
|
|
17
|
+
* encoder would substitute U+FFFD, and two DISTINCT carried values would silently share one
|
|
18
|
+
* digest — the opposite of "exactly as carried". Throws instead. */
|
|
19
|
+
export declare function rawDigest(data: Uint8Array | string): string;
|
|
20
|
+
/** Verify fetched artifact BYTES against their advertised digest (verify-on-read, SPEC §13.7):
|
|
21
|
+
* content addressing, not store ACLs, is the tamper boundary. The bytes must parse as JSON and
|
|
22
|
+
* re-canonicalize to the digest; anything else throws. Returns the parsed artifact. */
|
|
23
|
+
export declare function verifyArtifact(bytes: Uint8Array, digest: string): unknown;
|
|
24
|
+
//# sourceMappingURL=canonical.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canonical.d.ts","sourceRoot":"","sources":["../src/canonical.ts"],"names":[],"mappings":"AAYA,8FAA8F;AAC9F,eAAO,MAAM,aAAa,EAAG,SAAkB,CAAC;AAGhD,oEAAoE;AACpE,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED;;0FAE0F;AAC1F,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAEtD;AAsFD,4FAA4F;AAC5F,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAGpD;AAED,kGAAkG;AAClG,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAErD;AAED;;;;;qEAKqE;AACrE,wBAAgB,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,MAAM,CAS3D;AAED;;wFAEwF;AACxF,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAWzE"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RFC 8785 canonical JSON and content addressing (SPEC §13.7, D28).
|
|
3
|
+
*
|
|
4
|
+
* Contract identity is the SHA-256 digest of the RFC 8785 canonicalization of a JSON value,
|
|
5
|
+
* over I-JSON: lone surrogates are rejected loudly (never escaped through), because a digest
|
|
6
|
+
* over non-interchangeable text is not an identity. The strict `canonicalizeEx` path is pinned
|
|
7
|
+
* (`undefinedInArrayToNull: false`): an `undefined` anywhere in the value is a programming
|
|
8
|
+
* error, not data, and MUST NOT silently become `null`.
|
|
9
|
+
*/
|
|
10
|
+
import { createHash } from "node:crypto";
|
|
11
|
+
import { canonicalizeEx } from "json-canonicalize";
|
|
12
|
+
/** Digest identity form used everywhere a contract artifact is referenced: `sha256:<hex>`. */
|
|
13
|
+
export const DIGEST_PREFIX = "sha256:";
|
|
14
|
+
const DIGEST_RE = /^sha256:[0-9a-f]{64}$/;
|
|
15
|
+
/** True iff `s` is a well-formed `sha256:<hex>` artifact digest. */
|
|
16
|
+
export function isContractDigest(s) {
|
|
17
|
+
return DIGEST_RE.test(s);
|
|
18
|
+
}
|
|
19
|
+
/** True iff the string is well-formed UTF-16 (no unpaired surrogate). A lone surrogate has NO
|
|
20
|
+
* UTF-8 byte encoding — encoders silently substitute U+FFFD, so two distinct malformed strings
|
|
21
|
+
* can collapse to one byte sequence; anything digest- or wire-bound must refuse them. */
|
|
22
|
+
export function isWellFormedUnicode(s) {
|
|
23
|
+
return !hasLoneSurrogate(s);
|
|
24
|
+
}
|
|
25
|
+
/** True iff the string contains an unpaired UTF-16 surrogate (not well-formed / I-JSON
|
|
26
|
+
* violation). Manual scan: the repo's TS lib target predates `String#isWellFormed`. */
|
|
27
|
+
function hasLoneSurrogate(s) {
|
|
28
|
+
for (let i = 0; i < s.length; i++) {
|
|
29
|
+
const c = s.charCodeAt(i);
|
|
30
|
+
if (c >= 0xd800 && c <= 0xdbff) {
|
|
31
|
+
const n = s.charCodeAt(i + 1);
|
|
32
|
+
if (!(n >= 0xdc00 && n <= 0xdfff))
|
|
33
|
+
return true;
|
|
34
|
+
i++; // well-formed pair; skip the low half
|
|
35
|
+
}
|
|
36
|
+
else if (c >= 0xdc00 && c <= 0xdfff) {
|
|
37
|
+
return true; // low surrogate with no preceding high half
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
/** Walk a JSON value and throw on anything that cannot canonicalize EXACTLY (D28: verification
|
|
43
|
+
* and digesting must never run over a normalizing projection):
|
|
44
|
+
* - strings that are not well-formed UTF-16 (a lone surrogate violates I-JSON; canonicalizing
|
|
45
|
+
* it would mint a digest for text that cannot interchange), in values AND keys;
|
|
46
|
+
* - `undefined` anywhere and non-finite numbers (RFC 8785 cannot represent them);
|
|
47
|
+
* - NON-PLAIN-DATA graphs. `Object.entries` sees only enumerable string-keyed own data props,
|
|
48
|
+
* and the canonicalizer applies `toJSON`, so a symbol-keyed or non-enumerable own property,
|
|
49
|
+
* an accessor, or a class/exotic instance (Date → ISO string, Map → `{}`) would be SILENTLY
|
|
50
|
+
* projected away or rewritten — the exact field-dropping class D28 forbids (an artifact
|
|
51
|
+
* carrying state its signature never covered must refuse, not launder through the
|
|
52
|
+
* projection). Objects must be ordinary with a `null`/`Object.prototype` prototype and only
|
|
53
|
+
* enumerable string-keyed own DATA properties; arrays must be ordinary `Array.prototype`
|
|
54
|
+
* arrays with no holes and no extra own properties. */
|
|
55
|
+
function assertInterchangeable(v, path) {
|
|
56
|
+
if (v === null)
|
|
57
|
+
return;
|
|
58
|
+
switch (typeof v) {
|
|
59
|
+
case "string":
|
|
60
|
+
if (hasLoneSurrogate(v))
|
|
61
|
+
throw new Error(`canonicalJson: lone surrogate in string at ${path} (I-JSON violation)`);
|
|
62
|
+
return;
|
|
63
|
+
case "number":
|
|
64
|
+
if (!Number.isFinite(v))
|
|
65
|
+
throw new Error(`canonicalJson: non-finite number at ${path}`);
|
|
66
|
+
return;
|
|
67
|
+
case "boolean":
|
|
68
|
+
return;
|
|
69
|
+
case "undefined":
|
|
70
|
+
throw new Error(`canonicalJson: undefined at ${path} (strict mode never coerces to null)`);
|
|
71
|
+
case "object": {
|
|
72
|
+
if (Array.isArray(v)) {
|
|
73
|
+
if (Object.getPrototypeOf(v) !== Array.prototype)
|
|
74
|
+
throw new Error(`canonicalJson: non-ordinary array at ${path} (a subclassed/exotic array canonicalizes through projections)`);
|
|
75
|
+
for (const k of Reflect.ownKeys(v)) {
|
|
76
|
+
if (typeof k !== "string")
|
|
77
|
+
throw new Error(`canonicalJson: symbol-keyed own property on array at ${path} (invisible to canonicalization; refusing the projection)`);
|
|
78
|
+
if (k === "length")
|
|
79
|
+
continue;
|
|
80
|
+
if (!/^(0|[1-9][0-9]*)$/.test(k) || Number(k) >= v.length)
|
|
81
|
+
throw new Error(`canonicalJson: non-index own property "${k}" on array at ${path} (invisible to canonicalization; refusing the projection)`);
|
|
82
|
+
}
|
|
83
|
+
for (let i = 0; i < v.length; i++) {
|
|
84
|
+
const d = Object.getOwnPropertyDescriptor(v, i);
|
|
85
|
+
if (d === undefined)
|
|
86
|
+
throw new Error(`canonicalJson: hole at ${path}[${i}] (a hole would be coerced to null; refusing the projection)`);
|
|
87
|
+
if (!d.enumerable || d.get !== undefined || d.set !== undefined)
|
|
88
|
+
throw new Error(`canonicalJson: non-enumerable or accessor element at ${path}[${i}] (refusing the projection)`);
|
|
89
|
+
assertInterchangeable(v[i], `${path}[${i}]`);
|
|
90
|
+
}
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const proto = Object.getPrototypeOf(v);
|
|
94
|
+
if (proto !== Object.prototype && proto !== null)
|
|
95
|
+
throw new Error(`canonicalJson: non-plain object at ${path} (a class/exotic instance canonicalizes through projections like toJSON; only plain data objects are interchangeable)`);
|
|
96
|
+
for (const k of Reflect.ownKeys(v)) {
|
|
97
|
+
if (typeof k !== "string")
|
|
98
|
+
throw new Error(`canonicalJson: symbol-keyed own property at ${path} (invisible to canonicalization; refusing the projection)`);
|
|
99
|
+
if (hasLoneSurrogate(k))
|
|
100
|
+
throw new Error(`canonicalJson: lone surrogate in key at ${path}.${k}`);
|
|
101
|
+
const d = Object.getOwnPropertyDescriptor(v, k);
|
|
102
|
+
if (!d.enumerable)
|
|
103
|
+
throw new Error(`canonicalJson: non-enumerable own property "${k}" at ${path} (invisible to canonicalization; refusing the projection)`);
|
|
104
|
+
if (d.get !== undefined || d.set !== undefined)
|
|
105
|
+
throw new Error(`canonicalJson: accessor property "${k}" at ${path} (a getter is code, not data; refusing the projection)`);
|
|
106
|
+
assertInterchangeable(v[k], `${path}.${k}`);
|
|
107
|
+
}
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
default:
|
|
111
|
+
throw new Error(`canonicalJson: unsupported ${typeof v} at ${path}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/** RFC 8785 canonical JSON text of a value (strict: I-JSON enforced, no undefined→null). */
|
|
115
|
+
export function canonicalJson(value) {
|
|
116
|
+
assertInterchangeable(value, "$");
|
|
117
|
+
return canonicalizeEx(value, { undefinedInArrayToNull: false });
|
|
118
|
+
}
|
|
119
|
+
/** Content address of a contract artifact: `sha256:<hex>` over its RFC 8785 form (SPEC §13.7). */
|
|
120
|
+
export function contractDigest(value) {
|
|
121
|
+
return DIGEST_PREFIX + createHash("sha256").update(canonicalJson(value), "utf8").digest("hex");
|
|
122
|
+
}
|
|
123
|
+
/** `sha256:<hex>` over RAW bytes (a string digests as its UTF-8 encoding), NEVER re-canonicalized:
|
|
124
|
+
* the digest form for artifacts carried as opaque bytes — the §13.3 `auth` slot (`authDigest`,
|
|
125
|
+
* digested exactly as carried) and the §13.4 raw stored submission bytes (`submissionDigest`).
|
|
126
|
+
* A string input MUST be well-formed UTF-16: a lone surrogate has no UTF-8 encoding, the
|
|
127
|
+
* encoder would substitute U+FFFD, and two DISTINCT carried values would silently share one
|
|
128
|
+
* digest — the opposite of "exactly as carried". Throws instead. */
|
|
129
|
+
export function rawDigest(data) {
|
|
130
|
+
const h = createHash("sha256");
|
|
131
|
+
if (typeof data === "string") {
|
|
132
|
+
if (hasLoneSurrogate(data))
|
|
133
|
+
throw new Error("rawDigest: lone surrogate in string input; no UTF-8 encoding exists, the digest would not be over the carried value");
|
|
134
|
+
h.update(data, "utf8");
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
h.update(data);
|
|
138
|
+
}
|
|
139
|
+
return DIGEST_PREFIX + h.digest("hex");
|
|
140
|
+
}
|
|
141
|
+
/** Verify fetched artifact BYTES against their advertised digest (verify-on-read, SPEC §13.7):
|
|
142
|
+
* content addressing, not store ACLs, is the tamper boundary. The bytes must parse as JSON and
|
|
143
|
+
* re-canonicalize to the digest; anything else throws. Returns the parsed artifact. */
|
|
144
|
+
export function verifyArtifact(bytes, digest) {
|
|
145
|
+
if (!isContractDigest(digest))
|
|
146
|
+
throw new Error(`verifyArtifact: malformed digest ${JSON.stringify(digest)}`);
|
|
147
|
+
let parsed;
|
|
148
|
+
try {
|
|
149
|
+
parsed = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
|
|
150
|
+
}
|
|
151
|
+
catch (e) {
|
|
152
|
+
throw new Error(`verifyArtifact: artifact for ${digest} is not valid UTF-8 JSON: ${e.message}`);
|
|
153
|
+
}
|
|
154
|
+
const actual = contractDigest(parsed);
|
|
155
|
+
if (actual !== digest)
|
|
156
|
+
throw new Error(`verifyArtifact: digest mismatch; advertised ${digest}, content is ${actual}`);
|
|
157
|
+
return parsed;
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=canonical.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canonical.js","sourceRoot":"","sources":["../src/canonical.ts"],"names":[],"mappings":"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"}
|
package/dist/connector.d.ts
CHANGED
|
@@ -23,6 +23,10 @@ export interface LaunchOpts {
|
|
|
23
23
|
sentinelCredsPath: string;
|
|
24
24
|
bearerCmd: string[];
|
|
25
25
|
};
|
|
26
|
+
/** The incarnation's lifecycle UID (SPEC §13.1), minted by the launcher at spawn. The connector
|
|
27
|
+
* forwards it (`COTAL_LIFECYCLE_UID`) so the session's endpoint binds its lifecycle-keyed
|
|
28
|
+
* dm/dlv/chathist durables — the same exact names its credential pins. */
|
|
29
|
+
lifecycleUid?: string;
|
|
26
30
|
servers?: string;
|
|
27
31
|
/** The agent's resolved access policy — the SAME read/post set the manager mints the agent's
|
|
28
32
|
* creds from. The connector forwards it (`COTAL_SUBSCRIBE` / `COTAL_ALLOW_SUBSCRIBE` /
|
package/dist/connector.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connector.d.ts","sourceRoot":"","sources":["../src/connector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D,oFAAoF;AACpF,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;8EAE0E;IAC1E,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ;mDAC+C;IAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;uGAImG;IACnG,QAAQ,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,iBAAiB,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAC5F,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;qDAMiD;IACjD,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB;;;;uDAImD;IACnD,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB;;wEAEoE;IACpE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;0GAEsG;IACtG,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;iEAG6D;IAC7D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;qFAGiF;IACjF,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC;;kFAE8E;IAC9E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;uFAMmF;IACnF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;iDAG6C;IAC7C,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;qEAIiE;IACjE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC3C;;;4FAGwF;IACxF,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,oFAAoF;AACpF,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B;;;+CAG2C;IAC3C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;wBAMoB;IACpB,OAAO,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3C;AAED;kDACkD;AAClD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED;8DAC8D;AAC9D,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,gBAAgB,EAAE,CAAC;CAC/B;AAED,qGAAqG;AACrG,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,SAAS,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,iEAAiE;AACjE,MAAM,WAAW,qBAAsB,SAAQ,YAAY;IACzD,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,SAAU,SAAQ,SAAS;IAC1C,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU,CAAC;IAC1C;8DAC0D;IAC1D,UAAU,CAAC,CAAC,IAAI,CAAC,EAAE,gBAAgB,GAAG,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAC3E;;;;;;;sEAOkE;IAClE,iBAAiB,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACzC;;;;yCAIqC;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC;;;+DAG2D;IAC3D,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;;;uBAMmB;IACnB,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAClC;iEAC6D;IAC7D,QAAQ,CAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC;CACzC"}
|
|
1
|
+
{"version":3,"file":"connector.d.ts","sourceRoot":"","sources":["../src/connector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ACTION composite (SPEC §13.6): a long-running command as a pattern over the journal +
|
|
3
|
+
* records + events — zero new transport. `action` is a command MARKER, never a class: an
|
|
4
|
+
* action's submissions are `class: journal`, its accept/reject is the durable decision fact
|
|
5
|
+
* (§13.4), and there is no reply-rail answer to recover.
|
|
6
|
+
*
|
|
7
|
+
* THE RESULT FACT IS THE SINGLE TERMINAL ARBITER; THE STATUS ONLY EVER FOLLOWS IT, and every
|
|
8
|
+
* authority coordinate is bound to the PERSISTED accepted goal, never a caller claim. The
|
|
9
|
+
* pieces, each owned by the §13.9 principal named on its row:
|
|
10
|
+
* - the GOAL BIND (canonicalizer): a create-only CAS on
|
|
11
|
+
* `epf.<e>.goal.<caller triple>.<goalId>.bind` carrying the accepted fingerprint, BEFORE
|
|
12
|
+
* acceptance — the bind keys on `goalId` and stops a second distinct submission before
|
|
13
|
+
* acceptance and effect. A bind whose winner crashed BEFORE acceptance (no goal record) is
|
|
14
|
+
* ORPHANED, and a same-fingerprint resubmission ADOPTS it ({@link resolveGoalSubmission}).
|
|
15
|
+
* - the GOAL RECORD (commit path): `goal.<e>.<caller triple>.<goalId>` spec (the accepted
|
|
16
|
+
* definition — the trusted source every later seam validates against) + status (the CURRENT
|
|
17
|
+
* state projection). The status vocabulary is `accepted → running ⇄ waiting → terminal`,
|
|
18
|
+
* `cancelling` between a cancel and its terminal. A TERMINAL status exists ONLY as the
|
|
19
|
+
* projection of the committed result fact ({@link projectGoalTerminal}); {@link
|
|
20
|
+
* transitionGoal} refuses terminal targets, so the status never leads the journal. Every
|
|
21
|
+
* EXECUTOR-authored transition on a TARGET-PINNED goal proves the executor's fresh
|
|
22
|
+
* lifecycle/epoch currency (§13.6 item 7: a superseded epoch cannot commit transitions).
|
|
23
|
+
* - the TERMINAL RESULT (commit path): a create-only CAS on
|
|
24
|
+
* `epf.<e>.goal.<caller triple>.<goalId>.result` — the ONE commit point where completion,
|
|
25
|
+
* cancel, expiry-deny, and the readiness `uncertain` settle race, first terminal fact wins
|
|
26
|
+
* uniformly. The raw CAS is PRIVATE; the public commit takes a CLOSED CAUSE whose
|
|
27
|
+
* authoritative predicate is verified INSIDE the boundary (a `complete` proves executor
|
|
28
|
+
* currency, a `cancel` proves the goal is `cancelling`, a `readiness` proves the deadline
|
|
29
|
+
* passed) and DERIVES the terminal state from the cause — a raw state is never accepted.
|
|
30
|
+
* - the TOMBSTONE (§13.6 item 5): the summary lives INSIDE the one immutable result fact;
|
|
31
|
+
* retaining the fact the full idempotency horizon satisfies both retention minimums, and
|
|
32
|
+
* early payload eviction is a serving-layer policy answered with {@link goalTombstone}.
|
|
33
|
+
* - PROGRESS rides per-goal events, read-scoped to the caller at mint time.
|
|
34
|
+
*
|
|
35
|
+
* Every seam takes a BRANDED {@link ActionContext} bonding the record store + fact stream +
|
|
36
|
+
* space, so a composition mixup cannot read an accepted spec from space A and project through
|
|
37
|
+
* space B. Clocks are inputs everywhere (`now`, `acceptedAt`): the owner's clock decides.
|
|
38
|
+
*/
|
|
39
|
+
import type { KV } from "@nats-io/kv";
|
|
40
|
+
import { type JetStreamClient, type JetStreamManager } from "@nats-io/jetstream";
|
|
41
|
+
import { type NatsConnection } from "@nats-io/transport-node";
|
|
42
|
+
import { EpEnvelopeError } from "./endpoint-envelope.js";
|
|
43
|
+
import { type EpCaller, type ParsedEpRequest } from "./endpoint-subjects.js";
|
|
44
|
+
import { type Receipt, type ReceiptStoreContext } from "./endpoint-receipt.js";
|
|
45
|
+
/** A trusted, space-bonded action context: the KV + JS + JSM all DERIVE from one binding-layer
|
|
46
|
+
* connection and one space by the constructor (never injected independently — a branded bundle
|
|
47
|
+
* of split resources would still split accepted state from terminal authority), so a
|
|
48
|
+
* composition mixup can never read an accepted spec through one broker and commit its terminal
|
|
49
|
+
* through another. BRANDED: a hand-assembled structural look-alike is rejected at every seam,
|
|
50
|
+
* not just discouraged. */
|
|
51
|
+
export interface ActionContext {
|
|
52
|
+
kv: KV;
|
|
53
|
+
js: JetStreamClient;
|
|
54
|
+
jsm: JetStreamManager;
|
|
55
|
+
space: string;
|
|
56
|
+
}
|
|
57
|
+
export declare function actionContext(nc: NatsConnection, space: string): Promise<ActionContext>;
|
|
58
|
+
/** A CONSTRUCTION-BOUND owner-authority proof: minted only from the branded context by the
|
|
59
|
+
* commit principal itself, and accepted only against THAT context. This replaces a raw
|
|
60
|
+
* `ownerAuthored` boolean — a flag any caller could set by typo or confusion — with a value
|
|
61
|
+
* that cannot be hand-assembled and cannot leak across contexts: owner authority over a
|
|
62
|
+
* target-pinned goal's pause/deny is proven by construction, never asserted (SPEC 13.6). */
|
|
63
|
+
export interface OwnerCommitProof {
|
|
64
|
+
readonly space: string;
|
|
65
|
+
}
|
|
66
|
+
export declare function ownerCommitProof(ctx: ActionContext): OwnerCommitProof;
|
|
67
|
+
/** A GATE-MINTED clearance: the only key that opens a GUARDED goal's edge into `running`
|
|
68
|
+
* (SPEC 13.6: a guarded command MUST NOT effect until the guard answered allow, and `running`
|
|
69
|
+
* IS effecting). The mint lives behind a ONE-SHOT claim that THE guard gate module takes at
|
|
70
|
+
* load, so no other holder of an action context can mint gate passage - an owner proof
|
|
71
|
+
* deliberately does NOT satisfy this edge (any context holder mints owner proofs; only the
|
|
72
|
+
* gate, whose allow/release/reconcile arms verified the guard's answer, mints clearance). */
|
|
73
|
+
export interface GuardClearance {
|
|
74
|
+
readonly goalId: string;
|
|
75
|
+
}
|
|
76
|
+
/** ONE-SHOT handoff of the clearance mint to THE gate (endpoint-guard claims it at module
|
|
77
|
+
* load; the package always loads it). Every later call is a loud refusal: there is exactly
|
|
78
|
+
* one gate, so a second claimant is by definition not it (SPEC 13.6). */
|
|
79
|
+
export declare function claimGuardClearanceMint(): (ctx: ActionContext, goalId: string) => GuardClearance;
|
|
80
|
+
/** A goal's coordinates: the owning endpoint + the caller triple + the client-chosen goalId. */
|
|
81
|
+
export interface GoalRef {
|
|
82
|
+
endpoint: string;
|
|
83
|
+
caller: EpCaller;
|
|
84
|
+
goalId: string;
|
|
85
|
+
}
|
|
86
|
+
/** Snapshot a caller-supplied ref to a validated DETACHED copy at seam entry, BEFORE the first
|
|
87
|
+
* await: a shared mutable ref can otherwise split one operation's identity across its reads,
|
|
88
|
+
* its CAS, and its terminal publish. Exported for the guard seams, which detach the goal they
|
|
89
|
+
* bind, resume, and project against the same discipline. */
|
|
90
|
+
export declare function snapshotRef(ref: GoalRef): GoalRef;
|
|
91
|
+
/** Derive a goal ref STRUCTURALLY from the broker-authenticated request (§13.6): the caller
|
|
92
|
+
* triple comes from the subject the broker admitted, DETACHED so a later mutation of the parsed
|
|
93
|
+
* request cannot retarget it, never from body fields — a seam taking this ref addresses only
|
|
94
|
+
* the authenticated caller's own goals. */
|
|
95
|
+
export declare function goalRefOf(request: ParsedEpRequest, goalId: string): GoalRef;
|
|
96
|
+
/** The goal's terminal-result fact subject (`epf.<e>.goal.<triple>.<goalId>.result`, §13.2). */
|
|
97
|
+
export declare function goalResultSubject(space: string, ref: GoalRef): string;
|
|
98
|
+
/** The per-goal progress EVENT topic tail (§13.2 reserved topics). */
|
|
99
|
+
export declare function goalProgressTopic(ref: GoalRef): string[];
|
|
100
|
+
/** The bind fact: the goalId's accepted fingerprint, immutable for the goal's lifetime. */
|
|
101
|
+
export interface GoalBindFact {
|
|
102
|
+
v: 1;
|
|
103
|
+
goalId: string;
|
|
104
|
+
fingerprint: string;
|
|
105
|
+
}
|
|
106
|
+
/** Bind a goal to its accepted fingerprint BEFORE acceptance (the canonicalizer's seam): a
|
|
107
|
+
* create-only CAS per goalId. The winner proceeds; a loser reads the recorded bind and decides
|
|
108
|
+
* (same fingerprint = retry, different = `conflict` before acceptance and effect). The subject
|
|
109
|
+
* derives from the goal ref — ONE entry-derived identity (a caller derives it from the
|
|
110
|
+
* broker-authenticated request via {@link goalRefOf} exactly once), never body fields. */
|
|
111
|
+
export declare function bindGoal(ctx: ActionContext, ref: GoalRef, fingerprint: string): Promise<{
|
|
112
|
+
bound: true;
|
|
113
|
+
} | {
|
|
114
|
+
bound: false;
|
|
115
|
+
existing: GoalBindFact;
|
|
116
|
+
}>;
|
|
117
|
+
/** The submission-vs-bind verdict (§13.6 item 5 + orphan recovery). */
|
|
118
|
+
export type GoalSubmissionVerdict = {
|
|
119
|
+
kind: "new";
|
|
120
|
+
} | {
|
|
121
|
+
kind: "cached";
|
|
122
|
+
bind: GoalBindFact;
|
|
123
|
+
result?: GoalResultFact;
|
|
124
|
+
} | {
|
|
125
|
+
kind: "adopted";
|
|
126
|
+
bind: GoalBindFact;
|
|
127
|
+
} | {
|
|
128
|
+
kind: "conflict";
|
|
129
|
+
bind: GoalBindFact;
|
|
130
|
+
};
|
|
131
|
+
/** Resolve a goal submission against the bind rail (the canonicalizer's composed seam): NEW
|
|
132
|
+
* work (bind won); the caller's retry serving the CACHED decision/outcome (same fingerprint +
|
|
133
|
+
* a persisted goal whose spec AGREES with the bind); orphan ADOPTION (same fingerprint, no goal
|
|
134
|
+
* record — the bind winner crashed pre-acceptance); or `conflict` (different fingerprint). A
|
|
135
|
+
* persisted spec whose fingerprint disagrees with the bind is a loud `internal` (garbled
|
|
136
|
+
* authority chain), never a silent cached serve. */
|
|
137
|
+
export declare function resolveGoalSubmission(ctx: ActionContext, request: ParsedEpRequest, goalId: string, fingerprint: string): Promise<GoalSubmissionVerdict>;
|
|
138
|
+
/** The §13.6 single status vocabulary for every long-running surface. */
|
|
139
|
+
export declare const GOAL_STATES: readonly ["accepted", "running", "waiting", "cancelling", "succeeded", "failed", "cancelled", "expired", "uncertain"];
|
|
140
|
+
export type GoalState = (typeof GOAL_STATES)[number];
|
|
141
|
+
/** All five are TERMINAL and immutable; first-terminal-fact-wins applies uniformly. */
|
|
142
|
+
export declare const GOAL_TERMINAL_STATES: readonly GoalState[];
|
|
143
|
+
/** The legal §13.6 transitions: `accepted → running ⇄ waiting`, `cancelling` between a cancel
|
|
144
|
+
* and its terminal, every non-terminal may project a terminal, a terminal absorbs. */
|
|
145
|
+
export declare function isLegalGoalTransition(from: GoalState, to: GoalState): boolean;
|
|
146
|
+
/** The goal SPEC (written once at acceptance): the accepted definition every later seam
|
|
147
|
+
* validates against — the terminal commit stamps ITS fingerprint from here, the readiness
|
|
148
|
+
* settle reads ITS bound from here, and a target-pinned goal fences on ITS target lifecycle. */
|
|
149
|
+
export interface GoalSpecValue {
|
|
150
|
+
v: 1;
|
|
151
|
+
goalId: string;
|
|
152
|
+
fingerprint: string;
|
|
153
|
+
command: string;
|
|
154
|
+
caller: {
|
|
155
|
+
id: string;
|
|
156
|
+
lifecycleUid: string;
|
|
157
|
+
};
|
|
158
|
+
target?: {
|
|
159
|
+
owner: string;
|
|
160
|
+
actor: string;
|
|
161
|
+
lifecycleUid: string;
|
|
162
|
+
mappingRevision: number;
|
|
163
|
+
};
|
|
164
|
+
/** The accepted submission's request id — the goal's ADDRESS for its durable acceptance fact
|
|
165
|
+
* (`epf.<e>.dec.<triple>.<id>`), written at acceptance when it is known. The raw submission
|
|
166
|
+
* (EPJ) is age-evicted, so receipt reconstruction after a crash reads the acceptance THROUGH
|
|
167
|
+
* this address and proves the chain (id + sourceSeq + fingerprint) before minting (§13.10). */
|
|
168
|
+
requestId: string;
|
|
169
|
+
/** The guard endpoint named by the command's VERIFIED `ai.cotal.guarded` trait value,
|
|
170
|
+
* recorded at acceptance. Its PRESENCE is what {@link transitionGoal} enforces: a guarded
|
|
171
|
+
* goal's edge into `running` opens only with THE gate's {@link GuardClearance} - an
|
|
172
|
+
* unrecorded guard binding is unenforceable, so the acceptance path MUST record it
|
|
173
|
+
* (SPEC 13.6/13.7). */
|
|
174
|
+
guard?: string;
|
|
175
|
+
sourceSeq: number;
|
|
176
|
+
acceptedAt: number;
|
|
177
|
+
readinessDeadlineMs?: number;
|
|
178
|
+
}
|
|
179
|
+
/** Read the persisted accepted goal (`undefined` = never accepted). A DEL marker refuses. */
|
|
180
|
+
export declare function readGoalSpec(ctx: ActionContext, ref: GoalRef): Promise<{
|
|
181
|
+
value: GoalSpecValue;
|
|
182
|
+
revision: number;
|
|
183
|
+
} | undefined>;
|
|
184
|
+
/** The goal STATUS value: the current state projection. State-dependent fields are CLOSED. */
|
|
185
|
+
export interface GoalStatusValue extends Record<string, unknown> {
|
|
186
|
+
state: GoalState;
|
|
187
|
+
checkpoint?: {
|
|
188
|
+
token: string;
|
|
189
|
+
deadlineGeneration: number;
|
|
190
|
+
};
|
|
191
|
+
cancelMode?: "graceful" | "terminate";
|
|
192
|
+
observedSpecRevision: number;
|
|
193
|
+
}
|
|
194
|
+
/** Create the goal record at acceptance, IDEMPOTENTLY (spec create-only, then the `accepted`
|
|
195
|
+
* status): a crash between the two writes (or an adopted-retry replay) re-reads the spec,
|
|
196
|
+
* requires it CONTENT-IDENTICAL, and ensures the status — no stranded spec-only goal. */
|
|
197
|
+
export declare function createGoal(ctx: ActionContext, ref: GoalRef, spec: Omit<GoalSpecValue, "v" | "goalId">): Promise<{
|
|
198
|
+
specRevision: number;
|
|
199
|
+
}>;
|
|
200
|
+
/** Read the goal's current status projection (`undefined` = unknown goal). */
|
|
201
|
+
export declare function readGoalStatus(ctx: ActionContext, ref: GoalRef): Promise<{
|
|
202
|
+
value: GoalStatusValue;
|
|
203
|
+
revision: number;
|
|
204
|
+
} | undefined>;
|
|
205
|
+
/** Leader-read a goal's status projection by ref ALONE (no {@link ActionContext}) — a fencing read
|
|
206
|
+
* for a caller OUTSIDE the action module. The retirement drain uses it to decide whether an
|
|
207
|
+
* accepted ACTION goal is still `accepted` (never entered `running`, the guard/currency-fenced
|
|
208
|
+
* effecting edge, so provably never effected) before it may create-only cancel it: a `cancelled`
|
|
209
|
+
* terminal must mean the effect did NOT run (SPEC 13.6). `undefined` = no goal record at all
|
|
210
|
+
* (never created ⇒ never ran). Leader-served (read-your-writes), so a running executor's
|
|
211
|
+
* transition is never missed as a stale absence and a mis-read never authorizes a false cancel. */
|
|
212
|
+
export declare function readGoalStatusByRefLeader(jsm: JetStreamManager, space: string, ref: GoalRef): Promise<GoalStatusValue | undefined>;
|
|
213
|
+
/** The executor's authenticated identity (subject/creds, never a body claim), required when a
|
|
214
|
+
* goal's spec pins a target lifecycle (§13.6 item 7). */
|
|
215
|
+
export interface GoalExecutor {
|
|
216
|
+
lifecycleUid: string;
|
|
217
|
+
epoch: number;
|
|
218
|
+
}
|
|
219
|
+
/** CAS the goal's status through the NON-TERMINAL machine. A TERMINAL target is REFUSED (a
|
|
220
|
+
* terminal status exists only as {@link projectGoalTerminal}). An EXECUTOR-authored PROGRESS
|
|
221
|
+
* transition (`running`/`waiting`) on a TARGET-PINNED goal MUST prove the executor's fresh
|
|
222
|
+
* currency; a `cancelling` transition is owner/caller-authored (its authority is the cancel's
|
|
223
|
+
* broker-authenticated caller, {@link requestGoalCancel}) and takes no executor; an OWNER pause
|
|
224
|
+
* (guard hold → `waiting`) may declare `ownerAuthored`. A target-pinned progress transition
|
|
225
|
+
* with neither executor nor `ownerAuthored` is refused. */
|
|
226
|
+
export declare function transitionGoal(ctx: ActionContext, ref: GoalRef, to: GoalState, opts?: {
|
|
227
|
+
fields?: Partial<Pick<GoalStatusValue, "checkpoint" | "cancelMode">>;
|
|
228
|
+
executor?: GoalExecutor;
|
|
229
|
+
resolveCurrentEpoch?: (target: {
|
|
230
|
+
owner: string;
|
|
231
|
+
actor: string;
|
|
232
|
+
lifecycleUid: string;
|
|
233
|
+
}) => Promise<number | null> | number | null;
|
|
234
|
+
epochResolveBudgetMs?: number;
|
|
235
|
+
/** The owner's own commit principal drives this (guard-hold pause/release): a
|
|
236
|
+
* CONSTRUCTION-BOUND {@link ownerCommitProof} from THIS context, never a raw flag. */
|
|
237
|
+
owner?: OwnerCommitProof;
|
|
238
|
+
/** THE gate's construction-bound {@link GuardClearance} - REQUIRED on a GUARDED goal's
|
|
239
|
+
* edge into `running` (SPEC 13.6 MUST-NOT-effect-until-allow; an owner proof does NOT
|
|
240
|
+
* satisfy this edge, since any context holder mints owner proofs). */
|
|
241
|
+
clearance?: GuardClearance;
|
|
242
|
+
}): Promise<GoalStatusValue>;
|
|
243
|
+
/** Project the WINNING terminal fact onto the status — the ONLY path a status reaches a terminal
|
|
244
|
+
* state, and the crash reconciler for a commit that fenced the fact but died before projecting.
|
|
245
|
+
* Cross-checks the fact's fingerprint against the persisted spec (a terminal fact whose
|
|
246
|
+
* fingerprint disagrees with the accepted goal is a garbled authority chain). */
|
|
247
|
+
export declare function projectGoalTerminal(ctx: ActionContext, ref: GoalRef): Promise<GoalStatusValue>;
|
|
248
|
+
export type GoalOutcomeState = "succeeded" | "failed" | "cancelled" | "expired" | "uncertain";
|
|
249
|
+
/** The goal's terminal fact + the §13.6 item-5 tombstone summary in one immutable artifact. */
|
|
250
|
+
export interface GoalResultFact {
|
|
251
|
+
v: 1;
|
|
252
|
+
goalId: string;
|
|
253
|
+
fingerprint: string;
|
|
254
|
+
state: GoalOutcomeState;
|
|
255
|
+
outcomeDigest: string;
|
|
256
|
+
data?: unknown;
|
|
257
|
+
ts: number;
|
|
258
|
+
}
|
|
259
|
+
/** Build the retirement-cancelled goal terminal (§13.8 option (i)): the FIRST-CLASS `cancelled`
|
|
260
|
+
* outcome state the goal union ALREADY carries — no new wire shape — bound to the acceptance's
|
|
261
|
+
* fingerprint, with the retirement attribution riding the digest-bound payload
|
|
262
|
+
* (`data.cancelledBy = { opId, target }`). Published create-only on the goal's result subject,
|
|
263
|
+
* so a racing real commit wins by landing first (first-terminal-wins, §13.8). A retirement
|
|
264
|
+
* cancels only ITS OWN target's accepted goals. */
|
|
265
|
+
export declare function goalCancelledResultOf(acceptance: {
|
|
266
|
+
fingerprint: string;
|
|
267
|
+
request: Record<string, unknown>;
|
|
268
|
+
target?: {
|
|
269
|
+
owner: string;
|
|
270
|
+
actor: string;
|
|
271
|
+
lifecycleUid: string;
|
|
272
|
+
};
|
|
273
|
+
}, cancelled: {
|
|
274
|
+
opId: string;
|
|
275
|
+
target: {
|
|
276
|
+
owner: string;
|
|
277
|
+
actor: string;
|
|
278
|
+
lifecycleUid: string;
|
|
279
|
+
};
|
|
280
|
+
}, ts: number): GoalResultFact;
|
|
281
|
+
/** The §13.6 item-5 tombstone serving form for a payload-evicted retry. */
|
|
282
|
+
export declare function goalTombstone(fact: GoalResultFact): GoalResultFact;
|
|
283
|
+
/** Closed validation, IDENTITY-BOUND to the ref, with the tombstone digest RE-VERIFIED. */
|
|
284
|
+
export declare function parseGoalResultFact(raw: unknown, subject: string, ref: GoalRef): GoalResultFact;
|
|
285
|
+
/** Read the goal's cached terminal outcome (`undefined` = not terminal yet). */
|
|
286
|
+
export declare function readGoalResult(ctx: ActionContext, ref: GoalRef): Promise<GoalResultFact | undefined>;
|
|
287
|
+
/** What receipt emission needs beyond the action context: the receipt store bonded to the SAME
|
|
288
|
+
* space AND the same connection, the EMITTING instance recorded as EVIDENCE (who produced this
|
|
289
|
+
* attestation - after a crash the reconciling instance records ITSELF here, so this is never
|
|
290
|
+
* proof of who EXECUTED the goal, and never redemption authority; the executed outcome's
|
|
291
|
+
* authority is the committed terminal fact alone), and the receipts-scoped signer + key. */
|
|
292
|
+
export interface ReceiptEmissionWiring {
|
|
293
|
+
store: ReceiptStoreContext;
|
|
294
|
+
instance: {
|
|
295
|
+
id: string;
|
|
296
|
+
instanceId: string;
|
|
297
|
+
epoch: number;
|
|
298
|
+
};
|
|
299
|
+
signer: {
|
|
300
|
+
keyId: string;
|
|
301
|
+
};
|
|
302
|
+
keyPair: {
|
|
303
|
+
sign(input: Uint8Array): Uint8Array;
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
/** One emission attempt's outcome: `emitted` (this attempt's receipt won the create-only CAS)
|
|
307
|
+
* or `converged` (a receipt already attests these facts — an earlier attempt's or a racing
|
|
308
|
+
* emitter's, ADOPTED only after it proves agreement with the facts). A recorded receipt that
|
|
309
|
+
* DISAGREES with the committed facts is a loud `conflict`, never adopted. */
|
|
310
|
+
export type ReceiptEmissionResult = {
|
|
311
|
+
outcome: "emitted" | "converged";
|
|
312
|
+
receipt: Receipt;
|
|
313
|
+
};
|
|
314
|
+
/** The durable backstop for the §13.10 MUST-emit guarantee: re-derive and publish the receipt
|
|
315
|
+
* for a goal whose terminal committed but whose emission was omitted (a crash between the
|
|
316
|
+
* terminal CAS and the publish, or a commit made without emission wiring). Reads the persisted
|
|
317
|
+
* spec and the committed terminal FRESH, then runs the SAME emission seam the inline path uses.
|
|
318
|
+
* `no-terminal` = nothing to attest yet (the goal simply is not terminal — never an error). */
|
|
319
|
+
export declare function reconcileReceiptEmission(ctx: ActionContext, wiring: ReceiptEmissionWiring, args: {
|
|
320
|
+
ref: GoalRef;
|
|
321
|
+
now: number;
|
|
322
|
+
}): Promise<ReceiptEmissionResult | {
|
|
323
|
+
outcome: "no-terminal";
|
|
324
|
+
}>;
|
|
325
|
+
/** A deny's AUTHORITATIVE PREDICATE (§13.6): a bare `deny` proves nothing, so the commit
|
|
326
|
+
* boundary requires and VERIFIES one of:
|
|
327
|
+
* - `hold-expired`: the named checkpoint's recorded spec must BIND this exact goal and its
|
|
328
|
+
* recorded one-use settlement must be `expired` (the arbiter's own fact — a live or resumed
|
|
329
|
+
* hold never denies);
|
|
330
|
+
* - `owner`: the owner's construction-bound {@link ownerCommitProof} from THIS context (a
|
|
331
|
+
* guard-verdict deny the owner itself is committing). */
|
|
332
|
+
export type GoalDenial = {
|
|
333
|
+
kind: "hold-expired";
|
|
334
|
+
token: string;
|
|
335
|
+
} | {
|
|
336
|
+
kind: "owner";
|
|
337
|
+
owner: OwnerCommitProof;
|
|
338
|
+
};
|
|
339
|
+
/** The closed terminal CAUSE (§13.6): the public commit accepts ONLY these, each with its own
|
|
340
|
+
* authoritative predicate verified inside the boundary; the terminal state is DERIVED, never a
|
|
341
|
+
* raw caller value.
|
|
342
|
+
* - `complete`: the executor's own outcome (`succeeded`|`failed`), proving fresh currency for
|
|
343
|
+
* a target-pinned goal;
|
|
344
|
+
* - `cancel`: `cancelled`, requiring the goal to be `cancelling` (a cancel was requested);
|
|
345
|
+
* - `deny`: `failed`, requiring the verified {@link GoalDenial} predicate (a bare deny cause
|
|
346
|
+
* is refused — any commit-seam holder could otherwise fail any accepted goal);
|
|
347
|
+
* - `readiness`: `uncertain`, the OWNER's deadline settlement, requiring `now` past the
|
|
348
|
+
* persisted acceptance-relative readiness deadline (no executor — a target-pinned goal's
|
|
349
|
+
* owner deadline is reachable). */
|
|
350
|
+
export type GoalCommitCause = {
|
|
351
|
+
cause: "complete";
|
|
352
|
+
state: "succeeded" | "failed";
|
|
353
|
+
data?: unknown;
|
|
354
|
+
executor?: GoalExecutor;
|
|
355
|
+
resolveCurrentEpoch?: (target: {
|
|
356
|
+
owner: string;
|
|
357
|
+
actor: string;
|
|
358
|
+
lifecycleUid: string;
|
|
359
|
+
}) => Promise<number | null> | number | null;
|
|
360
|
+
epochResolveBudgetMs?: number;
|
|
361
|
+
} | {
|
|
362
|
+
cause: "cancel";
|
|
363
|
+
data?: unknown;
|
|
364
|
+
} | {
|
|
365
|
+
cause: "deny";
|
|
366
|
+
denial: GoalDenial;
|
|
367
|
+
data?: unknown;
|
|
368
|
+
} | {
|
|
369
|
+
cause: "readiness";
|
|
370
|
+
};
|
|
371
|
+
/** Commit the goal's terminal state at the ONE mediated commit point, BOUND to the persisted
|
|
372
|
+
* accepted goal and its CAUSE (see {@link GoalCommitCause}). First terminal fact wins uniformly
|
|
373
|
+
* (completion, cancel, deny, and readiness race here); a loser observes the winner and its
|
|
374
|
+
* projection converges. Every operation input detaches at ENTRY (single-read, before the first
|
|
375
|
+
* await): a caller mutating cause/state/data/executor across the spec read changes nothing.
|
|
376
|
+
*
|
|
377
|
+
* RECEIPT EMISSION (§13.10): with `receipts` wired, the commit emits the terminal's receipt
|
|
378
|
+
* INLINE, best-effort, for the WINNING fact (won or lost — the terminal is committed either
|
|
379
|
+
* way and emission is idempotent). Invalid wiring refuses at ENTRY, before any terminal
|
|
380
|
+
* commits; a RUNTIME emission failure after the irreversible commit surfaces as
|
|
381
|
+
* `receiptEmission: { outcome: "failed" }` — it never masks the committed terminal, and
|
|
382
|
+
* {@link reconcileReceiptEmission} is the durable backstop that converges it. */
|
|
383
|
+
export declare function commitGoalResult(ctx: ActionContext, args: {
|
|
384
|
+
ref: GoalRef;
|
|
385
|
+
now: number;
|
|
386
|
+
receipts?: ReceiptEmissionWiring;
|
|
387
|
+
} & GoalCommitCause): Promise<{
|
|
388
|
+
won: boolean;
|
|
389
|
+
fact: GoalResultFact;
|
|
390
|
+
status: GoalStatusValue;
|
|
391
|
+
receiptEmission?: ReceiptEmissionResult | {
|
|
392
|
+
outcome: "failed";
|
|
393
|
+
error: EpEnvelopeError;
|
|
394
|
+
};
|
|
395
|
+
}>;
|
|
396
|
+
/** The reverse-DNS detail kind carrying a goal's cached terminal fact on an error (§13.3). */
|
|
397
|
+
export declare const GOAL_TERMINAL_DETAIL_KIND = "ai.cotal.goal.terminal";
|
|
398
|
+
/** The reserved `cancel` command's handler seam. The goal ref derives STRUCTURALLY from the
|
|
399
|
+
* broker-authenticated request (a caller cancels only its own goals). Unknown = failed-
|
|
400
|
+
* precondition; terminal = failed-precondition with the cached outcome on error.details;
|
|
401
|
+
* otherwise the status transitions to `cancelling` (owner/caller-authored — no executor) and
|
|
402
|
+
* the owner later commits the `cancel` cause. A completion that landed during the transition is
|
|
403
|
+
* observed AFTER it and converges the projection. */
|
|
404
|
+
export declare function requestGoalCancel(ctx: ActionContext, args: {
|
|
405
|
+
request: ParsedEpRequest;
|
|
406
|
+
goalId: string;
|
|
407
|
+
mode: "graceful" | "terminate";
|
|
408
|
+
}): Promise<GoalStatusValue>;
|
|
409
|
+
/** Settle a goal `uncertain` at its persisted acceptance-relative readiness deadline (the
|
|
410
|
+
* `readiness` cause). The bound is read from the PERSISTED spec; a target-pinned goal is
|
|
411
|
+
* REACHABLE (readiness is the owner's deadline, not an executor completion, so no executor is
|
|
412
|
+
* required). A racing late success that committed first wins and this returns the winner. */
|
|
413
|
+
export declare function settleGoalUncertain(ctx: ActionContext, args: {
|
|
414
|
+
ref: GoalRef;
|
|
415
|
+
now: number;
|
|
416
|
+
}): Promise<{
|
|
417
|
+
won: boolean;
|
|
418
|
+
fact: GoalResultFact;
|
|
419
|
+
status: GoalStatusValue;
|
|
420
|
+
}>;
|
|
421
|
+
/** Classify a resubmission against the recorded bind: same fingerprint = retry (cached), else
|
|
422
|
+
* `conflict`. {@link resolveGoalSubmission} composes this with the orphaned-bind recovery. */
|
|
423
|
+
export declare function classifyGoalReuse(existing: GoalBindFact, submittedFingerprint: string): "cached" | "conflict";
|
|
424
|
+
//# sourceMappingURL=endpoint-action.d.ts.map
|