/** * 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` operator 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 (`@ 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 `. */ 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; 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 (`@ 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