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.
281 lines • 12.6 kB
TypeScript
/**
* Wire types for `buzz.notifications` — project-event routing into a Buzz
* community channel (gateway `add-buzz-project-event-routing`,
* `/buzz-project-event-routes/v1`).
*
* Every field is the gateway's `snake_case` wire shape, passed through
* unchanged. Timestamps are ISO 8601. `org_id` is the bare dashed UUID
* (never `org_`-prefixed). Route ids are `buzzper_…`, delivery ids `buzzped_…`.
*
* No type here ever carries credential material: the `notification_pubkey`
* and `signing_generation` are the ONLY credential-adjacent fields any
* response exposes — the signing secret lives KMS-encrypted on the gateway
* and no read path selects it.
*/
export type BuzzEventRouteStatus = "pending_authorization" | "active" | "paused" | "revoked";
/**
* `owner` = an explicit pause; `delivery_failures` = the gateway auto-paused
* after ten consecutive hard publish failures (a mandatory
* `buzz_route_auto_paused` owner notification fired alongside).
*/
export type BuzzEventRoutePauseReason = "owner" | "delivery_failures";
/**
* Derived from ROUTE + CREDENTIAL state, never from queue emptiness — a
* paused/pending/signing-unavailable route is never "healthy because its
* queue is empty".
*/
export type BuzzEventRouteHealth = "active" | "paused" | "pending_authorization" | "signing_unavailable" | "revoked";
export type BuzzNotificationPrincipalStatus = "pending_authorization" | "active" | "revoked";
export type BuzzRouteDeliveryStatus = "queued" | "retryable" | "delivered" | "suppressed" | "dead_letter" | "cancelled";
export interface BuzzEventRoute {
buzz_project_event_route_id: string;
/** Bare dashed UUID — NOT `org_`-prefixed. */
org_id: string;
buzz_community_installation_id: string;
route_name: string;
/** The NIP-29 channel id deliveries post into. */
buzz_channel_id: string;
/** The explicit project list (1–50 on a `listed` route; may be empty on an `org` route). */
project_ids: string[];
/** `listed`: only `project_ids` are routed. `org`: every project the organization owns, present and future. */
project_scope?: "listed" | "org";
/** null = every registered routable type (never an implicit `[]`). */
event_types: string[] | null;
/** null = every non-forbidden class. */
event_classes: string[] | null;
/** Also carries the organization's own facts (receipts, high-importance room messages). */
include_org_events?: boolean;
/**
* The Buzz agent (64-hex pubkey) a crash or platform incident on this
* route pages with a `p` mention — the tag that wakes a managed Buzz
* agent. The failing release's deployer is paged instead when it holds a
* public Buzz identity link. null pages nobody.
*/
on_call_buzz_pubkey?: string | null;
/** The name the page addresses that agent by (`@<name> please investigate:`), or null for a tag-only page. */
on_call_display_name?: string | null;
status: BuzzEventRouteStatus;
pause_reason: BuzzEventRoutePauseReason | null;
paused_at: string | null;
/** Optimistic-concurrency revision; echo it as `expectedRevision` on update. */
revision: number;
/** The outbox floor captured at creation — routes deliver NEW events only. */
start_after_event_id: number;
consecutive_hard_failures: number;
notification_principal_id: string;
/** The installation's Nostr notification pubkey (hex) — public by design. */
notification_pubkey: string;
signing_generation: number;
/** Probed at the installation's activation: `attested` means each project posts as its own bot. */
bot_mode: "attested" | "installation_identity" | null;
/** On the single-route read: the route's live project bots (attested mode). Never a secret. */
bots?: BuzzProjectBot[];
created_at: string;
updated_at: string;
/** Revoked routes stay READABLE (sanitized history); only mutations reject them. */
revoked_at: string | null;
}
/** A project's own Nostr identity in the community, attested by the installation identity (NIP-OA). */
export interface BuzzProjectBot {
buzz_project_bot_id: string;
project_id: string;
pubkey: string;
display_name: string;
attested_by_generation: number;
profile_state: "pending" | "published";
status: "active" | "retired";
}
/**
* The one exact non-secret handoff. When `pending_buzz_authorization`, a Buzz
* community owner or admin must add `notification_pubkey` as a relay member
* using already-released Buzz surfaces; POST the `verify_path` afterwards to
* verify the membership landed (which activates the route).
*/
export type BuzzRouteAuthorization = {
status: "authorized";
notification_pubkey: string;
} | {
status: "pending_buzz_authorization";
notification_pubkey: string;
/** e.g. `buzz-admin add-member --pubkey <hex>`. */
connect_command: string;
/** Verbatim human instructions for the community owner. */
instructions: string;
/** The test route — POSTing it verifies the authorization landed. */
verify_path: string;
};
/** `201` from create: the route plus its authorization handoff. */
export interface CreatedBuzzEventRoute extends BuzzEventRoute {
authorization: BuzzRouteAuthorization;
}
/** Route detail (`GET /:id`) — the route plus honest operational state. */
export interface BuzzEventRouteDetail extends BuzzEventRoute {
health: BuzzEventRouteHealth;
notification_principal_status: BuzzNotificationPrincipalStatus;
/** Counts by delivery state; every state present, zero-filled. */
delivery_counts: Record<BuzzRouteDeliveryStatus, number>;
oldest_pending_created_at: string | null;
newest_project_event_id: number | null;
/**
* The shared outbox consumer's cursor. `null` is the honest pre-wiring
* state (the consumer row appears once the tick registers itself) — a
* position is never fabricated.
*/
consumer_cursor: number | null;
}
/** `DELETE /:id` result — revoke keeps sanitized history readable. */
export interface RevokedBuzzEventRoute extends BuzzEventRoute {
/**
* True when this was the installation's LAST live route, so the
* installation-scoped notification credential was destroyed with it —
* never out from under a live sibling route.
*/
notification_credential_destroyed: boolean;
}
/**
* `202` from rotate: the NEXT signing generation is STAGED, not active. The
* swap activates only after the next pubkey's own Buzz-side NIP-43 membership
* verifies (the tick reconcile, or POSTing `verify_path`).
*/
export interface BuzzRouteRotation {
buzz_project_event_route_id: string;
rotation: {
status: "pending_buzz_authorization";
next_signing_generation: number;
next_notification_pubkey: string;
authorize_hint: string;
verify_path: string;
};
}
export interface BuzzRouteDelivery {
buzz_project_event_delivery_id: string;
kind: "event" | "test";
status: BuzzRouteDeliveryStatus;
event_type: string;
project_id: string;
/** null for synthetic test deliveries. */
project_event_id: number | null;
occurred_at: string;
/** Stable across retries — the stored envelope republishes byte-identically. */
nostr_event_id: string | null;
projection_hash: string | null;
signing_generation: number | null;
attempt_count: number;
next_attempt_at: string | null;
last_error: string | null;
suppressed_reason: string | null;
created_at: string;
delivered_at: string | null;
terminal_at: string | null;
/** The release this delivery belongs to; deliveries thread by (route, release). */
release_id: string | null;
/** Public id of the thread root delivery, for replies. */
thread_root_delivery_id: string | null;
thread_position: "root" | "reply" | null;
signer: "installation_identity" | "project_bot";
}
/**
* `202` from test: queued, NOT delivered (Faithful — the single-consumer tick
* publishes it, typically within ~60s). `poll.path` is the deliveries read
* scoped to this delivery id.
*/
export interface BuzzRouteTestDelivery extends BuzzRouteDelivery {
poll: {
path: string;
};
}
/** Keyset newest-first delivery history — dead letters included, the signed envelope never. */
export interface BuzzRouteDeliveryList {
buzz_project_event_deliveries: BuzzRouteDelivery[];
has_more: boolean;
/** Opaque keyset continuation; absent on the last page. Store and echo; never parse. */
next_cursor?: string;
}
export interface CreateBuzzEventRouteInput {
/** An ACTIVE community installation (`buzzci_…`) owned by the org. */
installationId: string;
/** Unique per installation among non-revoked routes (1–100 chars). */
routeName: string;
/** The NIP-29 channel id to post into. */
buzzChannelId: string;
/** 1–50 named projects owned by the org. Required for a `listed` route; optional for `org`. */
projectIds?: string[];
/**
* `listed` (default): the route carries only `projectIds`. `org`: every
* project the organization owns, present and future, read fresh per fact
* so a transferred project drops out; no list needed.
*/
projectScope?: "listed" | "org";
/**
* Also deliver the org's own facts (e.g. the `platform_payment_received`
* receipt after a Lightning top-up or tier purchase) into this channel.
* Default false: a route is project-scoped unless asked.
*/
includeOrgEvents?: boolean;
/**
* Omitted/null routes every registered routable type
* (`deploy_activated`, `error_fingerprints_observed`, `platform_incident`).
* An explicit `[]` is rejected (422) — it matches nothing, never everything.
*/
eventTypes?: string[] | null;
/**
* Omitted/null routes every non-forbidden class. `security`,
* `billing_critical`, `destructive_lifecycle`, `verification`, and
* `recovery` may never be routed. `[]` is rejected like `eventTypes`.
*/
eventClasses?: string[] | null;
/**
* The Buzz agent (64-hex pubkey) this route pages when a crash or platform
* incident names nobody — the projection mentions it with a `p` tag, which
* is what wakes a managed Buzz agent. Omit or null to page nobody.
*/
onCallBuzzPubkey?: string | null;
/**
* The name the page addresses the on-call agent by (`@<name> please
* investigate:` — what Buzz renders as a mention chip). Omitted with a
* pubkey: the gateway resolves it from the agent's Buzz profile.
*/
onCallDisplayName?: string | null;
/** Auto-generated when omitted — every route mutation is idempotent. */
idempotencyKey?: string;
}
export interface UpdateBuzzEventRoutePatch {
routeName?: string;
buzzChannelId?: string;
projectIds?: string[];
/** Switch between the explicit list and the whole organization; switching to `listed` needs at least one project stored or given. */
projectScope?: "listed" | "org";
/** `null` clears the filter back to "every registered type"; `[]` is rejected. */
eventTypes?: string[] | null;
eventClasses?: string[] | null;
includeOrgEvents?: boolean;
/** `null` clears the on-call agent (pages nobody). */
onCallBuzzPubkey?: string | null;
/** The `@name` the page addresses the on-call agent by; a new pubkey without one is resolved from its Buzz profile; `null` clears it. */
onCallDisplayName?: string | null;
idempotencyKey?: string;
}
export interface ListBuzzRouteDeliveriesOptions {
/** 1–200; the gateway defaults to 50. */
limit?: number;
/** Opaque `next_cursor` from a previous page. */
cursor?: string;
/** Scope the read to one `buzzped_…` id — the test-delivery poll shape. */
deliveryId?: string;
}
export interface TestAndWaitBuzzRouteOptions {
/** Delay between polls (default 5s; the gateway's Retry-After is 2s). */
pollMs?: number;
/**
* Total budget (default 3 minutes — the publisher tick runs ~every 60s, so
* a healthy test usually lands within one tick). On expiry the LAST
* OBSERVED delivery is RETURNED, still queued — never thrown.
*/
timeoutMs?: number;
/**
* Called with the `202` test response FIRST (the only state carrying
* `poll`), then with each polled delivery state.
*/
onPoll?: (state: BuzzRouteTestDelivery | BuzzRouteDelivery) => void;
}
//# sourceMappingURL=buzz-notifications.types.d.ts.map