/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { Dr as RequestType, Fr as MethodSchema, I as SigningCallCtx, M as CapProvider, Mt as IRequestSender, Nr as HubRpcInterfaceSchema, P as ManagedSigningChannel, Ut as IMessageTransport, V as Principal, kt as Channel, mr as InterfaceDefinition, pr as InterfaceClient, s as RootPrincipalSet } from "../../chunks/hubRpcConnection-Ba6dm9d-.js"; import { a as HubAccessResult, i as HubAccessRequest, n as HubAccessPattern, o as findCoveringCapabilities, r as HubAccessPermission, t as HubAccessDuration } from "../../chunks/hubAccess-DDeQLWpk.js"; //#region src/hub/common/serviceId.d.ts /** * A **ServiceId** is a `'/'`-segmented address naming a routing destination * on a {@link Hub}. The empty string is the **root** (the hub's own / local * services); every other id is one or more non-empty segments joined by * `'/'`. * * Examples: * - `""` → root (valid) * - `"foo"` → valid * - `"foo/bar"` → valid * - `"/"` → invalid (empty segments) * - `"/foo"` → invalid (leading separator) * - `"foo/"` → invalid (trailing separator) * - `"foo//bar"` → invalid (empty interior segment) * * It is a plain `string` alias — the name exists only to mark the role at * call sites. Use {@link isValidServiceId} / {@link splitServiceId} to work * with it structurally. */ type ServiceId = string; /** The root service id — the hub's own local services. */ declare const ROOT_SERVICE_ID: ServiceId; /** The separator between service id segments. */ declare const SERVICE_ID_SEPARATOR = "/"; /** * Whether `id` is a well-formed {@link ServiceId}. The root (`""`) is * valid; any other value must be non-empty segments joined by single * `'/'`s, with no leading, trailing, or empty segments. */ declare function isValidServiceId(id: string): boolean; /** * Split a {@link ServiceId} into its segments. The root (`""`) yields the * empty array; `"foo/bar"` yields `["foo", "bar"]`. * * Does not validate — pair with {@link isValidServiceId} when the input is * untrusted. */ declare function splitServiceId(id: ServiceId): string[]; /** * Whether `serviceId` is equal to or nested beneath `prefix` (segment-aware): * `"a/b"` covers `"a/b"` and `"a/b/c"` but **not** `"a/bc"`. The root prefix * (`""`) covers everything. */ declare function isServiceIdUnder(serviceId: ServiceId, prefix: ServiceId): boolean; //#endregion //#region src/hub/common/transportServer.d.ts /** * A link the hub can route, plus a close signal. {@link IMessageTransport} * on its own has no "closed" event (it only learns of teardown through its * own `dispose`), but a *server*-produced connection must be able to tell * downstream consumers when the remote end goes away so overlays can be torn * down and prefixes released. {@link Transport} adds exactly that. */ interface Transport extends IMessageTransport { /** * Register a handler fired exactly once when the transport closes (remote * hang-up or local {@link IMessageTransport.dispose}). Handlers added * after close fire on the next microtask. */ onDidClose(handler: () => void): void; } /** * A source of inbound {@link Transport}s — the single seam every transport * backend (UDS socket, websocket, iframe postMessage, in-process pair) * implements. The hub side consumes only this; it never names `net.Socket` * or any backend-specific type. */ interface ITransportServer { /** * Install the handler invoked once per accepted transport. Replacing the * handler is allowed; only the most recent one receives new connections. */ setConnectionHandler(handler: (transport: T) => void): void; dispose(): void; } /** * Lift a transport server from emitting `T1` to emitting `T2`. The `map` may * be async (e.g. to attest a peer before exposing it) and may return * `undefined` to **drop** a connection — the downstream handler is simply not * invoked for it. The transport's identity is preserved when the map returns * the same object (important: the hub keys routing state on the transport * reference), so prefer annotating in place over wrapping. */ declare function mapTransport(source: ITransportServer, map: (transport: T1) => T2 | undefined | Promise): ITransportServer; //#endregion //#region src/hub/common/hub.interfaces.d.ts /** * `hubServiceIdRegistry::registerServiceId` — a participant claims a prefix * **outside** its provenance-granted namespace. * * Reached under the hub's own service id (form-3 * `::hubServiceIdRegistry::registerServiceId`) and gated by an * admin-rooted capability. For claims **within** the connection's granted * namespace, use the cheaper, capability-free `hubGrantedServiceId::register` * instead. */ declare const hubServiceIdRegistryInterface: InterfaceDefinition<{ registerServiceId: RequestType<{ requestedPrefix: string; }, Record, any, never, never>; }>; /** * `hubGrantedServiceId` — the ungated connection surface, served at the * connection root on each participant's overlay (so it is reachable directly, * never forwarded, and needs no capability of its own). Two jobs: * * - `get` (unsigned) reports the topology facts the hub decided for this * connection — where it is and what it may claim. * - `register` (provenance-gated) claims a prefix **within** * this connection's granted namespace — the capability-free claim path. * Claims outside the namespace go through the admin-gated * `::hubServiceIdRegistry::registerServiceId` door instead. * - `getHubServiceId` (unsigned) reports the serviceId prefix the hub mounts * its own global services under — the prefix to address the admin-gated * registry and reflection endpoints through. Served at the connection root * so a participant can discover it **before** it knows where the hub lives. * * The hub's consent front door (`hubAccess::*`) is served at the connection * root too, so it needs no bootstrap capability and is reached directly. */ declare const hubGrantedServiceIdInterface: InterfaceDefinition<{ /** * Connection facts (unsigned). The participant pulls, on each * (re)connect, the topology facts the hub has decided for this * connection: * * - `grantedServiceIdNamespace` — the absolute serviceId region this * connection's provenance may claim (anything at/under it). May be * the empty string, meaning "claim nothing freely". */ get: RequestType, { grantedServiceIdNamespace: string; }, any, never, never>; /** * The serviceId prefix the hub mounts its own global services under * (default `'hub'`). Use it to address the admin-gated * `::hubServiceIdRegistry::registerServiceId` door and the * hub's reflection endpoints. Served at the connection root (unsigned), * so a participant can learn it without first knowing where the hub * lives. */ getHubServiceId: RequestType, { hubServiceId: string; }, any, never, never>; /** * Claim a serviceId prefix **within** this connection's provenance- * granted namespace (see `get().grantedServiceIdNamespace`). No * capability needed — the grant already happened out-of-band at attach * time. The requested `serviceId` must equal the granted namespace or be * nested beneath it; anything else is rejected (claim it through the * admin-gated `::hubServiceIdRegistry::registerServiceId` * door instead). */ register: RequestType<{ serviceId: string; }, Record, any, never, never>; }>; /** * `hubAccess::request` — a consumer (e.g. a sandboxed web editor) asks the * hub for scoped access to one or more services. * * Consumers describe their needs as named *dependencies* ("slots"): each * slot lists the interfaces the chosen service must implement and the * methods the consumer wants to call. The hub resolves candidate services * from its participant directory, then forwards the bundle to a host- * supplied handler (see `Hub` options) that shows the user a single * prompt. The handler picks a concrete service per slot and approves a * subset of the requested methods. * * In v1 the response carries only the resolution (which serviceId was * chosen per slot). Once the hub holds a signing identity it will also * return a `SignedCapability` the consumer attaches to subsequent calls. * Until then, dispatch is not gated on the grant — see plan-access.md. */ declare const hubAccessInterface: InterfaceDefinition<{ request: RequestType<{ consumer: { name: string; principal: string; origin?: string | undefined; purpose?: string | undefined; }; dependencies: Record; duration?: "once" | "shortLived" | "longLived" | "persistent" | undefined; }, { status: "granted"; slots: Record; capabilities: { issuer: string; audience: string; permissions: { target: { serviceId: { exact: string; } | { prefix: string; }; interfaceId: { exact: string; } | { prefix: string; }; members: ({ exact: string; } | { prefix: string; })[]; interfaceHash?: string | undefined; }; canInvoke?: boolean | undefined; canDelegate?: boolean | undefined; params?: Record | undefined; callBind?: { alg: "sha256"; payloadHash: string; } | undefined; }[]; nonce: string; $hubrpcSignature: { capability?: { keyId: string; sig: string; } | undefined; call?: { keyId: string; sig: string; } | undefined; }; expiresAtMs?: number | undefined; parentHash?: string | undefined; }[]; } | { status: "denied"; reason?: string | undefined; } | { status: "noCandidates"; slots: string[]; }, any, never, never>; /** * Service-pinned widening of an existing grant. The consumer asks * the hub for additional members on a `serviceId` they already * deal with — same audience (their NodeId) and (intended) same * `rootIssuer` as the prior grant. The hub never picks the service * for the consumer here: `serviceId` is an input, not a result. * * On grant the response carries a fresh `SignedCapability` whose * attenuations cover **only** the granted delta. Bag-compatible * with the prior cap; combine via `merge` (when it exists) or * just keep both in `$hubrpc.capabilities`. * * Distinguished from `request` so the consent UI can render a * different affordance ("X already has read access on `github`, * grant `update` as well?" instead of from-zero selection). * * TODO(hub-ledger): enforce "consumer has prior history on this * service" — see `hub.ts:_handleAccessExtend`. v1 forwards * directly to the host's `onAccessExtend` without consulting the * `_grants` ledger; this is by design while we settle on the * persistence model. */ extend: RequestType<{ consumer: { name: string; principal: string; origin?: string | undefined; purpose?: string | undefined; }; serviceId: string; added: { interfaceId: string; member: { exact: string; } | { prefix: string; }; required?: boolean | undefined; }[]; duration?: "once" | "shortLived" | "longLived" | "persistent" | undefined; }, { status: "granted"; serviceId: string; granted: { interfaceId: string; member: { exact: string; } | { prefix: string; }; }[]; capabilities?: { issuer: string; audience: string; permissions: { target: { serviceId: { exact: string; } | { prefix: string; }; interfaceId: { exact: string; } | { prefix: string; }; members: ({ exact: string; } | { prefix: string; })[]; interfaceHash?: string | undefined; }; canInvoke?: boolean | undefined; canDelegate?: boolean | undefined; params?: Record | undefined; callBind?: { alg: "sha256"; payloadHash: string; } | undefined; }[]; nonce: string; $hubrpcSignature: { capability?: { keyId: string; sig: string; } | undefined; call?: { keyId: string; sig: string; } | undefined; }; expiresAtMs?: number | undefined; parentHash?: string | undefined; }[] | undefined; } | { status: "denied"; reason?: string | undefined; }, any, never, never>; /** * `hubAccess::requestAccess` — direct capability request. The * consumer specifies the exact attenuations it wants. No * service-discovery, no candidate resolution: the consumer * already knows which `(serviceId, interfaceId, members)` it * needs, including wildcards (e.g. `serviceId: { prefix: "" }` * to ask for an interface anywhere). * * Compared to `request`: * - `request` does directory-based discovery, picks one service * per slot, and returns a cap pinned to that service. Use * when the consumer says "give me SOME service that does X". * - `requestAccess` is verbatim. Use when the consumer says * "give me exactly these attenuations". Especially useful for * reflection (`hubrpc.directory::list` on any service) and * for on-demand per-method grants from an explorer-style UI. * * The user prompt shows the exact `Capability` the hub will sign * on Allow, same byte-equality guarantee as `request`/`extend`. */ requestAccess: RequestType<{ consumer: { name: string; principal: string; origin?: string | undefined; purpose?: string | undefined; }; permissions: { target: { serviceId: { exact: string; } | { prefix: string; }; interfaceId: { exact: string; } | { prefix: string; }; members: ({ exact: string; } | { prefix: string; })[]; interfaceHash?: string | undefined; }; canInvoke?: boolean | undefined; canDelegate?: boolean | undefined; params?: Record | undefined; callBind?: { alg: "sha256"; payloadHash: string; } | undefined; callIntent?: { method: string; nonce: string; signedAtMs: number; params?: unknown; interfaceHash?: string | undefined; summary?: string | undefined; suggestion?: "once" | "shortLived" | "longLived" | "persistent" | undefined; } | undefined; }[]; duration?: "once" | "shortLived" | "longLived" | "persistent" | undefined; }, { status: "granted"; capabilities: { issuer: string; audience: string; permissions: { target: { serviceId: { exact: string; } | { prefix: string; }; interfaceId: { exact: string; } | { prefix: string; }; members: ({ exact: string; } | { prefix: string; })[]; interfaceHash?: string | undefined; }; canInvoke?: boolean | undefined; canDelegate?: boolean | undefined; params?: Record | undefined; callBind?: { alg: "sha256"; payloadHash: string; } | undefined; }[]; nonce: string; $hubrpcSignature: { capability?: { keyId: string; sig: string; } | undefined; call?: { keyId: string; sig: string; } | undefined; }; expiresAtMs?: number | undefined; parentHash?: string | undefined; }[]; } | { status: "denied"; reason?: string | undefined; }, any, never, never>; }>; /** * `hubAccessManifest` — the declarative twin of {@link hubAccessInterface}. * * Where `hubAccess` is the imperative, just-in-time door a consumer *calls* (and * the hub serves at the connection root), `hubAccessManifest` is **served by the * participant** under its own serviceId, so it appears in `hubrpc.directory::list` * — its very presence is the request. A participant publishes its DESIRED access * entries (keyed by id, like `request`'s `dependencies`); an admin discovers * them via the directory, mints capabilities **with its own identity** (a * configured hub capability root), and writes the CURRENT/granted state back via * patches. The participant reads the granted entries and attaches the caps to * its later calls. * * Reconcile model (desired vs. current), aligned with the hub's other surfaces: * - `getDesired` / `watchDesired` — the participant's declared needs. * - `getCurrent` / `setCurrent` / `watchCurrent` — the admin-written grants. * * `watch*` follows the coarse empty-tick convention of `hubrpc.directory::watch`: * a tick means "re-`get` now", keeping the server stateless (no per-item deltas). */ declare const hubAccessManifestInterface: InterfaceDefinition<{ /** The full desired document: who is asking and the entries it wants. */ getDesired: RequestType, { requested: Record | undefined; } | { kind: "direct"; consumer: { name: string; principal: string; origin?: string | undefined; purpose?: string | undefined; }; permissions: { target: { serviceId: { exact: string; } | { prefix: string; }; interfaceId: { exact: string; } | { prefix: string; }; members: ({ exact: string; } | { prefix: string; })[]; interfaceHash?: string | undefined; }; canInvoke?: boolean | undefined; canDelegate?: boolean | undefined; params?: Record | undefined; callBind?: { alg: "sha256"; payloadHash: string; } | undefined; callIntent?: { method: string; nonce: string; signedAtMs: number; params?: unknown; interfaceHash?: string | undefined; summary?: string | undefined; suggestion?: "once" | "shortLived" | "longLived" | "persistent" | undefined; } | undefined; }[]; reason?: string | undefined; duration?: "once" | "shortLived" | "longLived" | "persistent" | undefined; acceptableRootIds?: string[] | undefined; origin?: Record | undefined; }>; revision: number; }, any, never, never>; /** * Coarse change tap on the desired document. Emits an empty tick when * `requested` may have changed; the caller re-`getDesired`. Resolves when * the caller cancels. Mirrors `hubrpc.directory::watch`. */ watchDesired: RequestType, Record, void, any, Record>; /** The full current document: entryId → granted/denied (absent ⇒ undecided). */ getCurrent: RequestType, { current: Record | undefined; callBind?: { alg: "sha256"; payloadHash: string; } | undefined; }[]; nonce: string; $hubrpcSignature: { capability?: { keyId: string; sig: string; } | undefined; call?: { keyId: string; sig: string; } | undefined; }; expiresAtMs?: number | undefined; parentHash?: string | undefined; }[]; } | { kind: "direct"; capabilities: { issuer: string; audience: string; permissions: { target: { serviceId: { exact: string; } | { prefix: string; }; interfaceId: { exact: string; } | { prefix: string; }; members: ({ exact: string; } | { prefix: string; })[]; interfaceHash?: string | undefined; }; canInvoke?: boolean | undefined; canDelegate?: boolean | undefined; params?: Record | undefined; callBind?: { alg: "sha256"; payloadHash: string; } | undefined; }[]; nonce: string; $hubrpcSignature: { capability?: { keyId: string; sig: string; } | undefined; call?: { keyId: string; sig: string; } | undefined; }; expiresAtMs?: number | undefined; parentHash?: string | undefined; }[]; }; } | { status: "denied"; reason?: string | undefined; }>; revision: number; }, any, never, never>; /** * Apply patches to the current document. Replace the whole document with * `{ op: 'set', path: '', value }`, or a single entry with * `{ op: 'set', path: '/current/', value }` (a `zCurrentEntry`: * granted or denied). Admin-only in practice (gated by a capability * rooted at an accepted issuer). */ setCurrent: RequestType<{ patches: ({ op: "set"; path: string; value: unknown; } | { op: "remove"; path: string; })[]; }, { revision: number; }, any, never, never>; /** * Coarse change tap on the current document. Emits an empty tick when * `current` may have changed; the participant re-`getCurrent` and applies * any new capabilities. Resolves when the caller cancels. */ watchCurrent: RequestType, Record, void, any, Record>; }>; /** * The typed client shape of {@link hubAccessManifestInterface} — the exact * object `connection.get(hubAccessManifestInterface)` (or * `connection.service(id).get(...)`) returns. Approvers depend on this contract, * not on a concrete connection: the same approver runs against a local in-memory * host (loopback connection), a remote hub's served manifest, or a future * aggregating implementation with no code change. */ type IHubAccessManifest = InterfaceClient; /** One typed entry from `hubAccessManifest::getDesired().requested`. */ type HubAccessManifestRequest = Awaited>['requested'][string]; /** One typed value accepted at `/current/` by `setCurrent`. */ type HubAccessManifestDecision = Awaited>['current'][string]; //#endregion //#region src/hub/common/baseCapabilities.d.ts /** * Claim a serviceId prefix within this connection's provenance-granted * namespace via `hubGrantedServiceId::register` (no capability needed). * Resolves once the claim is registered. Rejects when the prefix is outside * the granted namespace or already owned. */ declare function registerGrantedServiceId(sender: IRequestSender, serviceId: string): Promise; //#endregion //#region src/hub/common/managedSigning.d.ts /** Who is asking — surfaced in the hub's consent prompt. */ interface AutoNegotiateConsumer { readonly name: string; readonly origin?: string; readonly purpose?: string; } /** Options for {@link createManagedSigningChannel}. */ interface ManagedSigningOptions { /** * When set, install a sign-time {@link CapProvider} that lazily negotiates * the capability each gated call needs through the hub's `hubAccess` * consent front door. Durable grants are absorbed into the principal's cap * bag so later calls present them automatically; one-shot grants are * attached to just the call that prompted them. * * Without it, the channel signs every call but presents no capabilities — * gated calls then fail with `permissionRequired` unless the caller has * arranged a capability some other way. */ readonly autoNegotiateCaps?: boolean; /** Consumer identity shown in the consent prompt. */ readonly consumer?: AutoNegotiateConsumer; } /** * Build a managed-identity signing {@link Channel} from a raw channel, with * optional per-call capability auto-negotiation. * * Like {@link SigningSender.fromChannelWithManagedPrincipal}, the * `identity::*` bootstrap rides the raw (unsigned) sender, and the returned * signing channel is what callers hand to `HubRpcConnection`. When * {@link ManagedSigningOptions.autoNegotiateCaps} is set, the returned * channel additionally negotiates capabilities on demand — the browser-safe * equivalent of the CLI's `setupSigning({ autoNegotiatePerCall: true })`. */ declare function createManagedSigningChannel(channel: Channel, opts?: ManagedSigningOptions): Promise>; /** * A sign-time {@link CapProvider} that negotiates access per gated call. * * For each outbound call it: presents any fresh caps already in the bag; if * none cover the call, bootstraps the root `hubAccess` capability (once), then * asks `hubAccess::requestAccess` for a grant scoped to exactly this call * (`callIntent` pinned to the method/params/nonce). Durable grants are added to * the bag; a one-shot grant is attached to just this call. * * Fail-soft: any negotiation error (open hub, denied consent, unreachable front * door) falls back to presenting the current bag, letting the call surface * `permissionRequired` if it is truly gated. */ declare function createAutoNegotiatingCapProvider(opts: { readonly sender: IRequestSender; readonly principal: Principal; readonly consumer: AutoNegotiateConsumer; }): CapProvider; //#endregion //#region src/hub/common/directoryWalk.d.ts /** * Portable reflection walk over the `hubrpc.directory` referral tree. * * The hub's global directory is **referral-only**: it lists one * `::hubrpc.directory` row per claimed prefix rather than the prefix's * leaf interfaces. Flattening that tree into the full interface inventory is the * consumer's job — {@link walkHubDetailed} performs the breadth-first walk and * is shared by the CLI (`hubrpc ls`, completions, the UI) and the hub's own * access-candidate resolution (`fetchFullDirectory`). */ /** * The sender reflection helpers speak over: the signing decorator that wraps * the live channel. Decoupled from the concrete `JsonRpcChannel` so reconnect * can swap the underlying channel transparently. */ type ReflectionChannel = IRequestSender; interface ServiceListing { readonly serviceId: string; readonly interfaceId: string; readonly hash: string; readonly path?: string; /** Optional non-normative description of the owning service. */ readonly serviceDescription?: string; /** * Root node ids required to access the owning service, in CNF. Surfaced by * the directory; {@link walkHubDetailed} additionally folds transitive * requirements from ancestor directories onto descendants. */ readonly rootPrincipalSets?: readonly RootPrincipalSet[]; } /** * A {@link ServiceListing} enriched with the serviceId of the directory that * reported it. The CLI uses `discoveredFrom` as the routing target for * follow-up reflection (`hubrpc.schemas::get`) — because the directory that * listed the interface is the one that actually knows about it, even if the * item's own `serviceId` says otherwise (e.g. a hub forwarding an aggregated * reference). */ interface DiscoveredListing extends ServiceListing { readonly discoveredFrom: string; } interface ListOptions { readonly interfaceId?: string; readonly serviceId?: string; readonly limit?: number; readonly timeoutMs?: number; /** * When set, send the reflection call to that service via form-3 * (`::hubrpc.directory::list`) instead of the implicit root * directory. Used when talking to a hub: the root directory is the hub * itself, but per-service reflection lives on each participant. */ readonly target?: string; } declare function fetchDirectory(channel: ReflectionChannel, opts?: ListOptions): Promise; declare function fetchSchema(channel: ReflectionChannel, interfaceId: string, hash: string | undefined, /** * Optional routing target. When set, the schema request is addressed to * `::hubrpc.schemas::get` (form-3) so it reaches the service that * actually hosts this interface — needed when talking to a hub and the * interface lives behind a participant. */ target?: string): Promise; declare function findMethodInSchema(schema: HubRpcInterfaceSchema, methodName: string): MethodSchema | undefined; /** Default recursion depth when walking the bus. */ declare const DEFAULT_WALK_DEPTH = 5; /** * A sub-directory the walk surfaced but could not enumerate — typically because * it is capability-gated (e.g. the `hub` directory, reachable only once the * connection holds a capability for it). The services it would have listed are * therefore absent from the walk; callers can surface `reason` to explain the * gap rather than silently dropping the branch. */ interface InaccessibleDirectory { /** The directory target (serviceId) that could not be enumerated. */ readonly serviceId: string; /** The error message from the denied directory lookup. */ readonly reason: string; } interface WalkHubResult { /** Every interface reachable from the directories the walk could read. */ readonly listings: DiscoveredListing[]; /** * Sub-directories that were referenced but could not be enumerated (e.g. * capability-gated). Their services are not present in `listings`. */ readonly inaccessible: InaccessibleDirectory[]; } /** * Recursive bus walk: list a directory, then for each `hubrpc.directory` * reference it surfaces on a service we haven't queried yet, recurse. Bounded * by `maxDepth`. * * Every listing is tagged with `discoveredFrom` — the serviceId of the * directory that produced it. When the same `(serviceId, interfaceId, hash)` * shows up via several directories (e.g. once forwarded by the hub, once * directly from the participant), we keep the one whose `discoveredFrom` * matches the item's `serviceId`, since that's the directory that * authoritatively knows about it. * * Transitive root-node-id requirements flow down the tree: when the walk * recurses into a directory whose own `rootPrincipalSets` include `transitive` * reqs, every interface discovered at or below that directory inherits them (as * singleton AND-sets, kept transitive so they keep flowing further down). This * replaces the hub-side `applyTransitiveReqs` fold that the v1 aggregating * directory performed. * * A sub-directory the walk cannot read is recorded in * {@link WalkHubResult.inaccessible} rather than silently dropped. A failure to * read the *root* directory is left silent — there is no sub-tree to explain — * and simply yields empty results. * * When {@link WalkHubOptions.unlockGatedDirectory} is supplied, each gated * sub-directory is offered to the hook; if it returns `true` (a capability was * granted), that directory is re-queued and the walk continues into it — a * fixpoint that keeps unlocking newly-revealed gated branches until nothing * more can be opened (still bounded by `maxDepth`). */ interface WalkHubOptions { readonly maxDepth?: number; /** * The directory the walk starts from. Defaults to the implicit root * directory (form-2 `hubrpc.directory::list`). Pass a serviceId to start at * `::hubrpc.directory::list` — e.g. the hub's own global * directory (`'hub'`) when walking from the hub's in-process connection. */ readonly rootTarget?: string; /** * Invoked once per gated sub-directory the walk encounters. Return `true` * if a capability for its `hubrpc.directory::list` was granted and the * directory should be re-listed; `false` (or omitted hook) leaves it in * {@link WalkHubResult.inaccessible}. Called at most once per `serviceId`. */ unlockGatedDirectory?: (serviceId: string) => Promise; } declare function walkHubDetailed(channel: ReflectionChannel, opts?: WalkHubOptions): Promise; /** * Backward-compatible wrapper over {@link walkHubDetailed} that returns only the * reachable listings, dropping the inaccessible-directory report. */ declare function walkHub(channel: ReflectionChannel, opts?: WalkHubOptions): Promise; //#endregion export { type AutoNegotiateConsumer, DEFAULT_WALK_DEPTH, type DiscoveredListing, type HubAccessDuration, type HubAccessManifestDecision, type HubAccessManifestRequest, type HubAccessPattern, type HubAccessPermission, type HubAccessRequest, type HubAccessResult, type IHubAccessManifest, type ITransportServer, type InaccessibleDirectory, type ListOptions, type ManagedSigningOptions, ROOT_SERVICE_ID, type ReflectionChannel, SERVICE_ID_SEPARATOR, type ServiceId, type ServiceListing, type Transport, type WalkHubOptions, type WalkHubResult, createAutoNegotiatingCapProvider, createManagedSigningChannel, fetchDirectory, fetchSchema, findCoveringCapabilities, findMethodInSchema, hubAccessInterface, hubAccessManifestInterface, hubGrantedServiceIdInterface, hubServiceIdRegistryInterface, isServiceIdUnder, isValidServiceId, mapTransport, registerGrantedServiceId, splitServiceId, walkHub, walkHubDetailed }; //# sourceMappingURL=index.d.ts.map