@cotal-ai/core 0.53.0 → 0.55.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-provider.d.ts +26 -1
- package/dist/auth-provider.d.ts.map +1 -1
- package/dist/auth-provider.js.map +1 -1
- package/dist/connector.d.ts +7 -1
- package/dist/connector.d.ts.map +1 -1
- package/dist/connector.js.map +1 -1
- package/dist/endpoint-grants.d.ts +7 -2
- package/dist/endpoint-grants.d.ts.map +1 -1
- package/dist/endpoint-grants.js +11 -4
- package/dist/endpoint-grants.js.map +1 -1
- package/dist/endpoint-invoke.d.ts +22 -11
- package/dist/endpoint-invoke.d.ts.map +1 -1
- package/dist/endpoint-invoke.js +255 -85
- package/dist/endpoint-invoke.js.map +1 -1
- package/dist/endpoint-service.d.ts +12 -0
- package/dist/endpoint-service.d.ts.map +1 -1
- package/dist/endpoint-service.js +1 -1
- package/dist/endpoint-service.js.map +1 -1
- package/dist/endpoint-verbs.d.ts +1 -0
- package/dist/endpoint-verbs.d.ts.map +1 -1
- package/dist/endpoint-verbs.js +14 -6
- package/dist/endpoint-verbs.js.map +1 -1
- package/dist/endpoint.d.ts +69 -3
- package/dist/endpoint.d.ts.map +1 -1
- package/dist/endpoint.js +217 -17
- package/dist/endpoint.js.map +1 -1
- package/dist/provision.d.ts +26 -1
- package/dist/provision.d.ts.map +1 -1
- package/dist/provision.js +116 -11
- package/dist/provision.js.map +1 -1
- package/dist/remote-manager-authority.d.ts +111 -0
- package/dist/remote-manager-authority.d.ts.map +1 -1
- package/dist/remote-manager-authority.js +175 -1
- package/dist/remote-manager-authority.js.map +1 -1
- package/dist/resolve.d.ts +13 -0
- package/dist/resolve.d.ts.map +1 -1
- package/dist/resolve.js +16 -0
- package/dist/resolve.js.map +1 -1
- package/dist/schema-profile.d.ts.map +1 -1
- package/dist/schema-profile.js +87 -8
- package/dist/schema-profile.js.map +1 -1
- package/dist/secret-store.d.ts +39 -0
- package/dist/secret-store.d.ts.map +1 -1
- package/dist/secret-store.js +24 -0
- package/dist/secret-store.js.map +1 -1
- package/dist/streams.d.ts +21 -21
- package/dist/streams.d.ts.map +1 -1
- package/dist/streams.js +52 -29
- package/dist/streams.js.map +1 -1
- package/dist/subjects.d.ts +18 -0
- package/dist/subjects.d.ts.map +1 -1
- package/dist/subjects.js +21 -0
- package/dist/subjects.js.map +1 -1
- package/package.json +1 -1
package/dist/provision.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { type RunDriverGrantArgs, type RunOperatorGrantArgs } from "./run-driver
|
|
|
7
7
|
import { type Identity } from "./identity.js";
|
|
8
8
|
import { type BackupPermissionScope, type RestorePermissionScope } from "./backup.js";
|
|
9
9
|
/** Cred profiles. Each profile has an explicit permission arm and a D5 lifetime classification. */
|
|
10
|
-
export type Profile = "agent" | "observer" | "admin" | "supervisor" | "provisioner" | "deprovisioner" | "retirement-requester" | "lifecycle-executor" | "endpoint-serve-executor" | "operator" | "purger" | "backup" | "restore" | "delivery" | "membership-rw" | "probe" | "channel-writer" | "channel-purger" | "teardown" | "control-caller-privileged" | "control-caller-admin" | "deployer" | "endpoint-serve" | "goal-writer" | "session-caller" | "session-serving" | "session-ledger" | "run-driver" | "run-mediator" | "run-operator" | "endpoint-evictor" | "issuer" | "run-admitter" | "remote-manager";
|
|
10
|
+
export type Profile = "agent" | "manager-caller" | "observer" | "admin" | "supervisor" | "provisioner" | "deprovisioner" | "retirement-requester" | "lifecycle-executor" | "endpoint-serve-executor" | "operator" | "purger" | "backup" | "restore" | "delivery" | "membership-rw" | "probe" | "channel-writer" | "channel-purger" | "teardown" | "control-caller-privileged" | "control-caller-admin" | "deployer" | "endpoint-serve" | "goal-writer" | "session-caller" | "session-serving" | "session-ledger" | "run-driver" | "run-mediator" | "run-operator" | "endpoint-evictor" | "issuer" | "run-admitter" | "remote-manager";
|
|
11
11
|
export type CredentialLifetimeClass = "standing-renewable" | "rotation-renewed" | "one-shot" | "static-operator-managed" | "mixed";
|
|
12
12
|
export type CredentialKind = Profile | "membership-observer" | "connection-evictor";
|
|
13
13
|
export interface CredentialLifetimePolicy {
|
|
@@ -17,6 +17,29 @@ export interface CredentialLifetimePolicy {
|
|
|
17
17
|
renewalOwner?: string;
|
|
18
18
|
note: string;
|
|
19
19
|
}
|
|
20
|
+
/** The broker's pre-auth control-line cap, in bytes (`max_control_line` in the generated config —
|
|
21
|
+
* `openServerConfig` and `serverConfig` below both render this literal, so the cap and the
|
|
22
|
+
* mint-time bound derived from it below can never drift). 64 KiB clears a many-channel agent
|
|
23
|
+
* JWT (~4-8 KB) with wide margin while keeping the pre-auth allocation ~16x tighter than 1 MB
|
|
24
|
+
* under connection flooding (the CONNECT line is parsed BEFORE auth). */
|
|
25
|
+
export declare const MAX_CONTROL_LINE_BYTES = 65536;
|
|
26
|
+
/** The fixed bytes a NATS client wraps around the `jwt` field on the CONNECT protocol line, over
|
|
27
|
+
* and above the JWT itself: the JSON object's other keys (`nkey`, `sig`, `name`, `lang`,
|
|
28
|
+
* `version`, `protocol`, `verbose`, `pedantic`, `no_responders`, `headers`), their values, and
|
|
29
|
+
* the surrounding braces/quotes/commas. Measured live (nats-server `-DV`, the trace of the raw
|
|
30
|
+
* protocol) on a real connect with the nats.js v3 client: a control-name credential produced a
|
|
31
|
+
* 5,104-byte JWT inside a 5,291-byte CONNECT line — 187 bytes of envelope, reproduced twice.
|
|
32
|
+
* Rounded up generously (>2.5x) to absorb client/library variation this repo does not control. */
|
|
33
|
+
export declare const CONNECT_ENVELOPE_OVERHEAD_BYTES = 512;
|
|
34
|
+
/** The mint-time budget for a user JWT's byte size: every composition that inflates the JWT (a
|
|
35
|
+
* long single channel, many channels, the per-agent event channel, any grant a later change
|
|
36
|
+
* adds) is priced against the SAME number, because the credential is what the client sends on
|
|
37
|
+
* the CONNECT line and the CONNECT line is what the broker caps — not any one contributor to it.
|
|
38
|
+
* `assertValidName`/`assertValidChannel` bound one input each; this bounds the OUTPUT, closing
|
|
39
|
+
* the gap between "every individual grant is legal" and "the composed credential still fits"
|
|
40
|
+
* (issue #375's review finding: six distinct 4096-char channels, each individually accepted,
|
|
41
|
+
* minted a JWT the broker would silently drop). */
|
|
42
|
+
export declare const MAX_MINTED_JWT_BYTES: number;
|
|
20
43
|
/** Bounded lifetime for `standing-renewable` credentials whose renewal owner is ONLINE (D5 slice 5):
|
|
21
44
|
* the holder (or its launcher) re-mints at 75% of the lifetime via the endpoint's creds-source seam,
|
|
22
45
|
* so a copied cred is broker-dead within a day while renewal never involves an operator. 24h keeps
|
|
@@ -176,6 +199,8 @@ export interface MintOpts {
|
|
|
176
199
|
* caller's own reply-rail read row. Requires {@link MintOpts.lifecycleUid} — the rows pin
|
|
177
200
|
* the full caller triple. Default-deny when absent. */
|
|
178
201
|
endpointCapabilities?: EpCapability[];
|
|
202
|
+
/** `manager-caller` profile only: the one manager instance every request row pins. */
|
|
203
|
+
managerInstanceId?: string;
|
|
179
204
|
/** The caller's lifecycle UID (SPEC §13.1), minted by the managing authority BEFORE the
|
|
180
205
|
* entity is reachable. REQUIRED with `endpointCapabilities` — every endpoint-rail row
|
|
181
206
|
* forge-locks it as the third caller token. */
|
package/dist/provision.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provision.d.ts","sourceRoot":"","sources":["../src/provision.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAkCL,KAAK,iBAAiB,EAYvB,MAAM,eAAe,CAAC;AACvB,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAmD,KAAK,YAAY,EAAE,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAGhI,OAAO,EAAqG,KAAK,YAAY,EAA2B,MAAM,uBAAuB,CAAC;AAEtL,OAAO,EAAyD,KAAK,kBAAkB,EAAE,KAAK,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAInJ,OAAO,EAAe,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EAGL,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC5B,MAAM,aAAa,CAAC;AAErB,mGAAmG;AACnG,MAAM,MAAM,OAAO,GACf,OAAO,GACP,UAAU,GACV,OAAO,GACP,YAAY,GACZ,aAAa,GACb,eAAe,GACf,sBAAsB,GACtB,oBAAoB,GACpB,yBAAyB,GACzB,UAAU,GACV,QAAQ,GACR,QAAQ,GACR,SAAS,GACT,UAAU,GACV,eAAe,GAEf,OAAO,GACP,gBAAgB,GAChB,gBAAgB,GAChB,UAAU,GAGV,2BAA2B,GAC3B,sBAAsB,GACtB,UAAU,GAIV,gBAAgB,GAKhB,aAAa,GAGb,gBAAgB,GAKhB,iBAAiB,GAKjB,gBAAgB,GAGhB,YAAY,GACZ,cAAc,GAMd,cAAc,GAQd,kBAAkB,GAIlB,QAAQ,GAIR,cAAc,GAGd,gBAAgB,CAAC;AAErB,MAAM,MAAM,uBAAuB,GAC/B,oBAAoB,GAKpB,kBAAkB,GAClB,UAAU,GACV,yBAAyB,GACzB,OAAO,CAAC;AACZ,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,qBAAqB,GAAG,oBAAoB,CAAC;AAEpF,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,uBAAuB,CAAC;IAC/B,4GAA4G;IAC5G,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;CACd;AAID;;;qGAGqG;AACrG,eAAO,MAAM,0BAA0B,QAAe,CAAC;AAEvD;;;;;2EAK2E;AAC3E,eAAO,MAAM,wBAAwB,QAAoB,CAAC;AAE1D;yFACyF;AACzF,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,cAAc,EAAE,wBAAwB,
|
|
1
|
+
{"version":3,"file":"provision.d.ts","sourceRoot":"","sources":["../src/provision.ts"],"names":[],"mappings":"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"}
|
package/dist/provision.js
CHANGED
|
@@ -19,7 +19,7 @@ import { join } from "node:path";
|
|
|
19
19
|
import { decode, encodeOperator, encodeAccount, encodeUser, fmtCreds, } from "@nats-io/jwt";
|
|
20
20
|
import { createOperator, createAccount, fromPublic, fromSeed } from "@nats-io/nkeys";
|
|
21
21
|
import { token, spacePrefix, chatSubject, assertValidChannel, channelInAllow, principalKey, parsePrincipalKey, deprovisionTargetPrincipal, principalTags, assertInboxConnId, DEV_OWNER, unicastSubject, anycastSubject, controlServiceSubject, CONTROL_DELIVERY, CONTROL_DELIVERY_ADMIN, artifactBucket, objectStoreStream, chatStream, dmStream, taskStream, dlvStream, inboxStream, chatHistDurable, dmDurable, taskDurable, dlvDurable, presenceBucket, channelBucket, membersBucket, aclBucket, aclKey, assertLifecycleToken, membershipBucket, deliveryBucket, managerBucket, MANAGER_LEASE_KEY, MANAGER_RENEWAL_LEASE_KEY, connzRequestSubject, accountConnectSubject, accountDisconnectSubject, MEMBERSHIP_INBOX_PREFIX, FANOUT_DURABLE, INBOX_READER_DURABLE, } from "./subjects.js";
|
|
22
|
-
import { epCallerGrantRows, epServeGrantRows, epBaselineGrantRows, spawnCallerCapabilities, runCallerCapabilities, epRequestGrantRows, operatorInstrumentCapabilities, epDescribeAllGrantRow, BASELINE_LIFECYCLE_ENDPOINT, } from "./endpoint-grants.js";
|
|
22
|
+
import { epCallerGrantRows, epServeGrantRows, epBaselineGrantRows, baselineCallerCapabilities, spawnCallerCapabilities, runCallerCapabilities, epRequestGrantRows, operatorInstrumentCapabilities, instanceOnlyManagerCapabilities, epDescribeAllGrantRow, BASELINE_LIFECYCLE_ENDPOINT, } from "./endpoint-grants.js";
|
|
23
23
|
import { assertServeGrantMintable, finalizeServeIssuance } from "./endpoint-service.js";
|
|
24
24
|
import { effectsBindGrants, poolOwnerBindGrants, goalWriterGrants, sessionLedgerGrants, epAuthBucket, sessionsBucket, epcStreamName, endpointPlaneStreamNames, eptReqStreamName, eptStreamName, hardenedAuthorityStreamNames, timerWriterDurable, timerWriterGrants } from "./endpoint-binding.js";
|
|
25
25
|
import { epsSubject, epCallerReplyFilter, assertGeneration, AUTH_ENDPOINT, EP_CMD_RETIRE_LIFECYCLE } from "./endpoint-subjects.js";
|
|
@@ -32,6 +32,29 @@ import { rawDigest } from "./canonical.js";
|
|
|
32
32
|
import { credsClaims } from "./identity.js";
|
|
33
33
|
import { backupProfilePermissions, restoreProfilePermissions, } from "./backup.js";
|
|
34
34
|
const FIVE_MINUTES = 5 * 60;
|
|
35
|
+
/** The broker's pre-auth control-line cap, in bytes (`max_control_line` in the generated config —
|
|
36
|
+
* `openServerConfig` and `serverConfig` below both render this literal, so the cap and the
|
|
37
|
+
* mint-time bound derived from it below can never drift). 64 KiB clears a many-channel agent
|
|
38
|
+
* JWT (~4-8 KB) with wide margin while keeping the pre-auth allocation ~16x tighter than 1 MB
|
|
39
|
+
* under connection flooding (the CONNECT line is parsed BEFORE auth). */
|
|
40
|
+
export const MAX_CONTROL_LINE_BYTES = 65536;
|
|
41
|
+
/** The fixed bytes a NATS client wraps around the `jwt` field on the CONNECT protocol line, over
|
|
42
|
+
* and above the JWT itself: the JSON object's other keys (`nkey`, `sig`, `name`, `lang`,
|
|
43
|
+
* `version`, `protocol`, `verbose`, `pedantic`, `no_responders`, `headers`), their values, and
|
|
44
|
+
* the surrounding braces/quotes/commas. Measured live (nats-server `-DV`, the trace of the raw
|
|
45
|
+
* protocol) on a real connect with the nats.js v3 client: a control-name credential produced a
|
|
46
|
+
* 5,104-byte JWT inside a 5,291-byte CONNECT line — 187 bytes of envelope, reproduced twice.
|
|
47
|
+
* Rounded up generously (>2.5x) to absorb client/library variation this repo does not control. */
|
|
48
|
+
export const CONNECT_ENVELOPE_OVERHEAD_BYTES = 512;
|
|
49
|
+
/** The mint-time budget for a user JWT's byte size: every composition that inflates the JWT (a
|
|
50
|
+
* long single channel, many channels, the per-agent event channel, any grant a later change
|
|
51
|
+
* adds) is priced against the SAME number, because the credential is what the client sends on
|
|
52
|
+
* the CONNECT line and the CONNECT line is what the broker caps — not any one contributor to it.
|
|
53
|
+
* `assertValidName`/`assertValidChannel` bound one input each; this bounds the OUTPUT, closing
|
|
54
|
+
* the gap between "every individual grant is legal" and "the composed credential still fits"
|
|
55
|
+
* (issue #375's review finding: six distinct 4096-char channels, each individually accepted,
|
|
56
|
+
* minted a JWT the broker would silently drop). */
|
|
57
|
+
export const MAX_MINTED_JWT_BYTES = MAX_CONTROL_LINE_BYTES - CONNECT_ENVELOPE_OVERHEAD_BYTES;
|
|
35
58
|
/** Bounded lifetime for `standing-renewable` credentials whose renewal owner is ONLINE (D5 slice 5):
|
|
36
59
|
* the holder (or its launcher) re-mints at 75% of the lifetime via the endpoint's creds-source seam,
|
|
37
60
|
* so a copied cred is broker-dead within a day while renewal never involves an operator. 24h keeps
|
|
@@ -48,6 +71,7 @@ export const ROTATION_RENEWED_TTL_SEC = 30 * 24 * 60 * 60;
|
|
|
48
71
|
* credential-death behavior instead of silently inheriting non-expiring static creds. */
|
|
49
72
|
export const CREDENTIAL_LIFETIMES = {
|
|
50
73
|
agent: { class: "mixed", note: "manager children, foreground spawn/join, and cotal mint static outputs all use this profile; split or repair flow required before default exp" },
|
|
74
|
+
"manager-caller": { class: "mixed", note: "short-lived user-auth view bound to the bearer expiry and one manager instance" },
|
|
51
75
|
observer: { class: "static-operator-managed", note: "out-of-band dashboard/audit credential from cotal mint" },
|
|
52
76
|
admin: { class: "static-operator-managed", note: "out-of-band elevated dashboard/audit credential from cotal mint" },
|
|
53
77
|
supervisor: { class: "standing-renewable", defaultTtlSeconds: STANDING_RENEWABLE_TTL_SEC, renewalOwner: "manager", note: "manager's always-on endpoint; the manager holds the DATA seed and self-remints via the endpoint creds source (D5 slice 5 class 1)" },
|
|
@@ -382,6 +406,19 @@ export async function mintCreds(auth, identity, profile, opts = {}) {
|
|
|
382
406
|
// orphan authority record). fmtCreds only wraps the already-signed JWT with the seed, so it is
|
|
383
407
|
// done here and the fence is the mint's LAST step.
|
|
384
408
|
const creds = new TextDecoder().decode(fmtCreds(userJwt, fromSeed(new TextEncoder().encode(identity.seed))));
|
|
409
|
+
// The composed-credential bound (SPEC 13.9, issue #375's review finding): every individual grant
|
|
410
|
+
// input can pass its own validator (assertValidName, assertValidChannel) and the COMPOSED JWT
|
|
411
|
+
// still exceed the CONNECT line the broker caps, because nothing bounded the COUNT of channels
|
|
412
|
+
// an agent's allowSubscribe/allowPublish may carry. Refuse here, BEFORE releaseIssuance (the
|
|
413
|
+
// file's own no-fallible-work-after-a-winning-CAS rule, stated above) — a refusal here has
|
|
414
|
+
// released no ledger row, unlike a refusal after.
|
|
415
|
+
const userJwtBytes = Buffer.byteLength(userJwt, "utf8");
|
|
416
|
+
if (userJwtBytes > MAX_MINTED_JWT_BYTES) {
|
|
417
|
+
const channelCount = (opts.allowSubscribe?.length ?? 0) + (opts.allowPublish?.length ?? 0);
|
|
418
|
+
throw new Error(`mintCreds: minted JWT is ${userJwtBytes} bytes, exceeding the ${MAX_MINTED_JWT_BYTES}-byte ` +
|
|
419
|
+
`mint bound (${channelCount} allowSubscribe+allowPublish channel(s)) - the composed credential ` +
|
|
420
|
+
`would exceed the broker's CONNECT line and the connect would hang silently (issue #375)`);
|
|
421
|
+
}
|
|
385
422
|
await releaseIssuance(auth.space, profile, pr, opts, perms, validDates.exp, rawDigest(creds).replace("sha256:", "sha256-"));
|
|
386
423
|
// §13.1 mint fence for the serve credential: the credential is BUILT, but released only when its
|
|
387
424
|
// NORMATIVE ledger row (holderPrincipal/lifecycleUid/sourceChain/state/exp + the currency
|
|
@@ -470,6 +507,18 @@ export async function mintPublicUserJwt(auth, publicId, profile, opts) {
|
|
|
470
507
|
if (validDates.exp === undefined)
|
|
471
508
|
throw new Error(`mintPublicUserJwt: profile "${profile}" must be bounded`);
|
|
472
509
|
const jwt = await encodeUser(profile, fromPublic(publicId), fromPublic(auth.account.pub), { ...perms, tags: principalTags(pr.owner, pr.actor) }, { signer: fromSeed(new TextEncoder().encode(auth.account.signingSeed)), ...validDates });
|
|
510
|
+
// Same composed-credential bound as mintCreds (see MAX_MINTED_JWT_BYTES): this JWT is presented
|
|
511
|
+
// on a real CONNECT line by the remote manager, so it is priced against the same budget before
|
|
512
|
+
// any fallible finalize step below. None of this function's profiles read allowSubscribe/
|
|
513
|
+
// allowPublish today (each returns through its own dedicated permission builder), so the count
|
|
514
|
+
// is always 0 here - the check stays live in case a future profile addition changes that.
|
|
515
|
+
const jwtBytes = Buffer.byteLength(jwt, "utf8");
|
|
516
|
+
if (jwtBytes > MAX_MINTED_JWT_BYTES) {
|
|
517
|
+
const channelCount = (opts.allowSubscribe?.length ?? 0) + (opts.allowPublish?.length ?? 0);
|
|
518
|
+
throw new Error(`mintPublicUserJwt: minted JWT is ${jwtBytes} bytes, exceeding the ${MAX_MINTED_JWT_BYTES}-byte ` +
|
|
519
|
+
`mint bound (${channelCount} allowSubscribe+allowPublish channel(s)) - the composed credential ` +
|
|
520
|
+
`would exceed the broker's CONNECT line and the connect would hang silently (issue #375)`);
|
|
521
|
+
}
|
|
473
522
|
if (profile === "endpoint-serve") {
|
|
474
523
|
if (!opts.serveIssuance)
|
|
475
524
|
throw new Error("mintPublicUserJwt: endpoint-serve requires serveIssuance");
|
|
@@ -516,6 +565,8 @@ export function permissionsFor(profile, space, pr, opts) {
|
|
|
516
565
|
throw new Error(`permissionsFor: opts.issued binds caller rails and "${profile}" holds none; only ${[...ISSUABLE_PROFILES].join(", ")} mint issued authority (SPEC 13.15)`);
|
|
517
566
|
if (profile === "delivery")
|
|
518
567
|
return deliveryPermissions(space, pr); // scoped server-side Plane-3 infra
|
|
568
|
+
if (profile === "manager-caller")
|
|
569
|
+
return managerCallerPermissions(space, pr, opts);
|
|
519
570
|
if (profile === "membership-rw")
|
|
520
571
|
return membershipRwPermissions(space, pr); // scoped graph-feed reader/writer
|
|
521
572
|
if (profile === "supervisor")
|
|
@@ -975,6 +1026,34 @@ export function permissionsFor(profile, space, pr, opts) {
|
|
|
975
1026
|
// the `ctl.<tier>.<id>.reply.>` subtrees are gone with the ctl rail (1d).
|
|
976
1027
|
return { pub: { allow: pubAllow, deny: pubDeny }, sub: { allow: [inbox, deliveryReplies, ...subChat, ...epSub] } };
|
|
977
1028
|
}
|
|
1029
|
+
/** One seat's manager control view. It carries no agent messaging or delivery surface, and every
|
|
1030
|
+
* manager request, including describe, is pinned to one exact registered instance. */
|
|
1031
|
+
function managerCallerPermissions(space, pr, opts) {
|
|
1032
|
+
if (!pr.lifecycleUid)
|
|
1033
|
+
throw new Error("permissionsFor(manager-caller): a lifecycleUid is required");
|
|
1034
|
+
const instanceId = opts.managerInstanceId === undefined
|
|
1035
|
+
? (() => { throw new Error("permissionsFor(manager-caller): managerInstanceId is required"); })()
|
|
1036
|
+
: assertLifecycleToken(opts.managerInstanceId, "managerInstanceId");
|
|
1037
|
+
const caps = opts.capabilities ?? [];
|
|
1038
|
+
const ordinary = [
|
|
1039
|
+
{ endpoint: BASELINE_LIFECYCLE_ENDPOINT, command: "describe" },
|
|
1040
|
+
...baselineCallerCapabilities().filter((cap) => cap.endpoint === BASELINE_LIFECYCLE_ENDPOINT),
|
|
1041
|
+
...(caps.includes("spawn") ? spawnCallerCapabilities(pr.owner) : []),
|
|
1042
|
+
...(caps.includes("run") ? runCallerCapabilities(pr.owner) : []),
|
|
1043
|
+
...(caps.includes("admin") ? operatorInstrumentCapabilities("admin", pr.owner) : []),
|
|
1044
|
+
];
|
|
1045
|
+
const caller = issuedCallerFor({ owner: pr.owner, actor: pr.actor, uid: assertLifecycleToken(pr.lifecycleUid) }, opts);
|
|
1046
|
+
const rows = epCallerGrantRows(space, instanceOnlyManagerCapabilities(ordinary, instanceId), caller);
|
|
1047
|
+
return {
|
|
1048
|
+
pub: {
|
|
1049
|
+
allow: [
|
|
1050
|
+
`$JS.API.DIRECT.GET.${epcStreamName(space)}.${spacePrefix(space)}.epc.>`,
|
|
1051
|
+
...rows.pub,
|
|
1052
|
+
],
|
|
1053
|
+
},
|
|
1054
|
+
sub: { allow: [`_INBOX_${pr.connId}.>`, ...rows.sub] },
|
|
1055
|
+
};
|
|
1056
|
+
}
|
|
978
1057
|
/** The long-lived SUPERVISOR permission set (closure (ii), residual 2) — the always-on manager daemon
|
|
979
1058
|
* (`manager.ts` `this.ep`), carved down from the former allow-all `manager`. THIS is the cred whose
|
|
980
1059
|
* STANDING breadth was the residual-2 gate: tightening it removes the always-on DM/DLV body-read AND the
|
|
@@ -990,6 +1069,7 @@ export function permissionsFor(profile, space, pr, opts) {
|
|
|
990
1069
|
* actor, provision, purge, or tamper with a stream. */
|
|
991
1070
|
function supervisorPermissions(space, pr) {
|
|
992
1071
|
const PKV = `KV_${presenceBucket(space)}`, MKV = `KV_${managerBucket(space)}`;
|
|
1072
|
+
const SUP_DLVKV = `KV_${deliveryBucket(space)}`;
|
|
993
1073
|
// 1d: the supervisor no longer serves the manager control tiers — the manager's control surface
|
|
994
1074
|
// is its v0.4 `service` endpoint, served on a SEPARATE connection under its own `endpoint-serve`
|
|
995
1075
|
// credential (its rails are that credential's grant, not the supervisor's). The supervisor now
|
|
@@ -1023,6 +1103,18 @@ function supervisorPermissions(space, pr) {
|
|
|
1023
1103
|
// files it requests `reloadCreds` here so adoption is an explicit, auditable event. Self-scoped
|
|
1024
1104
|
// request subject (its own owner+actor slots), bounded reply subtree in sub.allow below.
|
|
1025
1105
|
controlServiceSubject(space, CONTROL_DELIVERY_ADMIN, pr.owner, pr.actor),
|
|
1106
|
+
// #1694: a POINT READ of the delivery lease row, so the store-identity challenge can verify
|
|
1107
|
+
// that the process which answered the queue-grouped admin rail is the holder that actually
|
|
1108
|
+
// reloads the standing credentials. Without it the challenge can only report what some
|
|
1109
|
+
// responder sent, and a non-holder's store stands in for the reloading process's.
|
|
1110
|
+
//
|
|
1111
|
+
// READ ONLY, and that is the half that matters: a credential able to WRITE this row could
|
|
1112
|
+
// manufacture the very fact the challenge reads, which would put the determination back in
|
|
1113
|
+
// the hands of a participant. No `$KV.${deliveryBucket(space)}` publish, no watch consumer,
|
|
1114
|
+
// no STREAM.DELETE or PURGE.
|
|
1115
|
+
`$JS.API.STREAM.INFO.${SUP_DLVKV}`,
|
|
1116
|
+
`$JS.API.STREAM.MSG.GET.${SUP_DLVKV}`,
|
|
1117
|
+
`$JS.API.DIRECT.GET.${SUP_DLVKV}.>`,
|
|
1026
1118
|
],
|
|
1027
1119
|
},
|
|
1028
1120
|
sub: {
|
|
@@ -1500,10 +1592,13 @@ function purgerPermissions(space, pr) {
|
|
|
1500
1592
|
* `$JS` is an ENUMERATED allow-list, never `$JS.>`: STREAM.CREATE + INFO for the space streams/buckets,
|
|
1501
1593
|
* DM/DLV/TASK consumer CREATE/DURABLE.CREATE/INFO — and deliberately NO `MSG.NEXT`/`MSG.GET`/`ACK` on
|
|
1502
1594
|
* DM/DLV (it creates the bind-only mailbox but never reads it), and NO STREAM.DELETE/PURGE/MSG.DELETE
|
|
1503
|
-
* (it provisions, it does not tear down). STREAM.UPDATE is held on EXACTLY
|
|
1595
|
+
* (it provisions, it does not tear down). STREAM.UPDATE is held on EXACTLY eight streams and no others:
|
|
1504
1596
|
* the three TTL'd KV buckets (presence + the two leases, #286: an existing bucket's `max_age` cannot be
|
|
1505
|
-
* fixed by `kvm.create`, so reconciling a pre-TTL deployment requires updating it)
|
|
1506
|
-
* authority stores (records, issued, accepted, admission), each updated once at creation
|
|
1597
|
+
* fixed by `kvm.create`, so reconciling a pre-TTL deployment requires updating it), the four hardened
|
|
1598
|
+
* authority stores (records, issued, accepted, admission), each updated once at creation, and the
|
|
1599
|
+
* artifact Object Store, whose legacy 4 GiB `max_bytes` `ensureArtifactStore` reconciles to -1 (the
|
|
1600
|
+
* reservation a positive cap holds against the broker's `max_file_store` is what stopped a tenth space
|
|
1601
|
+
* from being provisioned; `Objm.create` cannot fix an existing bucket's cap either).
|
|
1507
1602
|
* Stated positively on purpose: this docblock previously read "NO …/UPDATE", which was already untrue of
|
|
1508
1603
|
* the records stream and became untrue of the buckets, and a comment that denies a credential's real
|
|
1509
1604
|
* power is worse than none — it is the document a reader trusts instead of checking. KV value-writes are
|
|
@@ -1535,8 +1630,9 @@ function provisionerPermissions(space, pr) {
|
|
|
1535
1630
|
// The artifact Object Store joins the list: `setupSpaceStreams` creates it, and under auth mode the
|
|
1536
1631
|
// provisioner is the cred doing that creating. Its backing stream is `OBJ_<bucket>` - named
|
|
1537
1632
|
// explicitly, because `$O.<bucket>.>` is outside the `cotal.<space>.>` grammar and no space-prefix
|
|
1538
|
-
// grant reaches it. CREATE + INFO
|
|
1539
|
-
// consumer on it, and never deletes it.
|
|
1633
|
+
// grant reaches it. CREATE + INFO here, plus the ONE STREAM.UPDATE below (the legacy-cap reconcile):
|
|
1634
|
+
// the provisioner never publishes an object, never creates a consumer on it, and never deletes it.
|
|
1635
|
+
// That confinement is load-bearing rather than tidy - the
|
|
1540
1636
|
// object-store client reads by creating an ephemeral PUSH consumer with a caller-chosen
|
|
1541
1637
|
// `deliver_subject`, so a CONSUMER.CREATE here would be an exporter of every artifact in the space.
|
|
1542
1638
|
const OBJ = objectStoreStream(artifactBucket(space));
|
|
@@ -1557,7 +1653,15 @@ function provisionerPermissions(space, pr) {
|
|
|
1557
1653
|
// the grant never learned about it. Same defect one seam out — a bucket the code knows to maintain
|
|
1558
1654
|
// and the credential is not allowed to.
|
|
1559
1655
|
const ttlStreams = ttlBuckets(space).map(([bucket]) => `KV_${bucket}`);
|
|
1560
|
-
|
|
1656
|
+
// ...plus the artifact Object Store. `ensureArtifactStore` creates it at `max_bytes: -1` so it
|
|
1657
|
+
// reserves nothing against the broker's `max_file_store`, and reconciles a store left at the legacy
|
|
1658
|
+
// stock 4 GiB to -1 so an EXISTING mesh releases that reservation too. `Objm.create` never updates
|
|
1659
|
+
// an existing bucket's config (measured: create at 1024 then create at 4096 leaves 1024), so the
|
|
1660
|
+
// reconcile is a STREAM.UPDATE and needs this grant — without it the provisioner dies on a
|
|
1661
|
+
// permissions violation on the first `cotal up` after the upgrade. Still CREATE/INFO/UPDATE only:
|
|
1662
|
+
// no publish, no CONSUMER.CREATE (a push consumer's caller-chosen `deliver_subject` would export
|
|
1663
|
+
// every artifact in the space), no DELETE/PURGE.
|
|
1664
|
+
const streamReconcile = [...ttlStreams, OBJ].map((s) => `$JS.API.STREAM.UPDATE.${s}`);
|
|
1561
1665
|
// #404: one EXACT reserved key on each TTL bucket is the post-update enforcement canary. The
|
|
1562
1666
|
// provisioner still cannot write presence identities or lease keys; it can only write this fixed
|
|
1563
1667
|
// maintenance key, which expires through the policy the reconcile is proving.
|
|
@@ -2135,7 +2239,7 @@ export function openServerConfig(opts) {
|
|
|
2135
2239
|
return `# Generated by \`cotal up\` - do not edit by hand.
|
|
2136
2240
|
host: ${host}
|
|
2137
2241
|
port: ${port}
|
|
2138
|
-
max_control_line:
|
|
2242
|
+
max_control_line: ${MAX_CONTROL_LINE_BYTES}
|
|
2139
2243
|
${renderTlsBlock(opts.transport)}${renderJetStreamBlock("openServerConfig", opts.storeDir, opts.maxFileStore)}
|
|
2140
2244
|
`;
|
|
2141
2245
|
}
|
|
@@ -2191,13 +2295,14 @@ export function serverConfig(broker, spaces, opts) {
|
|
|
2191
2295
|
// exceeds the 4 KB default max_control_line at ~2 channels, and the server then silently drops
|
|
2192
2296
|
// the connection (the client retries forever — a connect that "hangs"). Raise it to fit a rich
|
|
2193
2297
|
// agent JWT — but right-sized, not generous: the CONNECT line is parsed BEFORE auth, so the cap
|
|
2194
|
-
// is a per-connection pre-auth allocation under connection flooding.
|
|
2195
|
-
//
|
|
2298
|
+
// is a per-connection pre-auth allocation under connection flooding. See MAX_CONTROL_LINE_BYTES
|
|
2299
|
+
// for the derivation; mintCreds/mintPublicUserJwt refuse a JWT that would not fit it BEFORE this
|
|
2300
|
+
// config is ever reached, so a legal credential never depends on this margin alone.
|
|
2196
2301
|
const tlsBlock = renderTlsBlock(opts.transport);
|
|
2197
2302
|
return `# Generated by \`cotal up\` - do not edit by hand.
|
|
2198
2303
|
host: ${host}
|
|
2199
2304
|
port: ${port}
|
|
2200
|
-
max_control_line:
|
|
2305
|
+
max_control_line: ${MAX_CONTROL_LINE_BYTES}
|
|
2201
2306
|
${tlsBlock}${renderJetStreamBlock("serverConfig", opts.storeDir, opts.maxFileStore)}
|
|
2202
2307
|
${websocket}operator: ${broker.operator.jwt}
|
|
2203
2308
|
system_account: ${broker.sys.pub}
|