/** * Durable read-ACL registry — read/write helpers over the per-space ACL KV bucket * (`cotal_acl_`). One {@link AclRecord} per LIFECYCLE under {@link aclKey} * (`..`, SPEC §13.1), holding that incarnation's * current read ACL (`allowSubscribe`). This is the **keystone** that lets the Plane-3 trusted reader * run in a stateless, server-side **delivery daemon**: the reader re-authorizes every durable entry * against the owner's ACL read FRESH from here (not the manager's in-memory ledger), so a daemon * restart re-reads the truth instead of nak-looping every unknown owner to `term()`. * * Writes are **privileged** — the manager records an agent's ACL at mint time (the same act as baking * it into the JWT); agent-authored ACLs are forbidden (they would self-authorize reads). Every write * is a single ATOMIC CAS put of the whole value, so a present record is always complete: a present * `allowSubscribe: []` is a known "reads nothing" policy (the reader DROPS), distinct from an ABSENT * record (a genuinely-unknown owner — the reader DEFERS, never drops). */ import { type KV } from "@nats-io/kv"; import type { AclRecord } from "./types.js"; /** Open the ACL registry bucket. Auth mode OPENs the bucket pre-created at `cotal up`; a privileged * caller may pass `{ create: true }` to lazily CREATE it. Mirrors {@link openMembersRegistry}. */ export declare function openAclRegistry(nc: import("@nats-io/transport-node").NatsConnection, space: string, opts?: { create?: boolean; }): Promise; /** * Read one owner's read-ACL record, or `undefined` if there is NO usable record — absent, deleted, * undecodable, or missing the `allowSubscribe` array. The reader maps that `undefined` to DEFER (an * unknown owner, e.g. a pre-provision race — never dropped). A PRESENT record returns its * `allowSubscribe` as-is, **including `[]`** (a known no-read policy → DROP). The CAS revision is * returned alongside for a read-modify-write. */ export declare function readAcl(kv: KV, owner: string, lifecycleUid: string): Promise<{ record: AclRecord; revision: number; } | undefined>; /** Error for an alias with MORE than one live ACL row: §13.1's invariant is at most one live * lifecycle per alias, so two rows are split-brain evidence (a reservation breach or an unfinished * teardown), and an alias-level authorizer MUST refuse loudly rather than pick one. */ export declare class AmbiguousAclAlias extends Error { readonly principal: string; readonly lifecycleUids: string[]; constructor(principal: string, lifecycleUids: string[]); } /** * Resolve an ALIAS (`.` dot-form) to its single live lifecycle-keyed ACL row — the * bounded prefix enumeration for callers that hold no lifecycle UID (a runtime durable-join authz). * Returns `undefined` when NO live row exists (unknown alias — the caller DEFERS/refuses), the row + * its uid when exactly ONE does, and THROWS {@link AmbiguousAclAlias} on two or more: taking * first-match would let a stale row authorize (or de-authorize) the successor. Keys that do not parse * as `..` are ignored (foreign shapes never authorize). */ export declare function readAclForAlias(kv: KV, principal: string): Promise<{ record: AclRecord; revision: number; lifecycleUid: string; } | undefined>; /** * Raise the mint-time history ceiling (`issuedAllowSubscribe`) to match `allowSubscribe`. * * CALL PATH: only {@link provisionAgent} (and tests of that path). Ordinary registry writers use * {@link commitAcl}, which cannot raise the ceiling — a boolean flag on commitAcl would let any * DurableProvisioner holder re-open the ACL-authority hole. Separate function = separate call path. * * PROCESS DISCIPLINE, NOT CRYPTO BINDING: this write does not verify that a broader JWT was minted. * A caller who can reach `reissueAcl` can raise the ceiling while leaving the live credential * narrow, and mediated history will then serve channels `channelHistory` still broker-denies. * That is accepted residual: whoever holds the provisioner can already mint arbitrary JWTs. The * obligation is that `reissueAcl` may ONLY ride the same act that bakes `allowSubscribe` into the * user JWT (provision/remint). Do not call it from revoke, repair, or any path that does not also * remint. Docs must not claim the ceiling is bound to credential bytes. */ export declare function reissueAcl(kv: KV, owner: string, lifecycleUid: string, allowSubscribe: string[]): Promise; /** * Write the live read ACL. Never raises the mint-time ceiling: create sets ceiling = allow; * updates that exceed the ceiling throw. For a legitimate broaden that also remints the JWT, use * {@link reissueAcl} from the provisioning path only. */ export declare function commitAcl(kv: KV, owner: string, lifecycleUid: string, allowSubscribe: string[]): Promise; /** Permanently remove one LIFECYCLE's ACL row (GC / footprint deletion — revocation deletes the * footprint AFTER invalidating creds). Lifecycle-exact by construction: a replayed delete for a * retired lifecycle names a key the successor's row does not share. Distinct from a * `commitAcl(kv, owner, uid, [])` write, which keeps a present "no-read" record so the reader DROPS * (vs. DEFER for an absent owner). */ export declare function deleteAcl(kv: KV, owner: string, lifecycleUid: string): Promise; //# sourceMappingURL=acls.d.ts.map