@cotal-ai/auth 0.56.1 → 0.58.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/dist/auth-admin.d.ts +10 -0
- package/dist/auth-admin.d.ts.map +1 -1
- package/dist/auth-admin.js +162 -213
- package/dist/auth-admin.js.map +1 -1
- package/dist/auth-service-contract.d.ts +64 -0
- package/dist/auth-service-contract.d.ts.map +1 -0
- package/dist/auth-service-contract.js +131 -0
- package/dist/auth-service-contract.js.map +1 -0
- package/dist/authority-client.d.ts +16 -0
- package/dist/authority-client.d.ts.map +1 -1
- package/dist/authority-client.js +61 -1
- package/dist/authority-client.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/manager-authority.d.ts +102 -1
- package/dist/manager-authority.d.ts.map +1 -1
- package/dist/manager-authority.js +276 -16
- package/dist/manager-authority.js.map +1 -1
- package/dist/manager-contract.d.ts +4 -0
- package/dist/manager-contract.d.ts.map +1 -1
- package/dist/manager-contract.js +7 -1
- package/dist/manager-contract.js.map +1 -1
- package/dist/provider.d.ts.map +1 -1
- package/dist/provider.js +8 -0
- package/dist/provider.js.map +1 -1
- package/dist/service.d.ts +68 -1
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +572 -149
- package/dist/service.js.map +1 -1
- package/package.json +6 -6
package/dist/auth-admin.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type EpServeGrant } from "@cotal-ai/core";
|
|
1
2
|
import { runAgentRetirementBarrier, type RetirementDeps } from "./retirement-barrier.js";
|
|
2
3
|
import { type LifecycleRegistry } from "./lifecycle-registry.js";
|
|
3
4
|
/** The LISTENER profile (SPEC 13.9 "Auth endpoint rail" row): serve + bounded replies on the auth
|
|
@@ -42,6 +43,15 @@ export declare function openAuthAdminListener(opts: {
|
|
|
42
43
|
reg: LifecycleRegistry;
|
|
43
44
|
retirement: RetirementDeps;
|
|
44
45
|
barrierFlight: RetirementFlights;
|
|
46
|
+
/** The plane's #399 M2-registered instance id and current process epoch (`authServeGrant.epoch`)
|
|
47
|
+
* — the SAME instance/epoch the registration ceremony fenced. The gate's process-epoch reader is
|
|
48
|
+
* the fence now; there is no separate fixed responder identity to mint. */
|
|
49
|
+
instanceId: string;
|
|
50
|
+
epoch: number;
|
|
51
|
+
/** The M2-authorized serve artifact for this instance/epoch (`authServeGrant`, `service.ts:513`)
|
|
52
|
+
* — `serveEndpoint` consumes it directly; it is the ONE authority source for what this
|
|
53
|
+
* credential may serve (SPEC 13.9). */
|
|
54
|
+
grant: EpServeGrant;
|
|
45
55
|
log: (line: string) => void;
|
|
46
56
|
}): Promise<AuthAdminListener>;
|
|
47
57
|
//# sourceMappingURL=auth-admin.d.ts.map
|
package/dist/auth-admin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-admin.d.ts","sourceRoot":"","sources":["../src/auth-admin.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"auth-admin.d.ts","sourceRoot":"","sources":["../src/auth-admin.ts"],"names":[],"mappings":"AAkDA,OAAO,EAYL,KAAK,YAAY,EAElB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EAAE,yBAAyB,EAAE,KAAK,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzF,OAAO,EAA8C,KAAK,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAE7G;;gEAEgE;AAChE,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,SAAS,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC/C;IAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,SAAS,EAAE,MAAM,EAAE,CAAA;CAAE,CAuB5C;AAeD;;iFAEiF;AACjF,wBAAgB,4BAA4B,CAAC,kBAAkB,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAI3F;AAED,0FAA0F;AAC1F,MAAM,MAAM,iBAAiB,GAAG,GAAG,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,UAAU,CAAC,OAAO,yBAAyB,CAAC,CAAA;CAAE,CAAC,CAAC;AAE3J;mGACmG;AACnG,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,iBAAiB,EAC1B,GAAG,EAAE,iBAAiB,EACtB,EAAE,EAAE,UAAU,CAAC,OAAO,yBAAyB,CAAC,CAAC,CAAC,CAAC,EACnD,UAAU,EAAE,cAAc,GACzB,UAAU,CAAC,OAAO,yBAAyB,CAAC,GAAG,SAAS,CAQ1D;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE;IAChD,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IAClD,GAAG,EAAE,iBAAiB,CAAC;IACvB,UAAU,EAAE,cAAc,CAAC;IAC3B,aAAa,EAAE,iBAAiB,CAAC;IACjC;;gFAE4E;IAC5E,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd;;4CAEwC;IACxC,KAAK,EAAE,YAAY,CAAC;IACpB,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA6I7B"}
|
package/dist/auth-admin.js
CHANGED
|
@@ -1,29 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The AUTH service's ENDPOINT listener (#29 piece 3; Cotal #350): the GENERIC "retire a lifecycle
|
|
3
|
+
* (owner, actor, lifecycleUid)" operation, served by the auth plane itself — the despawn→retirement
|
|
4
|
+
* trigger's serve side, and the D5 split's other half (retirement is the AUTH plane's operation; it
|
|
5
|
+
* never rides the DELIVERY daemon's rail).
|
|
6
|
+
*
|
|
7
|
+
* THE RAIL: `ep.one.auth.retire-lifecycle.handle.<tO>.<tA>.<tUid>.<cO>.<cA>.<cUid>.<nonce>`.
|
|
8
|
+
* It used to serve on `ctl.auth-admin.<owner>.<actor>`. §13.11 retires the v0 `ctl` rail in full
|
|
9
|
+
* ("MUST NOT be handled") and grants it no scoping language, so the rows serving this rail there
|
|
10
|
+
* were defects — new normative rows written onto a deleted rail — and #350 ruled them rewritten
|
|
11
|
+
* onto the v0.4 endpoint surface rather than carved out of the cut.
|
|
12
|
+
*
|
|
13
|
+
* AUTHZ (RAIL-TIME, fresh per request, never mint-only):
|
|
14
|
+
* - Caller attribution is SUBJECT-derived and broker-enforced: the caller triple
|
|
15
|
+
* `<cO>.<cA>.<cUid>` rides the subject, and only a credential minted with that triple's
|
|
16
|
+
* request-publish grant can reach it (the `retirement-requester` profile).
|
|
17
|
+
* - The SERVE-ISSUANCE GATE check: the caller names a gate row by (serveEndpoint,
|
|
18
|
+
* serveInstanceId) and declares its epoch. The row must exist, not be retired, and carry the
|
|
19
|
+
* declared epoch — a superseded predecessor (a restart advanced the epoch) is refused.
|
|
20
|
+
* - THE PRINCIPAL CROSS-CHECK: the named row's `principal` must equal the SUBJECT-derived caller
|
|
21
|
+
* principal. This is what makes the two body fields safe to keep: they only SELECT a row, they
|
|
22
|
+
* no longer authorize, so naming a foreign row buys a refusal rather than an authorization.
|
|
23
|
+
* Before #350 the two-token `ctl` subject could not express the caller's identity beyond an
|
|
24
|
+
* alias, and the rail accepted ANY registered instance's gate — a holder of the manager
|
|
25
|
+
* principal could be authorized by a row belonging to someone else.
|
|
26
|
+
* - This is ALIAS-LEVEL binding, not incarnation-level: the gate row is keyed by the PERSISTED
|
|
27
|
+
* `instanceId` (stable across restarts) and its schema is closed with no uid field, while the
|
|
28
|
+
* caller triple's `<cUid>` is per-process. A same-principal zombie predecessor that learns the
|
|
29
|
+
* current epoch value still passes both checks. Binding the publishing incarnation needs a
|
|
30
|
+
* gate-row schema change — deliberately out of this cut, and its own decision.
|
|
31
|
+
* - The GENERIC surface never names a caller class (a manager despawn is ONE caller); the gate
|
|
32
|
+
* check is this service's serve-time authz, not subject grammar.
|
|
33
|
+
*
|
|
34
|
+
* IDEMPOTENCE (the confirmed four-outcome table, surfaced as OPERATOR results): already-retired
|
|
35
|
+
* (uid match) → success; a frozen gate under the SAME opId → the barrier resumes it; a FOREIGN
|
|
36
|
+
* operation holding the gate → refuse naming the operation; a different current uid → refuse
|
|
37
|
+
* (stale trigger). The requester sends a STABLE opId across retries, so an epCall retry never
|
|
38
|
+
* mints a second operation.
|
|
39
|
+
*
|
|
40
|
+
* UX (the piece-3 faces): every refusal is WHAT/WHY/NEXT in operator vocabulary — each authz
|
|
41
|
+
* refusal states the despawn was a FULL NO-OP (the target is unchanged and still running,
|
|
42
|
+
* nothing was applied) with `cotal supervise` → retry as the NEXT; the vocabulary bridge
|
|
43
|
+
* ("despawn started this agent's retirement") lives at the CLI surface that renders these.
|
|
44
|
+
*
|
|
45
|
+
* SEAL COMPOSITION (critic's three checks): the listener holds NO scanner/plane authority — the
|
|
46
|
+
* retirement runs through the injected {@link RetirementDeps}, whose drain rides the plane's ONE
|
|
47
|
+
* sealed records scanner exactly like the boot resume; the gate read is a leader read, no
|
|
48
|
+
* consumer-create anywhere; the requester credential is request + reply-inbox ONLY.
|
|
49
|
+
*/
|
|
1
50
|
import { Kvm } from "@nats-io/kv";
|
|
2
|
-
import { AUTH_ENDPOINT, EP_CMD_RETIRE_LIFECYCLE, EpEnvelopeError,
|
|
51
|
+
import { AUTH_ENDPOINT, EP_CMD_RETIRE_LIFECYCLE, EpEnvelopeError, epAuthBucket, epServeGrantRows, managedRetirementOpId, principalKey, retirementFrontierStreams, serveEndpoint, serveIssuanceGateKv, } from "@cotal-ai/core";
|
|
52
|
+
import { authCommandDefs } from "./auth-service-contract.js";
|
|
3
53
|
import { openAuthorityClient } from "./authority-client.js";
|
|
4
54
|
import { runAgentRetirementBarrier } from "./retirement-barrier.js";
|
|
5
55
|
import { observeGate, readLifecycleHeadForOperation } from "./lifecycle-registry.js";
|
|
6
|
-
const enc = new TextEncoder();
|
|
7
|
-
const dec = new TextDecoder();
|
|
8
|
-
/** The auth endpoint's one class rail, per-command (never a cross-command `>`): the grant and the
|
|
9
|
-
* runtime subscription are built from THIS, so a widened subscription cannot outrun its grant. */
|
|
10
|
-
function authClassRail(space) {
|
|
11
|
-
return `${spacePrefix(space)}.ep.one.${endpointToken(AUTH_ENDPOINT)}.${assertCommandToken(EP_CMD_RETIRE_LIFECYCLE)}.>`;
|
|
12
|
-
}
|
|
13
56
|
/** The LISTENER profile (SPEC 13.9 "Auth endpoint rail" row): serve + bounded replies on the auth
|
|
14
57
|
* endpoint's class rail, plus the ONE leader-served gate read the authz check performs.
|
|
15
58
|
* No store writes, no consumer authority, no scanner reach. */
|
|
16
59
|
export function authAdminListenerGrants(space, connId, responder) {
|
|
60
|
+
// The generic serve rows for this instance/epoch (reply plane, events, timer schedule, record
|
|
61
|
+
// writes on publish; the class/all/inst rails plus the derived `describe` and the epoch-pinned
|
|
62
|
+
// timer fire row on subscribe) — the SAME assembly `serveEndpoint` callers use, replacing the
|
|
63
|
+
// hand-built reply-pattern/class-rail rows above (M3, #399).
|
|
64
|
+
const serveRows = epServeGrantRows(space, {
|
|
65
|
+
endpoint: AUTH_ENDPOINT,
|
|
66
|
+
instanceId: responder.instanceId,
|
|
67
|
+
epoch: responder.epoch,
|
|
68
|
+
ephemeralCommands: [EP_CMD_RETIRE_LIFECYCLE],
|
|
69
|
+
});
|
|
17
70
|
return {
|
|
18
71
|
publish: [
|
|
19
|
-
|
|
20
|
-
// could make. There, request and reply shared one subtree, so the grant had to carve replies
|
|
21
|
-
// out of it by shape (`*.*.reply.>`) to stop a compromised listener self-publishing a request
|
|
22
|
-
// as the lease holder and passing its own subject-derived check (self-forge). Here the planes
|
|
23
|
-
// are DISJOINT: `ep.reply.…` cannot express a request subject at all, so the self-forge is
|
|
24
|
-
// closed by the grammar rather than by a pattern. The instance triple and epoch are pinned;
|
|
25
|
-
// only the caller suffixes span (addressing is confined by nonce possession, §13.2).
|
|
26
|
-
epResponderReplyPattern(space, AUTH_ENDPOINT, responder.instanceId, responder.epoch),
|
|
72
|
+
...serveRows.pub,
|
|
27
73
|
"$JS.API.INFO",
|
|
28
74
|
// The ONE leader-served read the authz check performs: the serve-issuance GATE, a point-get
|
|
29
75
|
// of `epgate.<endpoint>.<instanceId>` proving the requesting manager instance's serve grant
|
|
@@ -31,52 +77,7 @@ export function authAdminListenerGrants(space, connId, responder) {
|
|
|
31
77
|
// authority, no store writes.
|
|
32
78
|
`$JS.API.STREAM.MSG.GET.KV_${epAuthBucket(space)}`,
|
|
33
79
|
],
|
|
34
|
-
|
|
35
|
-
// NATS `"<subject> <queue>"` grant form. A PLAIN subject row would let this credential
|
|
36
|
-
// plain-subscribe the class rail and observe EVERY request's nonce — the property the queue
|
|
37
|
-
// qualification exists to protect. The runtime's queue subscription is not a substitute: it
|
|
38
|
-
// constrains what this process does, not what the credential permits.
|
|
39
|
-
subscribe: [`${authClassRail(space)} ${epClassQueueGroup(AUTH_ENDPOINT)}`, `_INBOX_${connId}.>`],
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
const RETIRE_ARG_KEYS = ["opId", "serveEndpoint", "serveInstanceId", "serveEpoch"];
|
|
43
|
-
/** The request id a reply MUST echo. This is the MINIMAL correctness guard from the full
|
|
44
|
-
* `EndpointRequest`/`EndpointReply` envelope, which this rail does NOT yet carry (named residual:
|
|
45
|
-
* the rail moved to `ep` SUBJECTS while still exchanging the ctl-era `{op,args}` / `{ok,data,error}`
|
|
46
|
-
* bodies, and SPEC 1421 states those envelopes are DELETED). Without the echo, a caller binding a
|
|
47
|
-
* reply on (endpoint, nonce) alone can accept a malformed or WRONG-ID `{ok:true}` and clear a
|
|
48
|
-
* retirement hold on it. The full envelope migration is its own cut; this edge is not deferrable. */
|
|
49
|
-
function parseRequestId(raw) {
|
|
50
|
-
if (typeof raw !== "string" || !/^[A-Za-z0-9_-]{1,64}$/.test(raw))
|
|
51
|
-
throw new EpEnvelopeError("failed-precondition", `the request requires an "id" ([A-Za-z0-9_-]{1,64}); the reply echoes it so a caller cannot accept another request's answer`);
|
|
52
|
-
return raw;
|
|
53
|
-
}
|
|
54
|
-
function parseRetireArgs(raw) {
|
|
55
|
-
const shape = "{ opId, serveEndpoint, serveInstanceId, serveEpoch }";
|
|
56
|
-
if (raw === null || typeof raw !== "object")
|
|
57
|
-
throw new EpEnvelopeError("failed-precondition", `retireLifecycle requires args ${shape}`);
|
|
58
|
-
const a = raw;
|
|
59
|
-
// The TARGET (owner, actor, lifecycleUid) is no longer an argument: `handle` mode carries it in
|
|
60
|
-
// the subject, broker-enforced and grant-pinned, so the handler reads it from there. Sending it
|
|
61
|
-
// in the body is now a CLOSED-SHAPE violation rather than a redundancy to reconcile — which
|
|
62
|
-
// removes the whole body-vs-subject mismatch class instead of managing it.
|
|
63
|
-
for (const k of Object.keys(a))
|
|
64
|
-
if (!RETIRE_ARG_KEYS.includes(k))
|
|
65
|
-
throw new EpEnvelopeError("failed-precondition", `retireLifecycle args carry the unknown field "${k}" (closed shape; the target rides the SUBJECT)`);
|
|
66
|
-
if (typeof a.opId !== "string" ||
|
|
67
|
-
typeof a.serveEndpoint !== "string" || typeof a.serveInstanceId !== "string" ||
|
|
68
|
-
typeof a.serveEpoch !== "number" || !Number.isInteger(a.serveEpoch) || a.serveEpoch < 0)
|
|
69
|
-
throw new EpEnvelopeError("failed-precondition", `retireLifecycle requires args ${shape} (serveEpoch a non-negative integer)`);
|
|
70
|
-
return {
|
|
71
|
-
// opId is OPERATION IDENTITY, not an authz input: the terminal rail independently derives it
|
|
72
|
-
// from the broker-pinned lifecycle target below. This parse only enforces the token grammar.
|
|
73
|
-
opId: assertLifecycleToken(a.opId, "opId"),
|
|
74
|
-
// LOOKUP COORDINATES, not authz inputs: they select WHICH gate row to read. The row they
|
|
75
|
-
// select must then survive the principal cross-check below, so naming a foreign row buys a
|
|
76
|
-
// refusal, never an authorization.
|
|
77
|
-
serveEndpoint: endpointToken(a.serveEndpoint),
|
|
78
|
-
serveInstanceId: assertLifecycleToken(a.serveInstanceId, "serveInstanceId"),
|
|
79
|
-
serveEpoch: a.serveEpoch,
|
|
80
|
+
subscribe: [...serveRows.sub, `_INBOX_${connId}.>`],
|
|
80
81
|
};
|
|
81
82
|
}
|
|
82
83
|
/** The terminal rail's operation-identity authorization. The requester credential pins the target
|
|
@@ -106,13 +107,11 @@ export function joinOrStartRetirement(flights, reg, op, retirement) {
|
|
|
106
107
|
*/
|
|
107
108
|
export async function openAuthAdminListener(opts) {
|
|
108
109
|
const { space, log } = opts;
|
|
109
|
-
// The auth plane's responder identity
|
|
110
|
-
//
|
|
111
|
-
//
|
|
112
|
-
//
|
|
113
|
-
|
|
114
|
-
// positions (`ep.reply.*.*.*.<cO>.<cA>.<cUid>.*`), so they never need to learn it.
|
|
115
|
-
const responder = { instanceId: mintLifecycleUid(), epoch: 0 };
|
|
110
|
+
// The auth plane's responder identity is the #399 M2-registered instance/epoch (the SAME triple
|
|
111
|
+
// `registerServiceInstance` fenced and `authorizeServeGrant` minted a serve grant for). The reply
|
|
112
|
+
// plane pins this triple in the grant; callers read replies through a filter that wildcards the
|
|
113
|
+
// caller-suffix positions (`ep.reply.*.*.*.<cO>.<cA>.<cUid>.*`), so they never need to learn it.
|
|
114
|
+
const responder = { instanceId: opts.instanceId, epoch: opts.epoch };
|
|
116
115
|
const client = await openAuthorityClient({
|
|
117
116
|
server: opts.server, space, dataAccount: opts.dataAccount,
|
|
118
117
|
label: `cotal:auth-admin:${space}`,
|
|
@@ -129,56 +128,6 @@ export async function openAuthAdminListener(opts) {
|
|
|
129
128
|
await client.close();
|
|
130
129
|
throw e;
|
|
131
130
|
}
|
|
132
|
-
const sub = client.nc.subscribe(authClassRail(space), {
|
|
133
|
-
queue: epClassQueueGroup(AUTH_ENDPOINT),
|
|
134
|
-
callback: (err, msg) => {
|
|
135
|
-
if (err)
|
|
136
|
-
return;
|
|
137
|
-
void (async () => {
|
|
138
|
-
// The reply target is DERIVED from the parsed request, never taken from the wire. On the
|
|
139
|
-
// `ctl` rail this was a guard: the listener held a subtree-wide reply grant, so a
|
|
140
|
-
// caller-selected foreign reply target had to be refused by inspecting `msg.reply`. Here
|
|
141
|
-
// there is no argument through which a payload-supplied reply target could arrive — the
|
|
142
|
-
// guard became structural, so the check it replaced cannot be forgotten.
|
|
143
|
-
const parsed = parseEpSubject(msg.subject);
|
|
144
|
-
if (parsed === null || parsed.plane !== "request") {
|
|
145
|
-
// null = MUST NOT handle (§13.2). Never a reply: an unparseable subject has no
|
|
146
|
-
// derivable reply target, and answering one would be the confused deputy itself.
|
|
147
|
-
log(`auth-admin: dropped an unparseable request subject ${msg.subject}`);
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
const request = parsed;
|
|
151
|
-
// The echoed id is stamped HERE, outside the handler, so EVERY reply carries it - including
|
|
152
|
-
// the thrown-error path. A reply the caller cannot bind to its own request is one it must
|
|
153
|
-
// ignore, so an unstamped error reply would silently become a timeout instead of a refusal.
|
|
154
|
-
let echoId;
|
|
155
|
-
try {
|
|
156
|
-
echoId = parseRequestId(JSON.parse(dec.decode(msg.data)).id);
|
|
157
|
-
}
|
|
158
|
-
catch {
|
|
159
|
-
echoId = undefined;
|
|
160
|
-
}
|
|
161
|
-
let reply;
|
|
162
|
-
try {
|
|
163
|
-
reply = await handle(request, msg.data);
|
|
164
|
-
}
|
|
165
|
-
catch (e) {
|
|
166
|
-
reply = { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
167
|
-
}
|
|
168
|
-
// A request with no usable id gets an unbindable reply BY CONSTRUCTION: the caller requires
|
|
169
|
-
// the echo, so it will refuse this answer rather than accept an unattributable one.
|
|
170
|
-
if (echoId !== undefined)
|
|
171
|
-
reply.id = echoId;
|
|
172
|
-
const target = deriveReplySubject(space, request, responder);
|
|
173
|
-
try {
|
|
174
|
-
client.nc.publish(target, enc.encode(JSON.stringify(reply)));
|
|
175
|
-
}
|
|
176
|
-
catch (e) {
|
|
177
|
-
log(`auth-admin: reply publish failed on ${target}: ${e instanceof Error ? e.message : String(e)}`);
|
|
178
|
-
}
|
|
179
|
-
})();
|
|
180
|
-
},
|
|
181
|
-
});
|
|
182
131
|
// SINGLE-FLIGHT the barrier EXECUTION per opId (audit #1): each request still runs its OWN fresh
|
|
183
132
|
// lease re-check + idempotence, but concurrent same-opId requests (a manager nudge + a retry, or a boot
|
|
184
133
|
// resume racing the rail) share ONE runAgentRetirementBarrier, so the barrier body never dual-executes
|
|
@@ -190,103 +139,103 @@ export async function openAuthAdminListener(opts) {
|
|
|
190
139
|
// Owned by the plane and shared with the loopback managed-retire door, so the rail and the door
|
|
191
140
|
// never run two barrier executions of one opId in this process (#2070).
|
|
192
141
|
const barrierFlight = opts.barrierFlight;
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
if (request.target === null || request.target.mode !== "handle")
|
|
199
|
-
return { ok: false, error: `retire-lifecycle requires a handle target (<owner>.<actor>.<lifecycleUid>) in the subject` };
|
|
200
|
-
const target = { owner: request.target.tOwner, actor: request.target.tActor, lifecycleUid: request.target.tUid };
|
|
201
|
-
// The CALLER principal likewise comes from the subject, and is now an AUTHZ INPUT (the
|
|
202
|
-
// cross-check below), not just the audit line it was on the `ctl` rail.
|
|
203
|
-
const requester = principalKey(request.caller.owner, request.caller.actor).key;
|
|
204
|
-
let req;
|
|
205
|
-
try {
|
|
206
|
-
req = JSON.parse(dec.decode(body));
|
|
207
|
-
}
|
|
208
|
-
catch {
|
|
209
|
-
return { ok: false, error: "auth-admin: the request body is not JSON" };
|
|
210
|
-
}
|
|
211
|
-
if (req.op !== "retireLifecycle")
|
|
212
|
-
return { ok: false, error: `op "${String(req.op)}" not supported on the auth admin service` };
|
|
213
|
-
const args = parseRetireArgs(req.args);
|
|
214
|
-
// TARGET comes from the broker-authorized subject. Bind the body's opId to it BEFORE the serve
|
|
215
|
-
// gate, lifecycle head, intent, or barrier is touched, so mint-time validation is not the only
|
|
216
|
-
// fence and the same target can never start a second durable terminal operation.
|
|
217
|
-
authorizeRetirementOperation(target.lifecycleUid, args.opId);
|
|
218
|
-
// THE RAIL-TIME REGISTRATION RE-CHECK (fresh, leader-served, fail-closed) — P2 item 3 (3b-3):
|
|
219
|
-
// the requesting manager instance's SERVE GRANT must be current. Read the serve-issuance gate
|
|
220
|
-
// (registration-record-derived, REPLACING the old name-derived manager-lease holder check): the
|
|
221
|
-
// requester declares its (serveEndpoint, serveInstanceId, serveEpoch); an absent/retired gate means
|
|
222
|
-
// no registered instance, and a gate whose current processEpoch moved past the declared one means
|
|
223
|
-
// the requester was SUPERSEDED (a deposed predecessor after a restart) — refused as a full no-op.
|
|
224
|
-
// The row this NAMES must also BELONG to the subject-derived caller principal (the cross-check
|
|
225
|
-
// below). Before #350 it did not have to: every instance of one space shares the manager
|
|
226
|
-
// principal, and the two-token `ctl` subject could not express the caller beyond that alias, so
|
|
227
|
-
// any current instance's gate authorized. That is no longer true, and the coordinates above no
|
|
228
|
-
// longer authorize — they only select which row to read.
|
|
229
|
-
// ALIAS-LEVEL, not incarnation-level: a DIFFERENT INSTANCE OF THE SAME PRINCIPAL still passes
|
|
230
|
-
// (the gate is keyed by the persisted instanceId and its row carries no lifecycle uid). What is
|
|
231
|
-
// refused is a row belonging to a DIFFERENT PRINCIPAL.
|
|
232
|
-
let serveGate;
|
|
233
|
-
try {
|
|
234
|
-
serveGate = await serveIssuanceGateKv(epAuthKv, space, { endpoint: args.serveEndpoint, instanceId: args.serveInstanceId }).observe();
|
|
235
|
-
}
|
|
236
|
-
catch (e) {
|
|
237
|
-
return { ok: false, error: `the retirement request cannot be authorized right now: the manager serve-issuance gate could not be read (${e instanceof Error ? e.message : String(e)}). Nothing was applied - the agent is unchanged. NEXT: check the broker and retry the despawn.` };
|
|
238
|
-
}
|
|
239
|
-
if (serveGate === null || serveGate.state === "retired")
|
|
240
|
-
return { ok: false, error: `no manager instance currently holds a serve registration for "${space}" (instance ${args.serveInstanceId} is ${serveGate === null ? "unregistered" : "retired"}), so nothing may retire agents. The despawn was a FULL no-op - the agent is unchanged and still running. NEXT: start or recover the manager (\`cotal supervise\`), then retry the despawn.` };
|
|
241
|
-
// THE PRINCIPAL CROSS-CHECK (#350). The two serve coordinates above only SELECTED this row;
|
|
242
|
-
// they do not authorize. The row must belong to the SUBJECT-derived caller principal — which
|
|
243
|
-
// the broker enforced when it admitted the publish. Without this, naming any currently
|
|
244
|
-
// registered instance's row authorizes the caller, which is what the `ctl` rail did: its
|
|
245
|
-
// two-token subject could not express the caller beyond an alias, so there was nothing to
|
|
246
|
-
// compare the row against.
|
|
247
|
-
// ALIAS-LEVEL, not incarnation-level: the gate is keyed by the PERSISTED instanceId and its
|
|
248
|
-
// schema carries no uid, while the caller triple's uid is per-process. A same-principal zombie
|
|
249
|
-
// predecessor holding the current epoch value still passes. Closing that needs a gate-row
|
|
250
|
-
// schema change; it is deliberately not in this cut.
|
|
251
|
-
if (serveGate.principal !== requester)
|
|
252
|
-
return { ok: false, error: `the retirement request was REFUSED: the serve registration named (${args.serveEndpoint}/${args.serveInstanceId}) belongs to ${serveGate.principal}, not to the requesting principal ${requester}. A caller may only be authorized by its OWN serve registration. The despawn was a FULL no-op - the agent is unchanged and still running. NEXT: name your OWN principal's serve registration (any current instance of ${requester} will do), or call as the principal that owns this one.` };
|
|
253
|
-
if (serveGate.processEpoch !== args.serveEpoch)
|
|
254
|
-
return { ok: false, error: `the requesting manager instance ${args.serveInstanceId} was SUPERSEDED (it registered at epoch ${args.serveEpoch}, the current serve grant is epoch ${serveGate.processEpoch}), so this despawn was REFUSED as a FULL no-op - the agent is unchanged and still running, nothing was torn down. NEXT: recover the manager (\`cotal supervise\`), then retry the despawn under the current serving instance.` };
|
|
255
|
-
// IDEMPOTENCE (the four-outcome table, in operator vocabulary).
|
|
256
|
-
const head = await readLifecycleHeadForOperation(opts.reg, target.owner, target.actor);
|
|
257
|
-
if (head === undefined)
|
|
258
|
-
return { ok: false, error: `no lifecycle exists for "${target.owner}/${target.actor}"; there is nothing to retire.` };
|
|
259
|
-
if (head.mapping.state === "retired" && head.mapping.lifecycleUid === target.lifecycleUid)
|
|
260
|
-
return { ok: true, data: { alreadyRetired: true, lifecycleUid: target.lifecycleUid } };
|
|
261
|
-
if (head.mapping.lifecycleUid !== target.lifecycleUid)
|
|
262
|
-
return { ok: false, error: `the despawn names a stale incarnation of "${target.owner}/${target.actor}" (current is ${head.mapping.lifecycleUid}); nothing was retired. NEXT: refresh the agent list and retry against the current incarnation.` };
|
|
263
|
-
const gate = await observeGate(opts.reg, target.lifecycleUid);
|
|
264
|
-
if (gate !== undefined && gate.row.state === "frozen" && gate.row.op !== undefined && gate.row.op.opId !== args.opId)
|
|
265
|
-
return { ok: false, error: `another operation (${gate.row.op.kind} ${gate.row.op.opId}) already holds "${target.owner}/${target.actor}"; this despawn did not start a second one. NEXT: wait for that operation to finish (or its resume on the next auth-service boot), then retry.` };
|
|
266
|
-
// EXECUTE (create-or-resume: the barrier's own freeze CAS + durable intent make the same
|
|
267
|
-
// opId resumable and a re-request idempotent). The drain, cleaner, and repair credentials
|
|
268
|
-
// all come from the plane's reviewed deps - this listener holds none of those rights.
|
|
269
|
-
const existing = barrierFlight.get(args.opId);
|
|
270
|
-
// A despawn cannot know the target's pool work, and the barrier never takes a pool hint: it
|
|
271
|
-
// DISCOVERS the real (endpoint, pools) cleaner inventory from the target's own accepted pool
|
|
272
|
-
// obligations (#F). Discovery is never a gap - the barrier never closes a frontier over
|
|
273
|
-
// un-cleaned accepted pool work (SPEC 13.1/13.9).
|
|
274
|
-
const flight = joinOrStartRetirement(barrierFlight, opts.reg, {
|
|
275
|
-
owner: target.owner, actor: target.actor, lifecycleUid: target.lifecycleUid, opId: args.opId,
|
|
276
|
-
frontierStreams: retirementFrontierStreams(space),
|
|
277
|
-
}, opts.retirement);
|
|
278
|
-
if (flight === undefined)
|
|
279
|
-
return { ok: false, error: `operation id ${args.opId} is already in flight for a different lifecycle (${existing?.owner}/${existing?.actor} ${existing?.lifecycleUid}); this despawn of "${target.owner}/${target.actor}" (${target.lifecycleUid}) was a FULL no-op - nothing was retired and it is still running. NEXT: retry the despawn (the manager derives a distinct operation id per lifecycle).` };
|
|
280
|
-
const result = await flight;
|
|
281
|
-
log(`auth-admin: retired ${target.owner}/${target.actor} (${target.lifecycleUid}) by despawn request from ${requester} (op ${args.opId})`);
|
|
282
|
-
return { ok: true, data: { retired: true, lifecycleUid: target.lifecycleUid, opId: result.opId, evictedPrincipals: result.evictedPrincipals } };
|
|
142
|
+
// The FRESH target resolver (§13.3/§13.9) for the `exact`-mode `retire-lifecycle` target: the
|
|
143
|
+
// lifecycle registry's own leader-served mapping read is the current-mapping authority.
|
|
144
|
+
const resolveTarget = async (t) => {
|
|
145
|
+
const head = await readLifecycleHeadForOperation(opts.reg, t.owner, t.actor);
|
|
146
|
+
return head === undefined ? undefined : { lifecycleUid: head.mapping.lifecycleUid, mappingRevision: head.revision };
|
|
283
147
|
};
|
|
284
|
-
|
|
285
|
-
|
|
148
|
+
const handlers = {
|
|
149
|
+
retireLifecycle: async (ctx) => {
|
|
150
|
+
// The TARGET comes from the subject (`exact` mode, arity 3) — broker-enforced and
|
|
151
|
+
// grant-pinned, not a claim the caller can vary independently of what it may publish.
|
|
152
|
+
const t = ctx.subject.target;
|
|
153
|
+
if (t === null || t.mode !== "exact")
|
|
154
|
+
throw new EpEnvelopeError("failed-precondition", `retire-lifecycle requires an exact target (<owner>.<actor>.<lifecycleUid>) in the subject`);
|
|
155
|
+
const target = { owner: t.tOwner, actor: t.tActor, lifecycleUid: t.tUid };
|
|
156
|
+
// The CALLER principal likewise comes from the subject, and is an AUTHZ INPUT (the
|
|
157
|
+
// cross-check below), not just an audit line.
|
|
158
|
+
const requester = principalKey(ctx.subject.caller.owner, ctx.subject.caller.actor).key;
|
|
159
|
+
const args = ctx.request.args;
|
|
160
|
+
// TARGET comes from the broker-authorized subject. Bind the body's opId to it BEFORE the
|
|
161
|
+
// serve gate, lifecycle head, intent, or barrier is touched, so mint-time validation is not
|
|
162
|
+
// the only fence and the same target can never start a second durable terminal operation.
|
|
163
|
+
authorizeRetirementOperation(target.lifecycleUid, args.opId);
|
|
164
|
+
// THE RAIL-TIME REGISTRATION RE-CHECK (fresh, leader-served, fail-closed) — P2 item 3 (3b-3):
|
|
165
|
+
// the requesting manager instance's SERVE GRANT must be current. Read the serve-issuance gate
|
|
166
|
+
// (registration-record-derived, REPLACING the old name-derived manager-lease holder check): the
|
|
167
|
+
// requester declares its (serveEndpoint, serveInstanceId, serveEpoch); an absent/retired gate means
|
|
168
|
+
// no registered instance, and a gate whose current processEpoch moved past the declared one means
|
|
169
|
+
// the requester was SUPERSEDED (a deposed predecessor after a restart) — refused as a full no-op.
|
|
170
|
+
// The row this NAMES must also BELONG to the subject-derived caller principal (the cross-check
|
|
171
|
+
// below). Before #350 it did not have to: every instance of one space shares the manager
|
|
172
|
+
// principal, and the two-token `ctl` subject could not express the caller beyond that alias, so
|
|
173
|
+
// any current instance's gate authorized. That is no longer true, and the coordinates above no
|
|
174
|
+
// longer authorize — they only select which row to read.
|
|
175
|
+
// ALIAS-LEVEL, not incarnation-level: a DIFFERENT INSTANCE OF THE SAME PRINCIPAL still passes
|
|
176
|
+
// (the gate is keyed by the persisted instanceId and its row carries no lifecycle uid). What is
|
|
177
|
+
// refused is a row belonging to a DIFFERENT PRINCIPAL.
|
|
178
|
+
let serveGate;
|
|
286
179
|
try {
|
|
287
|
-
|
|
180
|
+
serveGate = await serveIssuanceGateKv(epAuthKv, space, { endpoint: args.serveEndpoint, instanceId: args.serveInstanceId }).observe();
|
|
181
|
+
}
|
|
182
|
+
catch (e) {
|
|
183
|
+
throw new EpEnvelopeError("unavailable", `the retirement request cannot be authorized right now: the manager serve-issuance gate could not be read (${e instanceof Error ? e.message : String(e)}). Nothing was applied - the agent is unchanged. NEXT: check the broker and retry the despawn.`);
|
|
288
184
|
}
|
|
289
|
-
|
|
185
|
+
if (serveGate === null || serveGate.state === "retired")
|
|
186
|
+
throw new EpEnvelopeError("failed-precondition", `no manager instance currently holds a serve registration for "${space}" (instance ${args.serveInstanceId} is ${serveGate === null ? "unregistered" : "retired"}), so nothing may retire agents. The despawn was a FULL no-op - the agent is unchanged and still running. NEXT: start or recover the manager (\`cotal supervise\`), then retry the despawn.`);
|
|
187
|
+
// THE PRINCIPAL CROSS-CHECK (#350). The two serve coordinates above only SELECTED this row;
|
|
188
|
+
// they do not authorize. The row must belong to the SUBJECT-derived caller principal — which
|
|
189
|
+
// the broker enforced when it admitted the publish. Without this, naming any currently
|
|
190
|
+
// registered instance's row authorizes the caller, which is what the `ctl` rail did: its
|
|
191
|
+
// two-token subject could not express the caller beyond an alias, so there was nothing to
|
|
192
|
+
// compare the row against.
|
|
193
|
+
// ALIAS-LEVEL, not incarnation-level: the gate is keyed by the PERSISTED instanceId and its
|
|
194
|
+
// schema carries no uid, while the caller triple's uid is per-process. A same-principal zombie
|
|
195
|
+
// predecessor holding the current epoch value still passes. Closing that needs a gate-row
|
|
196
|
+
// schema change; it is deliberately not in this cut.
|
|
197
|
+
if (serveGate.principal !== requester)
|
|
198
|
+
throw new EpEnvelopeError("permission-denied", `the retirement request was REFUSED: the serve registration named (${args.serveEndpoint}/${args.serveInstanceId}) belongs to ${serveGate.principal}, not to the requesting principal ${requester}. A caller may only be authorized by its OWN serve registration. The despawn was a FULL no-op - the agent is unchanged and still running. NEXT: name your OWN principal's serve registration (any current instance of ${requester} will do), or call as the principal that owns this one.`);
|
|
199
|
+
if (serveGate.processEpoch !== args.serveEpoch)
|
|
200
|
+
throw new EpEnvelopeError("expired", `the requesting manager instance ${args.serveInstanceId} was SUPERSEDED (it registered at epoch ${args.serveEpoch}, the current serve grant is epoch ${serveGate.processEpoch}), so this despawn was REFUSED as a FULL no-op - the agent is unchanged and still running, nothing was torn down. NEXT: recover the manager (\`cotal supervise\`), then retry the despawn under the current serving instance.`);
|
|
201
|
+
// IDEMPOTENCE (the four-outcome table, in operator vocabulary).
|
|
202
|
+
const head = await readLifecycleHeadForOperation(opts.reg, target.owner, target.actor);
|
|
203
|
+
if (head === undefined)
|
|
204
|
+
throw new EpEnvelopeError("failed-precondition", `no lifecycle exists for "${target.owner}/${target.actor}"; there is nothing to retire.`);
|
|
205
|
+
if (head.mapping.state === "retired" && head.mapping.lifecycleUid === target.lifecycleUid)
|
|
206
|
+
return { retired: true, lifecycleUid: target.lifecycleUid, opId: args.opId, evictedPrincipals: [] };
|
|
207
|
+
if (head.mapping.lifecycleUid !== target.lifecycleUid)
|
|
208
|
+
throw new EpEnvelopeError("expired", `the despawn names a stale incarnation of "${target.owner}/${target.actor}" (current is ${head.mapping.lifecycleUid}); nothing was retired. NEXT: refresh the agent list and retry against the current incarnation.`);
|
|
209
|
+
const gate = await observeGate(opts.reg, target.lifecycleUid);
|
|
210
|
+
if (gate !== undefined && gate.row.state === "frozen" && gate.row.op !== undefined && gate.row.op.opId !== args.opId)
|
|
211
|
+
throw new EpEnvelopeError("conflict", `another operation (${gate.row.op.kind} ${gate.row.op.opId}) already holds "${target.owner}/${target.actor}"; this despawn did not start a second one. NEXT: wait for that operation to finish (or its resume on the next auth-service boot), then retry.`);
|
|
212
|
+
// EXECUTE (create-or-resume: the barrier's own freeze CAS + durable intent make the same
|
|
213
|
+
// opId resumable and a re-request idempotent). The drain, cleaner, and repair credentials
|
|
214
|
+
// all come from the plane's reviewed deps - this listener holds none of those rights.
|
|
215
|
+
const existing = barrierFlight.get(args.opId);
|
|
216
|
+
// A despawn cannot know the target's pool work, and the barrier never takes a pool hint: it
|
|
217
|
+
// DISCOVERS the real (endpoint, pools) cleaner inventory from the target's own accepted pool
|
|
218
|
+
// obligations (#F). Discovery is never a gap - the barrier never closes a frontier over
|
|
219
|
+
// un-cleaned accepted pool work (SPEC 13.1/13.9).
|
|
220
|
+
const flight = joinOrStartRetirement(barrierFlight, opts.reg, {
|
|
221
|
+
owner: target.owner, actor: target.actor, lifecycleUid: target.lifecycleUid, opId: args.opId,
|
|
222
|
+
frontierStreams: retirementFrontierStreams(space),
|
|
223
|
+
}, opts.retirement);
|
|
224
|
+
if (flight === undefined)
|
|
225
|
+
throw new EpEnvelopeError("conflict", `operation id ${args.opId} is already in flight for a different lifecycle (${existing?.owner}/${existing?.actor} ${existing?.lifecycleUid}); this despawn of "${target.owner}/${target.actor}" (${target.lifecycleUid}) was a FULL no-op - nothing was retired and it is still running. NEXT: retry the despawn (the manager derives a distinct operation id per lifecycle).`);
|
|
226
|
+
const result = await flight;
|
|
227
|
+
log(`auth-admin: retired ${target.owner}/${target.actor} (${target.lifecycleUid}) by despawn request from ${requester} (op ${args.opId})`);
|
|
228
|
+
return { retired: true, lifecycleUid: target.lifecycleUid, opId: result.opId, evictedPrincipals: result.evictedPrincipals };
|
|
229
|
+
},
|
|
230
|
+
};
|
|
231
|
+
// §13.9: the descriptor is PUBLIC. The broker grant on the request subject (who holds the
|
|
232
|
+
// caller triple's request-publish row, minted only by the `retirement-requester` profile) is the
|
|
233
|
+
// load-bearing authority tier; describe merely lists command names/schemas, which leaks nothing
|
|
234
|
+
// a holder of that grant does not already need to know to call successfully.
|
|
235
|
+
const handle = serveEndpoint(client.nc, space, opts.grant, authCommandDefs(handlers), { public: true }, { resolveTarget });
|
|
236
|
+
return {
|
|
237
|
+
close: async () => {
|
|
238
|
+
await handle.stop();
|
|
290
239
|
await client.close();
|
|
291
240
|
},
|
|
292
241
|
};
|
package/dist/auth-admin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-admin.js","sourceRoot":"","sources":["../src/auth-admin.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"auth-admin.js","sourceRoot":"","sources":["../src/auth-admin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The AUTH plane's v0.4 SERVICE CONTRACT (#399 M2): the §13.7 cluster document + compiled command
|
|
3
|
+
* contract for the `retire-lifecycle` op the auth plane serves on the `ep.*` rails. Shaped like
|
|
4
|
+
* `implementations/manager/src/manager-service-contract.ts` (the manager's own contract module):
|
|
5
|
+
* ONE `CommandRow`, its compiled input/output pair, and the cluster-document/artifact/command-def
|
|
6
|
+
* builders a `serveEndpoint` registration needs.
|
|
7
|
+
*
|
|
8
|
+
* This module is PURE DATA + schema (no broker, no barrier, no wire I/O): the registration and
|
|
9
|
+
* serve WIRING lives in the plane (`openAuthAuthorityPlane` / `openAuthAdminListener`).
|
|
10
|
+
*/
|
|
11
|
+
import { type CompiledContract, type EpAuthzMode, type EpCommandDef, type EpServeContext } from "@cotal-ai/core";
|
|
12
|
+
/** The auth plane's endpoint NAME (matches `AUTH_ENDPOINT` in `@cotal-ai/core`). */
|
|
13
|
+
export declare const AUTH_SERVICE_ENDPOINT = "auth";
|
|
14
|
+
/** The auth cluster document's URN (§13.7 content-addressed authority). */
|
|
15
|
+
export declare const AUTH_CLUSTER_URN = "ai.cotal.auth";
|
|
16
|
+
/** Per-command compiled contract pairs, exported for CALLERS (mirrors `MANAGER_CONTRACTS`). Lazy:
|
|
17
|
+
* a pair compiles on its first access, so importing the module alone pays no Ajv compile. */
|
|
18
|
+
export declare const AUTH_CONTRACTS: Readonly<Record<string, {
|
|
19
|
+
input: CompiledContract;
|
|
20
|
+
output: CompiledContract;
|
|
21
|
+
}>>;
|
|
22
|
+
/** Every §13.7 contract artifact the auth plane PUBLISHES to the EPC store at registration: each
|
|
23
|
+
* DISTINCT schema root plus its single-member closure manifest. */
|
|
24
|
+
export declare function authContractArtifactValues(): unknown[];
|
|
25
|
+
/** The §13.7 cluster DOCUMENT: the content-addressed authority for the auth plane's served
|
|
26
|
+
* command surface. Revision 1: the single `retire-lifecycle` command. */
|
|
27
|
+
export declare function authClusterDocument(): {
|
|
28
|
+
urn: string;
|
|
29
|
+
revision: number;
|
|
30
|
+
attributes: unknown[];
|
|
31
|
+
events: unknown[];
|
|
32
|
+
commands: Array<{
|
|
33
|
+
name: string;
|
|
34
|
+
class: "ephemeral";
|
|
35
|
+
targeted: boolean;
|
|
36
|
+
modes?: EpAuthzMode[];
|
|
37
|
+
capability: string;
|
|
38
|
+
inputDigest: string;
|
|
39
|
+
outputDigest: string;
|
|
40
|
+
}>;
|
|
41
|
+
};
|
|
42
|
+
/** The two-digest §13.7 content addressing for the auth document (mirrors
|
|
43
|
+
* `managerClusterArtifacts`): both artifacts publish to the `epc` store at their own digest;
|
|
44
|
+
* `clusterDigests` in the service spec carries the closure digest. */
|
|
45
|
+
export declare function authClusterArtifacts(): {
|
|
46
|
+
document: ReturnType<typeof authClusterDocument>;
|
|
47
|
+
rootDigest: string;
|
|
48
|
+
manifest: {
|
|
49
|
+
v: 1;
|
|
50
|
+
root: string;
|
|
51
|
+
members: string[];
|
|
52
|
+
};
|
|
53
|
+
closureDigest: string;
|
|
54
|
+
};
|
|
55
|
+
/** The handler the auth plane supplies to back `retire-lifecycle`. Receives the serve CONTEXT
|
|
56
|
+
* (broker-authenticated subject shape beside the validated args/target); returns the command's
|
|
57
|
+
* output value (the compiled output contract validates it at the serve boundary). Kept as a
|
|
58
|
+
* narrow interface so the contract module stays broker-free. */
|
|
59
|
+
export interface AuthServiceHandlers {
|
|
60
|
+
retireLifecycle(ctx: EpServeContext): unknown | Promise<unknown>;
|
|
61
|
+
}
|
|
62
|
+
/** Build the `EpCommandDef[]` `serveEndpoint` consumes. */
|
|
63
|
+
export declare function authCommandDefs(handlers: AuthServiceHandlers): EpCommandDef[];
|
|
64
|
+
//# sourceMappingURL=auth-service-contract.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-service-contract.d.ts","sourceRoot":"","sources":["../src/auth-service-contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAGL,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,cAAc,EACpB,MAAM,gBAAgB,CAAC;AAExB,oFAAoF;AACpF,eAAO,MAAM,qBAAqB,SAAS,CAAC;AAE5C,2EAA2E;AAC3E,eAAO,MAAM,gBAAgB,kBAAkB,CAAC;AAsEhD;8FAC8F;AAC9F,eAAO,MAAM,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE;IAAE,KAAK,EAAE,gBAAgB,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAA;CAAE,CAAC,CAMvG,CAAC;AAEL;oEACoE;AACpE,wBAAgB,0BAA0B,IAAI,OAAO,EAAE,CAYtD;AAED;0EAC0E;AAC1E,wBAAgB,mBAAmB,IAAI;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,OAAO,EAAE,CAAC;IACtB,MAAM,EAAE,OAAO,EAAE,CAAC;IAClB,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;;uEAEuE;AACvE,wBAAgB,oBAAoB,IAAI;IACtC,QAAQ,EAAE,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC;IACjD,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;;;iEAGiE;AACjE,MAAM,WAAW,mBAAmB;IAClC,eAAe,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAClE;AAED,2DAA2D;AAC3D,wBAAgB,eAAe,CAAC,QAAQ,EAAE,mBAAmB,GAAG,YAAY,EAAE,CAS7E"}
|