import { type EpCaller, type EpTarget } from "./endpoint-subjects.js"; /** A minted request capability: one endpoint command a caller may invoke, on the named rails. * `routes` defaults to `["one"]`; `instanceId` additionally pins the instance form to exactly * that instance. A TARGETED capability carries its authorization mode with the target tokens * LITERAL as minted (§13.2): `owner`/`child` pin the caller's own owner; `any`/`ledger` may pin * `"*"` (mintable only under operator/admin policy — enforced by the minting authority, not * here); `handle` pins the full redemption triple and is never a standing capability (the * standing rollup {@link epCallerGrantRows} refuses it; only the §13.6 redemption path builds * handle rows, through {@link epRequestGrantRows} directly). */ export interface EpCapability { endpoint: string; command: string; routes?: ("one" | "all")[]; instanceId?: string; target?: EpTarget; /** Also grant the matching journal-submission append row (`epj`, §13.9 matrix). */ journal?: boolean; } /** Request-publish rows for one capability (§13.9 "Request publish"): per route, * `ep.{one,all}..[.[.]]....*` and the * instance-pinned form when `instanceId` is set. The nonce is the only wildcard token. */ export declare function epRequestGrantRows(space: string, cap: EpCapability, caller: EpCaller): string[]; /** Journal-submission append row (§13.9 "Journal submission append"): the same authz/target * block as the request forms, caller-pinned, no nonce. Explicitly untrusted input (§13.4). */ export declare function epJournalGrantRow(space: string, cap: EpCapability, caller: EpCaller): string; /** The caller's reply-rail read row (§13.9 "Reply subscribe"): its own rail only, exact arity. */ export declare function epCallerReplyGrantRow(space: string, caller: EpCaller): string; /** Per-goal live progress read row (§13.9 "Live event progress", reserved `goal` topic): * `epe..*.*.goal....>` — the caller identity in the subject gives * mint-time read containment; delivered on the caller's own core subscription only. */ export declare function epGoalProgressGrantRow(space: string, endpoint: string, caller: EpCaller): string; /** All caller-side rows for a capability set: request-publish (+ optional journal) into * `pub.allow`, the reply rail (+ the per-goal progress read for GOAL-BEARING capabilities) into * `sub.allow`. This is the STANDING rollup (`permissionsFor` mints long-lived credentials from * it), so a `handle`-mode capability is refused here: handle rows are redemption-minted only * (§13.2/§13.6), built by the redemption path through {@link epRequestGrantRows} directly. * A goal-bearing capability ({@link GOAL_BEARING_COMMANDS}: spawn/launch) adds ONE per-endpoint * {@link epGoalProgressGrantRow} — the caller may follow its OWN goal to terminal (P2 item 2, Q1); * it is the one read an invoke implies, because the subject pins the caller's own triple. Still * NOT included: any OTHER `epe` subtree — those are minted per read capability by the granting * authority (Appendix B), not implied by an invoke. */ export declare function epCallerGrantRows(space: string, caps: EpCapability[], caller: EpCaller): { pub: string[]; sub: string[]; }; /** The delivery endpoint's baseline command names (Appendix B: "durable join/leave/list"). * All four command vocabularies below are RUNTIME-frozen (TS `as const` is type-level only) * and the capability builders consult PRIVATE module-load snapshots, never these live * exports: a post-import `push("attach")` here would otherwise widen every subsequently * minted agent grant (the afa715b identity-vs-integrity class, executed repro). */ export declare const BASELINE_DELIVERY_ENDPOINT = "delivery"; export declare const BASELINE_DELIVERY_COMMANDS: readonly ["join", "leave", "list"]; /** The manager endpoint's self-lifecycle baseline and the spawn-capability owner-mode lifecycle * set. Self mode reaches the caller's OWN incarnation and nothing else: the no-name self stop * (the v0.3 self-service tier's only op) and the two halves of the run-turn relay, a seat * pulling the turns addressed to it and yielding them back. Both are in the baseline because * the manager pushes nothing into a seat: without the pull row, a seat on an auth mesh is * broker-denied at its first `turn-pending` and the relay is silently dead for every spawned * agent (measured: the connector reads the denial as "no manager here" and stays quiet). */ export declare const BASELINE_LIFECYCLE_ENDPOINT = "manager"; export declare const BASELINE_SELF_LIFECYCLE_COMMANDS: readonly ["stop", "turn-pending", "turn-yield"]; /** `spawn` is CREATION: a virgin spawn has no target lifecycle UID or current mapping yet, so it * CANNOT ride owner mode (§13.2 owner mode resolves a body `{owner, actor, lifecycleUid}` against * the CURRENT mapping — there is nothing to resolve for a not-yet-existing child). It is minted * UNTARGETED; the child-owner ceiling is the authenticated caller's own owner, carried by the * pinned caller triple. `despawn` (terminal) and `attach` (interactive) act on an EXISTING agent, * so they ride owner mode. Owner-mode `stop` is DELIBERATELY ABSENT: on the v0.3 surface a named * stop and a despawn both free-slot + deprovision, so an owner-mode `stop` would be a wire synonym * of `despawn` (distsys) — one owner-mode terminal command keeps the vocabulary single. Self-`stop` * stays in the BASELINE (the v0.3 self-service tier's only op); it is the lighter self-halt. * `input` (type into the seat) is DELIBERATELY ABSENT from this set, and the reasoning is worth * keeping because the obvious argument for including it is false. That argument runs: owner-mode * `attach` already reaches the same pty through `AttachSession.write`, so granting `input` adds * nothing. It does not reach it. `attach` returns a §13.6 grant, and REDEEMING one needs a * `session-caller` credential carrying `eps....in`, which this profile * does not hold and cannot mint, because minting reads the space signing seed. Executed: a * spawn-capability credential's minted JWT carries the owner-mode `attach` request row and ZERO * `eps.` rows, so its holder can ask for a grant it can never use. * * What that leaves is a genuine widening, and on a user mesh it is not bounded by "your own * children": {@link authorizeNamedControl}'s owner-domain arm admits any agent under the caller's * owner, spawned by anyone. So a spawn-scoped agent would gain blind WRITE into a sibling's * harness, a seat whose command line it did not choose. It can already `despawn` that sibling, * but killing a peer is denial; typing into a peer is control of it, and the two are different in * kind. `input` therefore rides the operator instrument set only * ({@link operatorInstrumentCapabilities}), where the holder is already the administrative * authority for the domain. */ export declare const SPAWN_CREATE_COMMANDS: readonly ["spawn"]; export declare const SPAWN_OWNER_LIFECYCLE_COMMANDS: readonly ["despawn", "attach"]; /** The two commands that WRITE INTO a seat, granted ONLY into operator-authorized credentials * (see the note above for why `input` is not in the spawn set; `turn` is the same authority * through a different door: a run's turn is a payload the seat is shown and works on, and the run * driver submits it under its own operator instrument, so it rides the same placement). Both * modes are minted here, unlike `despawn`/`attach`, whose owner-mode rows an operator inherits * from the spawn set: with these absent from that set an operator would otherwise hold the * any-mode row and not the owner-mode one, and the CLI rides OWNER reach on a user mesh (a * bearer's one deterministic path), as does the run driver's `turn`. Granting only `any` would * leave `cotal input`, and every run that turns a seat, broker-denied on exactly the mesh mode * the feature is for. Measured: no profile carried a `turn` row at all until it joined this set, * so a run on an auth mesh had its every turn submit dropped at the broker. */ export declare const OPERATOR_SEAT_COMMANDS: readonly ["input", "turn"]; /** The spawn capability's UNTARGETED additions (the 1c grant-migration table): the connector's * persona write (`define-persona`, caller-scoped by the pinned triple), per-agent status read * (`inspect` - the responder narrows the view to the caller's owner domain, like `ps`), and the * persona-catalog reads (`list-personas` / `show-persona`). These ride the v0.3 privileged tier * today; minting them with `spawn` keeps that tier's surface 1:1. */ export declare const SPAWN_SERVICE_COMMANDS: readonly ["define-persona", "inspect", "list-personas", "show-persona"]; /** The `run` capability's commands (SPEC 14.3): the manager-hosted workflow-run surface. The * three writes start a run, take one over and answer its open pause; the two reads list runs * and render one run's record and journal. All UNTARGETED: a run is not an agent, so no target * block names it, and the manager scopes what a caller may see by the run's own record. * A program can `spawn`, so the `run` capability implies the spawn set as well * ({@link runCallerCapabilities}): a caller that may start a program that spawns may spawn. */ export declare const RUN_WRITE_COMMANDS: readonly ["run-start", "run-resume", "run-answer"]; export declare const RUN_READ_COMMANDS: readonly ["run-status", "run-ps"]; /** The manager endpoint's read commands (`manager.read` class). */ export declare const MANAGER_READ_COMMANDS: readonly ["status", "ps", "inspect", "models", "list-personas", "show-persona"]; /** The manager endpoint's admin-class commands (`manager.admin`): capability-only + untargeted - * the broker grant (who holds the row) IS the boundary; minted ONLY into operator instruments, * NEVER an agent/spawn profile (the ratified 1c pin). */ export declare const MANAGER_ADMIN_COMMANDS: readonly ["purge", "launch", "resume-preserved", "commit-resume", "finalize-resume", "prepare-preservation", "commit-preservation", "abort-preservation"]; /** The ACTION commands (§13.6): submitting one accepts a GOAL, so the caller may follow its OWN * goal progress (P2 item 2). `spawn` (create) and `launch` (manifest) both serve as actions on * the manager endpoint since 2a; a caller holding one of these capabilities is granted the * per-goal live-progress read for that endpoint ({@link epGoalProgressGrantRow}), the one read an * invoke DOES imply because it is bounded to the caller's OWN goal subtree. */ export declare const GOAL_BEARING_COMMANDS: readonly ["spawn", "launch"]; /** RETRY SAFETY (§13.2): commands a client may execute a SECOND time after a responded-but-unbound * split, because a second execution is observably indistinguishable from one. Read only by * {@link isRepeatSafeCommand}, for `Endpoint.invokeService`. * * An allowlist rather than a denylist so it fails CLOSED: an unclassified command surfaces the * split to its caller instead of running twice. A denylist would auto-retry the next admin command * someone adds above, silently. * * Keyed by endpoint, not by bare command name, because `invokeService` is endpoint-agnostic: a * flat name list would hand a third-party endpoint's `list` or `ps` a judgement made about the * manager's. An unknown endpoint has no repeat-safe commands. * * Written out literally rather than derived from {@link MANAGER_READ_COMMANDS}, because retry * safety and grant tiers answer different questions and must be able to disagree. `models` is the * case that forces it: it reads a catalog unless called with `{refresh: true}`, which shells out * and rewrites a cache, so the answer turns on an ARGUMENT this table cannot see. Per-command * argument rules here would be the fail-open shape again, so `models` is simply not listed. * Convergence is not sufficient either: `despawn` converges, but its second run despawns whatever * now holds the name. * * **THIS TABLE MUST NOT SURVIVE `protocol.v: 2`.** §13.7 `effect` is the command author's own * declaration, and allowlist-says-safe could then contradict author-declares-`write`. It cannot * reach the wire in this tree — `endpoint-serve.ts` pins the descriptor to `v: { const: 1 }` — so * this table stands in for a field no responder here can emit rather than competing with one, and * it derives nothing from a descriptor, which is the part §13.7 forbids. `smoke:unfenced-responder` * tripwires that pin so the version cannot move without this table being named. */ export declare const REPEAT_SAFE_COMMANDS: Readonly>; /** True only for a command whose re-execution is observably harmless on THAT endpoint * ({@link REPEAT_SAFE_COMMANDS}). An unknown endpoint, or an unlisted command, is not repeat-safe: * the intended default, not an oversight. */ export declare function isRepeatSafeCommand(endpoint: string, command: string): boolean; /** `describe` on ALL endpoints (Appendix B / §13.9 "describe by default"): the ONE * subject-wildcard request form in the caller grammar, * `ep.one.*.describe....*` — the endpoint token is the wildcard, the command is * the literal reserved `describe`, and the caller triple stays pinned. DELIBERATELY not an * {@link EpCapability} (whose endpoint is a validated literal): a wildcard-endpoint capability * would generalize to arbitrary commands, and the baseline is the only place the wildcard form * is normative. Untargeted only — describe is constructed untargeted on every serve * (§13.7), so no authz/target block ever appears in the row. */ export declare function epDescribeAllGrantRow(space: string, caller: EpCaller): string; /** The baseline {@link EpCapability} set every agent holds (Appendix B) beyond the wildcard * describe row: delivery join/leave/list (untargeted) + self-mode lifecycle. */ export declare function baselineCallerCapabilities(): EpCapability[]; /** The `spawn` capability's addition (Appendix B): the manager endpoint's lifecycle commands. * `spawn` (creation) is UNTARGETED — a virgin child has no lifecycle UID to resolve against the * current mapping, so an owner-mode row would be un-invokable under the verb grammar (§13.2). The * three that act on an existing agent ride owner mode, target owner pinned to the CALLER's own * (§13.2: an owner-mode standing mint never names a foreign owner). */ export declare function spawnCallerCapabilities(callerOwner: string): EpCapability[]; /** The `run` capability's addition (SPEC 14.3): the five untargeted `run-*` commands PLUS the * whole spawn set. The implication is deliberate and one-way: a program is free to `spawn`, so a * caller that may start one must hold what the program's spawns need, and the manager checks * nothing weaker at `run-start`; a `spawn`-only caller gains no run row from this. */ export declare function runCallerCapabilities(callerOwner: string): EpCapability[]; /** An operator INSTRUMENT's capability set (the 1c grant-migration table's admin row), per the * instrument's v0.3 control tier - the SAME mint sites that grant a `ctl.` row today * (`control-caller-*` / `deployer`) consume this for the ep rails; no new minting authority. * * `privileged` (the ps/start instrument): the manager reads (incl. persona catalog list/show) + * untargeted `spawn` + `define-persona` - structurally barred from cross-agent reach, exactly like its ctl row. * * `admin` (the stop/attach/deploy instrument): everything above plus ANY-mode `despawn`/`attach` * (tOwner `"*"`), BOTH modes of `input` (which no other profile grants at all), and the * `manager.admin` command family. The 1c admin-reach decision: operator * cross-agent terminal/interactive ops ride authz-mode `any` on the SAME commands (no wire * synonym) - the any-mode subject row is minted ONLY into operator-authorized credentials: the * `control-caller-admin`/`deployer`/`teardown` instruments AND an agent credential explicitly * granted the `admin` capability (which by design mirrors the full admin instrument set - its * ctl-tier equivalent already held `ctl.`, so this is parity, not a new escalation). An * ordinary agent, incl. the `spawn` capability, never carries it. So the broker grant is the tier boundary exactly as * `ctl.` is today, and the responder maps mode `any` to its admin authorization path. */ export declare function operatorInstrumentCapabilities(tier: "privileged" | "admin", callerOwner?: string): EpCapability[]; /** The SAME tier set, pinned to NAMED instances — the issuance `--on ` was always meant * to get. These instruments are ONE-SHOT, minted per control call, and the resolve that chose the * instance runs BEFORE the mint, so the exact id can be handed down and the emitter's * `if (cap.instanceId)` branch produces exactly `ep.inst...` for THIS * invocation and nothing else. No wildcard instance is minted anywhere, which is what keeps the * `inst-route-grant` boundary intact: instance addressing stays with the per-invocation operator * instruments that already hold it, and a plain, spawn-capable, or observer credential still gets * no instance route at all. * * SEVERAL ids are accepted, and that does NOT relax the rule above. `cotal ps` scatters, so it has * no single instance to pin — but it FREEZES the class first, and a frozen set is a list of exact * ids known before the mint, which is the same precondition `--on` satisfies with one. Each id * still emits its own concrete rows; the count changes, the shape does not. The alternative * considered and rejected was a wildcard instance row for the tier, which is a widening three * review seats already refused and which `inst-route-grant` asserts against by shape. * * `describe` is included EXPLICITLY. The baseline describe row is class-rail only * ({@link epDescribeAllGrantRow}), so without this the pinned RESOLVE that must precede a pinned * invoke is refused at the broker — and refused invisibly, because the client renders that refusal * as a describe timeout. Here it is a concrete endpoint+instance capability, not the normative * wildcard form, so the exact-arity discipline of the caller grammar is preserved. It is also what * the §13.5 scatter's liveness probe publishes, so a frozen instance the broker has to be asked * about is reachable at all. */ export declare function instancePinnedInstrumentCapabilities(tier: "privileged" | "admin", instanceId: string | string[]): EpCapability[]; /** All BASELINE caller rows (Appendix B): the wildcard describe form + the baseline capability * rollup into `pub.allow`, and the caller's reply rail into `sub.allow` — ALWAYS present (the * baseline implies the reply read even when no per-capability rows are minted). The §13.7 * contract-store FETCH (the Direct Get API on the EPC stream) rides the baseline too: describe * answers digests, and a caller that may describe may fetch-verify-compile the schemas those * digests name (content-addressed public artifacts — a digest is the read capability; the * per-caller authorization surface is the describe VIEW, never the schema bytes). */ export declare function epBaselineGrantRows(space: string, caller: EpCaller): { pub: string[]; sub: string[]; }; /** One registered command's serve-subscribe rows (§13.9 "Serve subscribe"), per registered * command and never a cross-command `>`: * - class rail: `"ep.one...> "` — QUEUE-QUALIFIED ONLY (the NATS * `subject queue` grant form): no credential can plain-subscribe the class rail, which is * what keeps per-request nonces visible only to the queue-selected instance; * - scatter rail: `ep.all...>` plain; * - instance rail: `ep.inst....>` exact. * The epoch is deliberately absent from serve subscriptions (§13.1's barrier is the fence). */ export declare function epServeSubscribeRows(space: string, endpoint: string, instanceId: string, command: string): string[]; /** A serving instance's egress rows (§13.9 matrix): reply publish (attribution-pinned instance * triple + epoch), events, timer SCHEDULE requests (never `.armed`/`.fire`), and the epoch-pinned * record-write ingress. Every row pins the instance's own identity and epoch. */ export declare function epServePublishRows(space: string, endpoint: string, instanceId: string, epoch: number): string[]; /** All serve-credential subject-space rows for an instance. `ephemeralCommands` is the * RAIL-SERVED (ephemeral) subset only — journal commands stay in the credential's descriptor * surface but ride `epj` submissions, never the §13.2 request rails, so they take no rail * subscribe row here (their effects/pool durable binds ride the §13.12 stream binding). The * reserved `describe` is DERIVED here — every endpoint serves it (§13.7), so this ONE assembly * seam emits its rails for every serve credential (even a journal-only endpoint, whose * `ephemeralCommands` is empty) and an explicit `describe` refuses (mirroring * {@link import("./endpoint-serve.js").serveEndpoint}'s construction rule: there is no custom * describe). The subscribe side also carries the instance's OWN epoch-pinned timer FIRE row * (§13.9 "Timer fire consume": `ept....*.fire` — consume only; the publish side * stays `.schedule`-only, no credential publishes `.armed`/`.fire`). */ export declare function epServeGrantRows(space: string, serve: { endpoint: string; instanceId: string; epoch: number; ephemeralCommands: string[]; }): { pub: string[]; sub: string[]; }; //# sourceMappingURL=endpoint-grants.d.ts.map