run402-mcp
Version:
MCP server for Run402 — full-stack backend infrastructure for AI agents: Postgres, auth, storage, serverless functions and atomic deploys. Paid with x402/MPP. Includes $0.03 image generation.
169 lines • 7.36 kB
TypeScript
/**
* Organization context, owned by the Node SDK: the ONE resolver every
* org-scoped command consumes, and the verbs that select, report, and bind
* the current organization.
*
* The org is the ownership root — it owns projects, holds memberships, and is
* the scope for rooms, escalations, members, grants, and audit. Precedence is
* four INTENT CLASSES, highest first, and inside each class an organization
* named directly outranks one derived from a project named in that same class:
*
* 1. flag `org` (--org) else `project` (--project) -> its org
* 2. environment RUN402_ORG, else the org half else RUN402_PROJECT_ID -> its org
* of RUN402_ROOM
* 3. binding the `org` key of the nearest .run402(.local).json
* 3.5 vault pin `r402.orgId` in this checkout's local git config
* 4. profile state the profile's selected org else its active project -> org
*
* Naming a project IS naming its organization, so a stale profile selection
* never outranks it; classes 3 and 4 are what let an org that owns no project
* be addressed at all.
*
* Two things this deliberately does NOT do:
* - Infer the org from the caller's memberships, at any count: membership is
* server state that changes without the caller acting.
* - Validate membership locally: a well-formed id goes to the server and the
* server's answer is surfaced as returned, never retried against a lower
* class and never rewritten into a local not-found.
*/
import { LocalError, type NextAction } from "../errors.js";
import type { Client } from "../kernel.js";
import { Orgs } from "../namespaces/org.js";
import { Rooms } from "../namespaces/rooms.js";
import { Projects } from "../namespaces/projects.js";
export declare const ORG_ENV = "RUN402_ORG";
export declare const ROOM_ENV = "RUN402_ROOM";
export declare const PROJECT_ENV = "RUN402_PROJECT_ID";
/** `org_id` is a UUID at every API boundary. */
export declare const ORG_ID_RE: RegExp;
export type OrgSource = "flag" | "env" | "binding" | "vault_pin" | "profile";
export interface ResolvedOrg {
orgId: string;
source: OrgSource;
sourceDetail: string;
}
export interface ResolveOrgInput {
/** The org named directly (the `--org` flag). */
org?: string | null;
/** A project named directly (the `--project` flag); its owning org decides. */
project?: string | null;
}
export interface ResolveOrgOptions {
env?: Record<string, string | undefined>;
/** Directory the binding walk starts from. Default `process.cwd()`. */
cwd?: string;
/** Return null instead of throwing `ORG_REQUIRED` when nothing supplies an org. */
optional?: boolean;
/** Skip the env-vs-binding `AMBIGUOUS_ORG` error (surfaces that must stay usable while ambiguous). */
allowConflict?: boolean;
}
export interface OrgProvenance {
org_id: string | null;
org_source: OrgSource | null;
org_source_detail: string | null;
}
export interface CurrentOrgResult extends OrgProvenance {
selected_org_id: string | null;
}
export interface OrgBindResult {
org_id: string;
room_key: string | null;
org_source: "flag" | "sole_membership";
file: ".run402.json";
path: string;
bound: true;
safe_to_commit: true;
note: string;
binding: Record<string, unknown> | null;
}
export interface OrgUnbindResult {
file: ".run402.json";
unbound: boolean;
removed: boolean;
binding: Record<string, unknown> | null;
}
export declare function listOrgsAction(): NextAction;
/** The recovery actions an `ORG_REQUIRED` refusal carries: every way to supply an org. */
export declare function orgRequiredActions(): NextAction[];
/**
* Shape-validate an organization id from a local source. Never checks
* membership. A rejected value may be a pasted secret, so it is redacted.
*/
export declare function assertOrgIdShape(orgId: string, origin: string): string;
/** The `ORG_REQUIRED` refusal, optionally naming a rejected positional. */
export declare function orgRequiredError(opts?: {
rejectedPositional?: string;
positionalHint?: boolean;
}): LocalError;
/** Provenance triple for command output: bounded, never a resolution trace. */
export declare function orgProvenance(resolved: ResolvedOrg | null): OrgProvenance;
/**
* `r.orgs` on the Node entry: the isomorphic org collection and identity
* verbs plus the local organization context.
*/
export declare class NodeOrgs extends Orgs {
#private;
/**
* @param namespaces the reads the resolver makes (a project's org, the
* project listing); default to fresh namespaces on `client`.
*/
constructor(client: Client, namespaces?: {
rooms?: Pick<Rooms, "forProject">;
projects?: Pick<Projects, "list">;
});
/**
* The one resolver. Returns the org with its provenance, or null when
* `optional` and nothing supplies one; throws `BAD_ORG_ID`, `AMBIGUOUS_ORG`,
* or `ORG_REQUIRED` (each with its recovery actions) otherwise.
*/
resolve(input?: ResolveOrgInput, opts?: ResolveOrgOptions): Promise<ResolvedOrg | null>;
/** Select the current organization for the active wallet profile (`orgs use`). */
use(orgId: string): Promise<{
org_id: string;
selected: true;
scope: "wallet_profile";
}>;
/**
* The organization this directory and profile resolve to, with provenance,
* beside the profile's own selection. An empty selection is an explicit
* null state. Never fails on ambiguity: the command that reports the
* selection stays usable while it is ambiguous.
*/
current(opts?: Pick<ResolveOrgOptions, "env" | "cwd">): Promise<CurrentOrgResult>;
/** The profile's selected organization, without running the chain. */
selected(): string | null;
/** Clear the profile's selected organization. */
clear(): Promise<{
org_id: null;
selected: false;
previous_org_id: string | null;
}>;
/**
* Write this checkout's org (and room) into `.run402.json`. With no org, the
* caller's sole membership is used and written down: an explicit, recorded
* act, unlike the chain, which never infers. Two or more memberships refuse.
*/
bind(orgId?: string | null, opts?: {
room?: string | null;
cwd?: string;
}): Promise<OrgBindResult>;
/** Remove the `org` and `room` keys from `./.run402.json`; the file goes when nothing else is left. */
unbind(opts?: {
cwd?: string;
}): Promise<OrgUnbindResult>;
/**
* Stamp a project's owning organization as the profile's selection
* (`projects use` does this: a project determines its org unambiguously).
* Best-effort: returns the org, or null, and never throws.
*/
selectFromProject(projectId: string): Promise<string | null>;
/**
* The organization that OWNS a specific project, or null. Distinct from
* {@link resolve} (which org a command is addressed at): an `--org` override
* here would be a mis-binding. Remembered in the local project entry after
* the first lookup, so the vault scaffold adds no network read on a
* returning machine; an exact id match is required.
*/
owningOrgOf(projectId: string): Promise<string | null>;
}
//# sourceMappingURL=org-context.d.ts.map