/** * Console flows — every action is a real operator-plane flow through `fx`. * * The audit log is the trace (console §1 · §6). */ import { z } from "zod"; import { authenticateOperator, BreachCheckError, createOperator, issueSession, PasswordPolicyError, scopesForRoles, type IssuedSession, } from "../../auth/index.ts"; import { DryRunWriteIsolationError } from "../../kernel/dry-run.ts"; import { fail, flow, http, type AnyFlowDef, type Binding } from "../../kernel/index.ts"; import { redactHttpFrame } from "../../kernel/http-frame.ts"; import { lazyRequire } from "../../kernel/lazy-require.ts"; import type { Flow as ManifestFlow, ResourceRef } from "../../manifest/types.ts"; import { eventHasIrreversible, runReplay } from "../../cli/replay.ts"; import { createRunsRuntime } from "../../runs/runtime.ts"; import type { WideEvent } from "../../runs/types.ts"; import { bindHttp } from "./bind.ts"; import { touchLoginRateLimit } from "./auth-rate.ts"; import { clearClaimCodeArtifact, verifyClaimCode } from "./claim.ts"; import { maskPiiValue, maskWideEventForConsole, piiFieldNamesFromManifest } from "./runs-pii.ts"; import { ConsoleRunsQueryError, RUNS_QUERY_PII_GAP, RUNS_QUERY_TIMEOUT_MS } from "./runs-query.ts"; import { DuckQueryTimeoutError } from "../../runs/duckdb.ts"; import { ClockResourceNotFoundError, ScheduleNotOverridableError } from "./clock.ts"; import { isoAt } from "./iso-at.ts"; import { createFileDiff, emitStructuralDiff } from "./structural.ts"; import type { ConsoleState } from "./state.ts"; import { consoleFailureMessage } from "./i18n.ts"; import { CONSOLE_PASSWORD_POLICY } from "../password-policy.ts"; import { PUBLIC_CONSOLE_FLOWS } from "./public-flows.ts"; import { resolveInvokeAs } from "./invoke-user-flow.ts"; import { resolveRlsIdentity } from "../../elements/store.ts"; import type { RlsIdentity } from "../../drivers/pg-rls.ts"; import { accessUserCeiling } from "./access.ts"; import { isKnownConsoleSqlGate, StoreFileNotFoundError, tenancyDeclared } from "./store.ts"; import { PG_STAT_STATEMENTS_NOT_CREATED, PG_STAT_STATEMENTS_NOT_PRELOADED, STORE_SQL_LOCKS_POLL_MS, STORE_SQL_STATS_PII_GAP, StoreSqlStatsError, engineErrorText, } from "./store-stats.ts"; import { STORE_KV_STATS_SERVER_WIDE_GAP, STORE_KV_STATS_SLOWLOG_ARGS_GAP, StoreKvStatsError, } from "./store-kv-stats.ts"; export { PUBLIC_CONSOLE_FLOWS }; const SetupStatusOut = z.object({ setupClosed: z.boolean(), claimRequired: z.boolean(), }); const ClaimIn = z.object({ claimCode: z.string().min(1), email: z.string().email(), name: z.string().min(1), /** Matches {@link CONSOLE_PASSWORD_POLICY} (enforced again in createOperator). */ password: z.string().min(12), }); const SessionOut = z.object({ operatorId: z.string(), email: z.string(), name: z.string(), accessToken: z.string(), refreshToken: z.string(), accessExpiresAt: z.number(), }); const LoginIn = z.object({ email: z.string().email(), password: z.string().min(1), }); const MeOut = z.object({ operatorId: z.string(), email: z.string(), name: z.string(), setupClosed: z.boolean(), }); const ManifestOut = z.object({ manifest: z.unknown().nullable(), }); const EffectEntryOut = z.object({ kind: z.enum([ "read", "write", "emit", "send", "ask", "embed", "secret", "call", "fetch", "decide", ]), resource: z.string(), timestamp: z.number(), duration: z.number(), reversibility: z.enum(["none", "reversible", "deferred", "irreversible", "capability", "portal"]), external: z .object({ host: z.string(), provider: z.string().optional(), kind: z.enum(["third-party", "infrastructure"]).optional(), }) .optional(), agentRunId: z.string().optional(), }); const LogLineOut = z.object({ level: z.enum(["debug", "info", "warn", "error"]), message: z.string(), data: z.record(z.string(), z.unknown()).optional(), at: z.number(), }); /** Wide-event projection — Runs · Traces · Overview share one store (console §9.11). */ const RunsListOut = z.object({ runs: z.array( z.object({ id: z.string(), parentId: z.string().nullable(), flow: z.string(), unit: z.string().nullable(), trigger: z.string(), plane: z.string(), tenant: z.string().nullable(), principal: z.string().nullable(), gates: z.array(z.string()), cache: z.enum(["hit", "miss", "none"]), replica: z.enum(["primary", "replica"]).nullable(), replicaLagMs: z.number().nullable(), cost: z.number().nullable(), inputTokens: z.number().nullable(), outputTokens: z.number().nullable(), promptVersion: z.number().nullable(), buildVersion: z.string().nullable(), startedAt: z.number(), endedAt: z.number(), durationMs: z.number(), error: z.string().nullable(), /** Human message from the run ledger when present. */ errorMessage: z.string().nullable(), sampled: z.enum(["full", "error", "sample", "boost"]), effects: z.array(EffectEntryOut), /** `fx.log` lines — a field on the run, not a parallel stream. */ logs: z.array(LogLineOut), /** All queryable dimensions for population analysis. */ dimensions: z.record(z.string(), z.union([z.string(), z.number(), z.boolean(), z.null()])), /** Validated flow input snapshot for replay — null when absent. */ input: z.unknown().nullable(), /** Flow return value snapshot — null when absent (failures / legacy). */ output: z.unknown().nullable(), /** * HTTP wire frame — null for non-HTTP runs and rows recorded before * the frame existed. */ http: z .object({ request: z.object({ method: z.string(), path: z.string(), query: z.record(z.string(), z.string()), headers: z.record(z.string(), z.string()), }), response: z .object({ status: z.number(), headers: z.record(z.string(), z.string()), }) .optional(), }) .nullable(), }), ), }); const TracesReplayIn = z.object({ rootId: z.string().min(1), dryRun: z.boolean(), }); const TracesReplayOut = z.object({ ok: z.literal(true), rootId: z.string(), dryRun: z.boolean(), at: z.string(), flow: z.string(), }); const ReplayUnavailable = z.object({ rootId: z.string(), reason: z.enum(["no_stored_input"]), }); const ReplayFailed = z.object({ rootId: z.string(), message: z.string(), }); const SignalEndpointOut = z.object({ flowId: z.string(), durable: z.boolean(), external: z.boolean(), peakTier: z.enum(["none", "reads", "writes", "emits", "external", "capabilities"]), }); const DeadLetterOut = z.object({ id: z.string(), signal: z.string(), payload: z.unknown(), delivery: z.enum(["once", "broadcast", "live"]), attempts: z.number(), failures: z.array( z.object({ code: z.string(), message: z.string(), at: z.number(), attempt: z.number(), }), ), createdAt: z.number(), availableAt: z.number(), status: z.literal("dead"), causeRunId: z.string().optional(), causeFlow: z.string().optional(), }); const SignalsListOut = z.object({ signals: z.array( z.object({ name: z.string(), description: z.string().optional(), delivery: z.enum(["once", "broadcast", "live"]), retries: z.number(), deadLetterEnabled: z.boolean(), orphaned: z.boolean(), pending: z.number(), inflight: z.number(), dead: z.number(), delivered: z.number(), outboxLagMs: z.number().nullable(), connections: z.number(), throughputPerSec: z.number(), schema: z.unknown().optional(), subscribers: z.array( z.object({ id: z.string(), lag: z.number(), errorCount: z.number(), }), ), recentLive: z.array(z.unknown()), deadLetters: z.array(DeadLetterOut), producers: z.array(SignalEndpointOut), consumers: z.array(SignalEndpointOut), consumersDurable: z.boolean().nullable(), }), ), }); const SignalsReplayIn = z.object({ signal: z.string().min(1), messageIds: z.array(z.string()).optional(), subscriberId: z.string().optional(), ratePerSec: z.number().min(1).max(1_000).default(10), dryRun: z.boolean(), payloads: z.record(z.string(), z.unknown()).optional(), /** Typed confirmation phrase for irreversible production replay. */ confirmation: z.string().optional(), /** Recorded reason for irreversible production replay. */ reason: z.string().optional(), }); const SignalsReplayOut = z.object({ ok: z.literal(true), attempted: z.number(), succeeded: z.number(), failed: z.number(), dryRun: z.boolean(), results: z.array( z.object({ id: z.string(), ok: z.boolean(), error: z.object({ code: z.string(), message: z.string() }).optional(), }), ), wouldHaveFired: z.array( z.object({ kind: z.enum(["send", "ask", "embed", "fetch"]), resource: z.string(), messageId: z.string().optional(), }), ), at: z.string(), }); const SignalsDiscardIn = z.object({ signal: z.string().min(1), messageIds: z.array(z.string()).min(1), confirmation: z.string().optional(), reason: z.string().optional(), }); const SignalsDiscardOut = z.object({ ok: z.literal(true), discarded: z.number(), at: z.string(), }); const ActionPingIn = z.object({ note: z.string().optional(), }); const ActionPingOut = z.object({ ok: z.literal(true), note: z.string().optional(), at: z.string(), }); const StructuralIn = z.object({ title: z.string().min(1), relativePath: z.string().min(1), contents: z.string(), reason: z.string().min(1), }); const StructuralOut = z.object({ id: z.string(), path: z.string(), applied: z.literal(false), }); const IdentitiesOut = z.object({ identities: z.array( z.object({ id: z.string(), email: z.string(), name: z.string(), status: z.enum(["active", "disabled"]), scopes: z.array(z.string()), }), ), }); const InvokeIn = z.object({ flowId: z.string().min(1), body: z.unknown(), /** Seeded identity when Invoke As → User. Omit for Operator / Public / policy. */ asUserId: z.string().min(1).optional(), /** `public` or a policy Gate. Omit for Operator bypass. */ asGate: z.string().min(1).optional(), /** Path params for HTTP routes with `:param` segments. */ pathParams: z.record(z.string(), z.string()).optional(), /** Typed confirmation phrase for irreversible production invokes. */ confirmation: z.string().optional(), /** Recorded reason for irreversible production invokes. */ reason: z.string().optional(), /** Return classified PII in the handler response (audited). */ revealPii: z.boolean().optional(), }); const InvokeOut = z.object({ ok: z.literal(true), flowId: z.string(), asUserId: z.string(), asGate: z.string().nullable().optional(), trigger: z.enum(["http", "signal", "clock", "internal", "durable"]), response: z.unknown(), /** True when classified PII keys were redacted. */ masked: z.boolean(), /** HTTP-ish status from the host when available (200 / 4xx). */ status: z.number().optional(), /** Host typed failure when the target flow returned `fail(...)`. */ failure: z .object({ code: z.string(), data: z.unknown().optional(), message: z.string().optional(), }) .optional(), runId: z.string().optional(), /** Host telemetry cache dimension when the invoke adapter reported one. */ cache: z.enum(["hit", "miss", "none"]).optional(), /** Handler duration from the host execute (high-res ms). */ durationMs: z.number().optional(), peakTier: z.enum(["none", "reads", "writes", "emits", "external", "capabilities"]), auditedAt: z.number(), rls: z .object({ gate: z.string().nullable(), userId: z.string(), applied: z.boolean(), }) .optional(), }); const SetupClosed = z.object({ reason: z.string() }); const ClaimFailed = z.object({ reason: z.string(), /** Password-policy detail lines when `reason` is `password_policy`. */ reasons: z.array(z.string()).optional(), }); const AuthFailed = z.object({}); const QueryRejected = z.object({ reason: z.string() }); const QueryTimeout = z.object({ timeoutMs: z.number() }); const QueryFailed = z.object({ reason: z.string() }); const AuthRateLimited = z.object({ reason: z.string() }); const NotFound = z.object({ flowId: z.string() }); const InvokeDenied = z.object({ reason: z.string() }); const ConfirmRequired = z.object({ phrase: z.enum([ "INVOKE", "REPLAY", "DISCARD", "EDIT", "DELETE", "PURGE", "ROTATE", "ROTATE_MASTER", "REVOKE", "RUN", "SEND", ]), reason: z.string(), }); const ChannelNotFound = z.object({ template: z.string() }); const ChannelOutcomeOut = z.object({ state: z.enum([ "suppressed/opted-out", "suppressed/prior-bounce", "blocked/invalid-address", "soft-bounce", "hard-bounce", "provider-error", "delivered-then-complained", ]), count: z.number(), verdict: z.enum(["correct", "retry", "suppress", "review"]), weight: z.number(), }); const ChannelsListOut = z.object({ face: z.enum(["inbox", "deliverability"]), production: z.boolean(), templates: z.array( z.object({ name: z.string(), description: z.string().optional(), medium: z.string(), locales: z.array(z.string()), from: z.string().nullable(), schema: z.unknown(), }), ), outcomes: z.array(ChannelOutcomeOut), fallback: z.object({ template: z.string().nullable(), chainExample: z.string(), fallbackRate: z.number(), fallbackCount: z.number(), totalCount: z.number(), weeklyDeltaUsd: z.number(), primaryMedium: z.string(), fallbackMedium: z.string(), summary: z.string(), }), inbox: z.array( z.object({ id: z.string(), medium: z.string(), toMasked: z.string(), subject: z.string().nullable(), text: z.string().nullable(), html: z.string().nullable(), template: z.string().nullable(), locale: z.string().nullable(), at: z.number(), }), ), receipts: z.array( z.object({ id: z.string(), template: z.string(), toMasked: z.string(), medium: z.string(), locale: z.string().nullable(), localeChain: z.array(z.string()), status: z.string(), chain: z.string(), messageId: z.string().nullable(), at: z.number(), error: z.string().nullable(), }), ), suppression: z.array( z.object({ subjectMasked: z.string(), medium: z.string(), reason: z.enum(["opted-out", "prior-bounce"]), at: z.number(), }), ), }); const ChannelPreviewIn = z.object({ template: z.string().min(1), locale: z.string().optional(), profileLocale: z.string().optional(), acceptLanguage: z.string().optional(), data: z.record(z.string(), z.unknown()).optional(), }); const ChannelPreviewOut = z.object({ template: z.string(), locale: z.string(), localeChain: z.array(z.string()), dir: z.enum(["ltr", "rtl"]), subject: z.string().nullable(), text: z.string().nullable(), html: z.string().nullable(), }); const ChannelVerifyAuthIn = z.object({ from: z.string().min(1), }); const ChannelVerifyAuthOut = z.object({ domain: z.string(), spf: z.enum(["pass", "fail", "missing"]), dkim: z.enum(["pass", "fail", "missing"]), dmarc: z.enum(["pass", "fail", "missing"]), checkedAt: z.number(), }); const ChannelRevealIn = z.object({ id: z.string().min(1), }); const ChannelRevealOut = z.object({ ok: z.literal(true), id: z.string(), to: z.string(), at: z.string(), }); const ChannelSendTestIn = z.object({ template: z.string().min(1), to: z.string().min(1), locale: z.string().optional(), data: z.record(z.string(), z.unknown()).optional(), confirmation: z.string().optional(), reason: z.string().optional(), }); const ChannelSendTestOut = z.object({ ok: z.boolean(), messageId: z.string(), status: z.string(), chain: z.string(), at: z.string(), }); const VaultNotFound = z.object({ name: z.string(), reason: z.string().optional(), }); const VaultSealed = z.object({ reason: z.string() }); const VaultRotateBusy = z.object({ reason: z.string() }); const VaultUnsupported = z.object({ reason: z.string() }); const ClockNotFound = z.object({ kind: z.enum(["cron", "run"]), id: z.string() }); const ScheduleNotOverridable = z.object({ name: z.string() }); const CronHealthOut = z.object({ driftMs: z.number().nullable(), overdue: z.boolean(), missedRuns: z.number(), catchUp: z.literal("one"), leaderInstanceId: z.string().optional(), leaderLeaseUntil: z.number().optional(), }); const ClockCronOut = z.object({ name: z.string(), description: z.string().optional(), status: z.enum(["active", "paused", "orphaned"]), timezone: z.string(), overridable: z.boolean(), declaredCron: z.string().optional(), declaredEvery: z.string().optional(), effectiveCron: z.string().optional(), effectiveEvery: z.string().optional(), lastRunAt: z.number().optional(), nextRunAt: z.number().optional(), health: CronHealthOut, dstAmbiguity: z .object({ kind: z.enum(["gap", "overlap"]), reason: z.string(), on: z.string(), localTime: z.string(), }) .nullable(), external: z.boolean(), flowIds: z.array(z.string()), }); const WaitingOnOut = z.object({ runId: z.string(), flow: z.string(), label: z.string(), wakeAt: z.number(), wakeInMs: z.number(), step: z.string().nullable(), }); const ClockListOut = z.object({ now: z.number(), crons: z.array(ClockCronOut), waitingOn: z.array(WaitingOnOut), waitingOnCounts: z.array(z.object({ label: z.string(), count: z.number() })), timeline: z.array( z.object({ at: z.number(), kind: z.enum(["cron", "wake"]), name: z.string(), meta: z.string().optional(), }), ), }); const InstanceClockLeaseOut = z.object({ name: z.string(), leaseUntil: z.number(), }); const InstanceJournalLeaseOut = z.object({ runId: z.string(), flow: z.string(), leaseUntil: z.number(), }); const InstanceDetailOut = z.object({ id: z.string(), startedAt: z.number(), heartbeatAt: z.number(), leaseExpiresAt: z.number(), env: z.enum(["dev", "test", "prod"]), pid: z.number().optional(), clock: z.array(InstanceClockLeaseOut), journal: z.array(InstanceJournalLeaseOut), }); const InstancesListOut = z.discriminatedUnion("kind", [ z.object({ kind: z.literal("empty") }), z.object({ kind: z.literal("fleet"), now: z.number(), alive: z.number(), instances: z.array(InstanceDetailOut), }), ]); const ClockRunNowIn = z.object({ name: z.string().min(1), confirmation: z.string().optional(), reason: z.string().optional(), }); const ClockRunNowOut = z.object({ ok: z.literal(true), name: z.string(), ran: z.boolean(), at: z.string(), }); const ClockPauseIn = z.object({ name: z.string().min(1) }); const ClockPauseOut = z.object({ ok: z.literal(true), name: z.string(), status: z.string(), at: z.string(), }); const ClockEditIn = z.object({ name: z.string().min(1), cron: z.string().optional(), every: z.string().optional(), }); const ClockEditOut = z.object({ ok: z.literal(true), name: z.string(), effectiveCron: z.string().optional(), effectiveEvery: z.string().optional(), at: z.string(), }); const ClockWakeEarlyIn = z.object({ runId: z.string().min(1) }); const ClockWakeEarlyOut = z.object({ ok: z.literal(true), runId: z.string(), wakeAt: z.number(), resumed: z.boolean(), at: z.string(), }); const VaultResolutionStepOut = z.object({ source: z.enum(["process.env", ".env.local", "driver", "dev-fallback"]), present: z.boolean(), won: z.boolean(), }); const VaultBlastRadiusOut = z.object({ count: z.number(), longestWakeAt: z.number().nullable(), longestOutstandingMs: z.number().nullable(), runIds: z.array(z.string()), }); const VaultRowOut = z.object({ name: z.string(), kind: z.enum(["secret", "config"]), sensitive: z.boolean(), description: z.string().optional(), rotate: z.string().optional(), fingerprints: z.record(z.string(), z.string()), fingerprint: z.string().nullable(), cleartext: z.string().nullable(), winner: z.enum(["process.env", ".env.local", "driver", "dev-fallback"]).nullable(), resolution: z.array(VaultResolutionStepOut), readers: z.array(z.string()), blastRadius: VaultBlastRadiusOut, lastReadAt: z.number().nullable(), sharedFingerprintEnvs: z.array(z.string()), origin: z.enum(["source", "console"]).optional(), }); const VaultBuiltinStatusOut = z.object({ initialized: z.boolean(), sealed: z.boolean(), masterKeyPresent: z.boolean(), kekVersion: z.number(), secretCount: z.number(), sealCount: z.number(), lastSealedAt: z.number().nullable(), lastUnsealedAt: z.number().nullable(), rewrapTargetKekVersion: z.number().nullable(), }); const VaultBackendOut = z.object({ driverId: z.enum(["env", "vault", "managed", "memory"]), builtin: z.boolean(), status: VaultBuiltinStatusOut.nullable(), unavailable: z.string().nullable(), provider: z.string().nullable(), }); const VaultListOut = z.object({ secrets: z.array(VaultRowOut), env: z.string(), backend: VaultBackendOut.nullable(), }); const VaultWriteIn = z.object({ name: z.string().min(1), value: z.string().min(1), confirmation: z.string().optional(), reason: z.string().min(3), }); const VaultCreateIn = z.object({ name: z.string().min(1), value: z.string().min(1), kind: z.enum(["secret", "config"]), description: z.string().optional(), rotate: z.string().optional(), }); const VaultExists = z.object({ name: z.string() }); const VaultWriteOut = z.object({ ok: z.literal(true), name: z.string(), fingerprint: z.string().nullable(), at: z.string(), }); const VaultAuditRowOut = z.object({ id: z.string(), seq: z.number(), action: z.string(), path: z.string().nullable(), actorType: z.string(), actorId: z.string().nullable(), success: z.boolean(), errorCode: z.string().nullable(), errorMessage: z.string().nullable(), requestId: z.string().nullable(), createdAt: z.number(), }); const VaultAuditVerifyOut = z.object({ ok: z.boolean(), brokenAt: z.string().nullable(), reason: z.enum(["link", "payload"]).nullable(), row: VaultAuditRowOut.nullable(), }); const VaultRotateMasterIn = z.object({ confirmation: z.string().optional(), reason: z.string().optional(), }); const VaultRotateMasterOut = z.object({ ok: z.literal(true), kekVersion: z.number(), remaining: z.number(), masterKey: z.string().nullable(), at: z.string(), }); const AiMetricOut = z.object({ samples: z.array(z.number()), mean: z.number(), p50: z.number(), p95: z.number(), buckets: z.array( z.object({ min: z.number(), max: z.number(), count: z.number(), }), ), }); const AiListOut = z.object({ prompts: z.array( z.object({ name: z.string(), version: z.number().optional(), model: z.string().optional(), evals: z.string().optional(), budgetMaxCostPerCall: z.number().nullable(), manifestDiffPath: z.string(), }), ), agents: z.array( z.object({ name: z.string(), tools: z.array(z.string()), maxSteps: z.number().optional(), model: z.string().optional(), budgetMaxCostPerRun: z.number().nullable(), }), ), versions: z.array( z.object({ prompt: z.string(), version: z.number(), sampleCount: z.number(), cost: AiMetricOut, latencyMs: AiMetricOut, evalScore: AiMetricOut, schemaInvalidRate: z.number(), providerErrorRate: z.number(), okRate: z.number(), overBudgetRate: z.number(), budgetMaxCostPerCall: z.number().nullable(), outcomeCounts: z.object({ ok: z.number(), provider_error: z.number(), schema_invalid: z.number(), budget_exceeded: z.number(), }), }), ), allowPii: z.array( z.object({ flowId: z.string(), asks: z.array(z.string()), pii: z.enum(["masked", "allow", "denied"]).nullable(), allowPii: z.boolean(), source: z.string().nullable(), }), ), fallbackChains: z.array( z.object({ prompt: z.string(), version: z.number().optional(), attempts: z.array( z.object({ model: z.string(), ok: z.boolean(), error: z.string().optional(), cost: z.number().optional(), latencyMs: z.number().optional(), at: z.number(), }), ), actualCost: z.number(), primaryOnlyCost: z.number().nullable(), costConsequence: z.number().nullable(), at: z.number(), }), ), agentRuns: z.array( z.object({ id: z.string(), agent: z.string(), message: z.string(), ok: z.boolean(), stopReason: z.enum(["completed", "max_steps", "budget", "denied", "aborted", "error"]), error: z.string().optional(), steps: z.number(), cost: z.number(), at: z.number(), trail: z.array( z.object({ tool: z.string(), status: z.enum(["ok", "denied"]), effects: z.array( z.object({ kind: z.enum([ "read", "write", "emit", "send", "ask", "embed", "secret", "call", "fetch", "decide", ]), resource: z.string(), }), ), denial: z .object({ agent: z.string(), tool: z.string(), gate: z.string(), reason: z.string(), at: z.number(), }) .nullable(), at: z.number(), }), ), denials: z.array( z.object({ agent: z.string(), tool: z.string(), gate: z.string(), reason: z.string(), at: z.number(), }), ), }), ), denials: z.array( z.object({ agent: z.string(), tool: z.string(), gate: z.string(), reason: z.string(), at: z.number(), }), ), }); const GatesListOut = z.object({ moduleActions: z.array(z.string()), flows: z.array( z.object({ flowId: z.string(), plane: z.enum(["user", "operator"]), gates: z.array(z.string()), unguarded: z.boolean(), explicitPublic: z.boolean(), }), ), gates: z.array( z.object({ name: z.string(), description: z.string().optional(), kind: z.enum(["policy", "rate"]), scopes: z.array(z.string()), roles: z.array(z.string()), strategy: z.string().optional(), max: z.number().optional(), per: z.string().optional(), keyBy: z.string().optional(), overridable: z.boolean(), attachedTo: z.array(z.string()), }), ), principals: z.array( z.object({ kind: z.enum(["role", "key", "user"]), id: z.string(), name: z.string(), plane: z.enum(["user", "operator"]), scopes: z.array(z.string()), memberCount: z.number().optional(), email: z.string().optional(), }), ), violations: z.array( z.object({ kind: z.literal("operator-application-scope"), operatorId: z.string(), name: z.string(), email: z.string(), applicationScopes: z.array(z.string()), }), ), audit: z.object({ unguardedFlows: z.array(z.string()), orphanPermissions: z.array(z.string()), emptyRoles: z.array(z.string()), unattachedGates: z.array(z.string()), }), widenings: z.array( z.object({ path: z.string(), category: z.string(), kind: z.string(), summary: z.string(), before: z.unknown().optional(), after: z.unknown().optional(), }), ), }); const DiffChangeOut = z.object({ path: z.string(), category: z.enum(["contract-breaking", "permission-widening", "effect-widening", "no-impact"]), kind: z.enum(["added", "removed", "changed"]), summary: z.string(), before: z.unknown().optional(), after: z.unknown().optional(), flowName: z.string().nullable(), runCountLastWeek: z.number(), blastLine: z.string().nullable(), weeklyDeltaUsd: z.number().nullable(), weeklyBillLine: z.string().nullable(), ciGate: z.enum(["blocked", "acknowledged"]).nullable(), }); const DiffListOut = z.object({ hasBaseline: z.boolean(), severity: z .enum(["contract-breaking", "permission-widening", "effect-widening", "no-impact"]) .nullable(), blockedCount: z.number(), acknowledgedCount: z.number(), changes: z.array(DiffChangeOut), }); const SupplySignalStates = z.enum([ "pass", "fail", "hold", "not-applicable", "unknown", "clean", "conflict", ]); const PluginsListOut = z.object({ stateDerivation: z.string(), plugins: z.array( z.object({ id: z.string(), origin: z.enum(["core", "local", "community"]), state: z.enum(["on", "off"]), version: z.string().nullable(), summary: z.string().nullable(), scopes: z.array( z.object({ kind: z.enum(["app", "unit", "flow"]), name: z.string().optional(), }), ), declares: z.array(z.string()), tables: z.record( z.string(), z.object({ plane: z.string().optional(), description: z.string().optional(), }), ), intercepts: z.array( z.object({ stage: z.string(), meanMs: z.number().nullable(), count: z.number(), }), ), hookCost: z .object({ count: z.number(), meanMs: z.number(), p50Ms: z.number(), p95Ms: z.number(), lastMs: z.number().nullable(), }) .nullable(), supplyChain: z.object({ lifecycleScripts: z.object({ state: SupplySignalStates, scripts: z.array(z.string()), detail: z.string(), }), releaseCooldown: z.object({ state: SupplySignalStates, publishedAt: z.number().nullable(), holdUntil: z.number().nullable(), detail: z.string(), }), nodeImportScan: z.object({ state: SupplySignalStates, findings: z.array( z.object({ source: z.string(), specifier: z.string(), line: z.number().nullable(), }), ), detail: z.string(), }), npmProvenance: z.object({ state: SupplySignalStates, detail: z.string(), }), bootConflicts: z.object({ state: SupplySignalStates, conflicts: z.array(z.string()), detail: z.string(), }), }), capabilityDiff: z.array( z.object({ path: z.string(), category: z.string(), kind: z.string(), summary: z.string(), }), ), installCommand: z.string().nullable(), enableHint: z.string().nullable(), packageName: z.string().nullable(), }), ), }); const GatesSimulateIn = z.object({ flowId: z.string().min(1), principal: z.object({ kind: z.enum(["role", "key", "user"]), id: z.string().min(1), }), meta: z .object({ ip: z.string().optional(), }) .optional(), }); const GatesSimulateOut = z.object({ flowId: z.string(), gates: z.array(z.string()), evaluations: z.array( z.object({ name: z.string(), allowed: z.boolean(), kind: z.enum(["policy", "rate"]), remaining: z.number().optional(), retryAfterMs: z.number().optional(), reason: z.string().optional(), }), ), deniedAt: z.string().nullable(), denial: z .object({ code: z.enum(["Unauthorized", "Forbidden", "RateLimited"]), data: z.record(z.string(), z.unknown()), status: z.union([z.literal(401), z.literal(403), z.literal(429)]), }) .nullable(), allowed: z.boolean(), }); const GatesPowersIn = z.object({ kind: z.enum(["role", "key", "user"]), id: z.string().min(1), }); const GatesPowersOut = z.object({ scopes: z.array(z.string()), allowedFlowIds: z.array(z.string()), deniedFlowIds: z.array(z.string()), }); const AccessKeyRowOut = z.object({ id: z.string(), name: z.string(), plane: z.enum(["user", "operator"]), creatorId: z.string(), creatorScopes: z.array(z.string()), scopes: z.array(z.string()), createdAt: z.number(), lastUsedAt: z.number().nullable(), expiresAt: z.number().nullable(), revokedAt: z.number().nullable(), rateLimit: z.object({ max: z.number(), per: z.string() }).nullable(), ipAllowlist: z.array(z.string()), unused90d: z.boolean(), }); const AccessPlaneSection = z.object({ plane: z.enum(["user", "operator"]), operators: z .array( z.object({ id: z.string(), email: z.string(), name: z.string(), status: z.enum(["active", "suspended", "invited"]), roles: z.array(z.string()), scopes: z.array(z.string()), lastSeenAt: z.number().nullable(), neverSignedIn: z.boolean(), }), ) .optional(), users: z .array( z.object({ id: z.string(), email: z.string(), name: z.string(), status: z.enum(["active", "disabled"]), roles: z.array(z.string()), scopes: z.array(z.string()), }), ) .optional(), roles: z.array( z.object({ id: z.string(), name: z.string(), plane: z.enum(["user", "operator"]), description: z.string(), scopes: z.array(z.string()), memberCount: z.number(), }), ), keys: z.array(AccessKeyRowOut), invites: z .array( z.object({ id: z.string(), email: z.string(), invitedBy: z.string(), createdAt: z.number(), expiresAt: z.number(), expired: z.boolean(), }), ) .optional(), grantableScopes: z.array(z.string()), }); const AccessListOut = z.object({ operatorPlane: AccessPlaneSection, userPlane: AccessPlaneSection, hygiene: z.object({ unusedKeys: z.array(AccessKeyRowOut), neverSignedInOperators: z.array( z.object({ id: z.string(), email: z.string(), name: z.string(), status: z.enum(["active", "suspended", "invited"]), roles: z.array(z.string()), scopes: z.array(z.string()), lastSeenAt: z.number().nullable(), neverSignedIn: z.boolean(), }), ), expiredInvitations: z.array( z.object({ id: z.string(), email: z.string(), invitedBy: z.string(), createdAt: z.number(), expiresAt: z.number(), expired: z.boolean(), }), ), }), accessTtlMs: z.number(), catalog: z.array(z.string()), }); const AccessEffectiveIn = z.object({ kind: z.enum(["operator", "user", "role", "key"]), id: z.string().min(1), }); const AccessEffectiveOut = z.object({ kind: z.enum(["operator", "user", "role", "key"]), id: z.string(), plane: z.enum(["user", "operator"]), scopes: z.array( z.object({ scope: z.string(), sources: z.array( z.object({ kind: z.enum(["role", "direct"]), id: z.string(), name: z.string(), }), ), }), ), }); const AccessKeyBlastIn = z.object({ keyId: z.string().min(1), }); const AccessKeyBlastOut = z.object({ callVolume: z.number(), lastUsedAt: z.number().nullable(), sourceAddresses: z.array(z.string()), accessTtlMs: z.number(), residualAccessNote: z.string(), }); const AccessCreateKeyIn = z.object({ plane: z.enum(["user", "operator"]), name: z.string().min(1), scopes: z.array(z.string()), /** Required for user-plane keys — issuer whose grants are the ceiling. */ creatorUserId: z.string().min(1).optional(), expiresAt: z.number().nullable().optional(), rateLimit: z.object({ max: z.number(), per: z.string() }).nullable().optional(), ipAllowlist: z.array(z.string()).optional(), }); const AccessUpdateKeyIn = z.object({ keyId: z.string().min(1), name: z.string().min(1).optional(), scopes: z.array(z.string()).optional(), expiresAt: z.number().nullable().optional(), rateLimit: z.object({ max: z.number(), per: z.string() }).nullable().optional(), ipAllowlist: z.array(z.string()).optional(), }); const AccessUpdateKeyOut = z.object({ key: AccessKeyRowOut, }); const AccessCreateKeyOut = z.object({ key: AccessKeyRowOut, /** Raw secret — returned exactly once. */ secret: z.string(), }); const AccessRevokeKeyIn = z.object({ keyId: z.string().min(1), confirmation: z.string().optional(), reason: z.string().optional(), }); const AccessRevokeKeyOut = z.object({ key: AccessKeyRowOut, blastRadius: AccessKeyBlastOut, }); const AccessRotateKeyIn = z.object({ keyId: z.string().min(1), confirmation: z.string().optional(), reason: z.string().optional(), }); const AccessRotateKeyOut = z.object({ key: AccessCreateKeyOut.shape.key, secret: z.string(), blastRadius: AccessKeyBlastOut, }); const AccessSetRoleGrantsIn = z.object({ roleId: z.string().min(1), scopes: z.array(z.string()), }); const AccessSetRoleGrantsOut = z.object({ roleId: z.string(), scopes: z.array(z.string()), }); const AccessGrantDenied = z.object({ reason: z.string() }); const AccessKeyNotFound = z.object({ keyId: z.string() }); const SignalNotFound = z.object({ signal: z.string() }); const DryRunUnsafe = z.object({ signal: z.string().optional(), ref: z.string().optional(), reason: z.string(), }); const TenantRequired = z.object({ reason: z.string(), }); const StoreNotFound = z.object({ ref: z.string() }); const WillNotFireOut = z.object({ writerFlowIds: z.array(z.string()), signals: z.array(z.string()), channels: z.array(z.string()), }); const StoreListOut = z.object({ tenancyDeclared: z.boolean(), tenants: z.array(z.string()), stores: z.array( z.object({ ref: z.string(), facet: z.enum(["sql", "kv", "files", "index"]), name: z.string(), description: z.string().optional(), children: z.array( z.object({ name: z.string(), effectRef: z.string(), kind: z.enum(["table", "index", "function", "trigger", "extension", "policy"]).optional(), writers: z.array(z.string()), readers: z.array(z.string()), cache: z.object({ producedByRead: z.string(), invalidatedByWrites: z.array(z.string()), invalidatingFlowIds: z.array(z.string()), }), willNotFire: WillNotFireOut, piiColumns: z.array(z.string()), columnDescriptions: z.record(z.string(), z.string()), rls: z.boolean().optional(), rlsPolicyCount: z.number().int().nonnegative().optional(), }), ), replicaLagMs: z.number().nullable(), migrationDrift: z .object({ declared: z.string(), applied: z.string().nullable(), drifted: z.boolean(), }) .nullable(), contentAddressed: z.boolean(), driverId: z.enum(["memory", "fs", "s3"]).optional(), warnings: z.array( z.object({ code: z.string(), message: z.string(), key: z.string(), }), ), }), ), }); const StoreRlsAs = { asGate: z.string().min(1).optional(), asUserId: z.string().min(1).optional(), }; const StoreRlsOut = z.object({ gate: z.string().nullable(), userId: z.string(), applied: z.boolean(), }); const StoreQueryIn = z.object({ ref: z.string().min(1), child: z.string().optional(), tenant: z.string().optional(), prefix: z.string().optional(), limit: z.number().min(1).max(500).optional(), vector: z.array(z.number()).optional(), q: z.string().optional(), topK: z.number().min(1).max(100).optional(), revealPii: z.boolean().optional(), ...StoreRlsAs, }); const StoreQueryOut = z.object({ facet: z.enum(["sql", "kv", "files", "index"]), rows: z.array(z.record(z.string(), z.unknown())).optional(), keys: z .array( z.object({ key: z.string(), value: z.unknown().optional(), ttlMs: z.number().nullable().optional(), sizeBytes: z.number().optional(), originalName: z.string().optional(), warnings: z.array(z.object({ code: z.string(), message: z.string() })).optional(), }), ) .optional(), hits: z .array( z.object({ id: z.string(), score: z.number(), meta: z.record(z.string(), z.unknown()).optional(), }), ) .optional(), masked: z.boolean(), routedRole: z.enum(["primary", "replica"]).optional(), rls: StoreRlsOut.optional(), }); const StoreRevealIn = z.object({ ref: z.string().min(1), child: z.string().optional(), tenant: z.string().optional(), id: z.string().min(1), column: z.string().min(1), }); const StoreRevealOut = z.object({ ok: z.literal(true), value: z.unknown(), at: z.string(), }); const StoreFileGetIn = z.object({ ref: z.string().min(1), key: z.string().min(1), tenant: z.string().optional(), }); const StoreFileGetOut = z.object({ key: z.string(), sizeBytes: z.number(), contentType: z.string(), encoding: z.enum(["utf8", "base64"]), body: z.string(), truncated: z.boolean(), originalName: z.string().optional(), warnings: z.array(z.object({ code: z.string(), message: z.string() })), }); const StoreEditIn = z.object({ ref: z.string().min(1), child: z.string().optional(), tenant: z.string().optional(), id: z.string().optional(), key: z.string().optional(), patch: z.record(z.string(), z.unknown()), confirmation: z.string().optional(), reason: z.string().optional(), /** When false/omitted, returns willNotFire without applying. */ commit: z.boolean().optional(), ...StoreRlsAs, }); const StoreEditOut = z.object({ ok: z.literal(true), dryRun: z.boolean(), applied: z.boolean(), willNotFire: WillNotFireOut, wouldHaveFired: z.array( z.object({ kind: z.enum(["send", "ask", "embed", "fetch"]), resource: z.string(), }), ), at: z.string(), rls: StoreRlsOut.optional(), }); const StoreDeleteIn = z.object({ ref: z.string().min(1), child: z.string().optional(), tenant: z.string().optional(), ids: z.array(z.string()).optional(), keys: z.array(z.string()).optional(), confirmation: z.string().optional(), reason: z.string().optional(), }); const StoreDeleteOut = z.object({ ok: z.literal(true), deleted: z.number(), at: z.string(), }); const StorePurgeIn = z.object({ resource: z.string().min(1), confirmation: z.string().optional(), reason: z.string().optional(), }); const StorePurgeOut = z.object({ ok: z.literal(true), keys: z.array(z.string()), at: z.string(), }); const StoreSqlIn = z.object({ ref: z.string().min(1), sql: z.string().min(1), tenant: z.string().optional(), allowWrite: z.boolean().optional(), revealPii: z.boolean().optional(), asGate: z.string().min(1).optional(), asUserId: z.string().min(1).optional(), }); const StoreSqlOut = z.object({ rows: z.array(z.record(z.string(), z.unknown())), masked: z.boolean(), routedRole: z.enum(["primary", "replica"]), asGate: z.string().nullable(), asUserId: z.string().nullable(), gateApplied: z.boolean(), rls: StoreRlsOut.optional(), }); const StoreSqlStatsIn = z.object({ ref: z.string().min(1), tenant: z.string().optional(), }); const StoreSqlStatsOut = z.object({ statements: z.array( z.object({ queryid: z.string().nullable(), query: z.string().nullable(), calls: z.number(), totalExecMs: z.number(), meanExecMs: z.number(), minExecMs: z.number(), maxExecMs: z.number(), rows: z.number(), sharedBlksHit: z.number(), sharedBlksRead: z.number(), cacheHitRate: z.number().nullable(), }), ), kpis: z.object({ slowQueries: z.number(), cacheHitRate: z.number().nullable(), avgRowsPerCall: z.number().nullable(), }), limitation: z.literal(STORE_SQL_STATS_PII_GAP), rowCount: z.number(), truncated: z.boolean(), advisor: z.object({ available: z.boolean(), installed: z.boolean(), hypopgAvailable: z.boolean(), }), }); const StoreSqlLocksIn = z.object({ ref: z.string().min(1), tenant: z.string().optional(), revealPii: z.boolean().optional(), }); const StoreSqlLocksOut = z.object({ rows: z.array( z.object({ blockedPid: z.number().nullable(), blockedUser: z.string().nullable(), blockedQuery: z.string().nullable(), blockedAt: z.string().nullable(), blockingPid: z.number().nullable(), blockingUser: z.string().nullable(), blockingQuery: z.string().nullable(), blockingState: z.string().nullable(), waitEventType: z.string().nullable(), waitEvent: z.string().nullable(), }), ), masked: z.boolean(), limitation: z.literal(STORE_SQL_STATS_PII_GAP), pollingMs: z.literal(STORE_SQL_LOCKS_POLL_MS), }); const StoreSqlAdviseIn = z.object({ ref: z.string().min(1), query: z.string().min(1), tenant: z.string().optional(), }); const StoreSqlAdviseOut = z.object({ startupCostBefore: z.unknown(), startupCostAfter: z.unknown(), totalCostBefore: z.unknown(), totalCostAfter: z.unknown(), indexStatements: z.array(z.string()), errors: z.array(z.string()), }); const PgStatStatementsNotPreloaded = z.object({ reason: z.string() }); const PgStatStatementsUnsupported = z.object({ reason: z.string() }); const PgStatStatementsNotCreated = z.object({ reason: z.string() }); const StoreKvStatsIn = z.object({ ref: z.string().min(1), tenant: z.string().optional(), revealPii: z.boolean().optional(), }); const StoreKvStatsOut = z.object({ engine: z.enum(["redis", "memory"]), kpis: z.object({ hitRate: z.number().nullable(), opsPerSec: z.number().nullable(), evictedKeys: z.number().nullable(), expiredKeys: z.number().nullable(), }), commands: z.array( z.object({ command: z.string(), calls: z.number(), usec: z.number(), usecPerCall: z.number().nullable(), }), ), slowlog: z.array( z.object({ id: z.number(), timestamp: z.number(), durationUs: z.number(), command: z.string(), args: z.array(z.string()), }), ), latency: z.array( z.object({ event: z.string(), latestUs: z.number().nullable(), allTimeUs: z.number().nullable(), }), ), limitation: z.literal(STORE_KV_STATS_SERVER_WIDE_GAP), slowlogLimitation: z.literal(STORE_KV_STATS_SLOWLOG_ARGS_GAP), masked: z.boolean(), namespacePrefix: z.string(), }); const KvStatsUnsupported = z.object({ reason: z.string() }); const RunsQueryIn = z.object({ sql: z.string().min(1), revealPii: z.boolean().optional(), }); const RunsQueryOut = z.object({ rows: z.array(z.record(z.string(), z.unknown())), truncated: z.boolean(), rowCount: z.number(), masked: z.literal("column-keys"), durationMs: z.number(), limitation: z.literal(RUNS_QUERY_PII_GAP), injectedLimit: z.boolean(), }); const StorePreviewIn = z.object({ ref: z.string().min(1), child: z.string().optional(), tenant: z.string().optional(), id: z.string().optional(), key: z.string().optional(), patch: z.record(z.string(), z.unknown()), }); const StorePreviewOut = z.object({ ok: z.literal(true), dryRun: z.literal(true), willNotFire: WillNotFireOut, wouldHaveFired: z.array( z.object({ kind: z.enum(["send", "ask", "embed", "fetch"]), resource: z.string(), }), ), at: z.string(), }); /** * Build all Console HTTP bindings against shared state. * * @param state - Console state */ export function createConsoleBindings(state: ConsoleState): { readonly bindings: Binding[]; readonly routes: { readonly setup: { readonly status: AnyFlowDef; readonly claim: AnyFlowDef; }; readonly session: { readonly login: AnyFlowDef; readonly me: AnyFlowDef; readonly logout: AnyFlowDef; }; readonly manifest: { readonly get: AnyFlowDef }; readonly runs: { readonly list: AnyFlowDef; readonly query: AnyFlowDef }; readonly action: { readonly ping: AnyFlowDef }; readonly structural: { readonly propose: AnyFlowDef; }; readonly flows: { readonly identities: AnyFlowDef; readonly invoke: AnyFlowDef; }; readonly traces: { readonly replay: AnyFlowDef; }; readonly signals: { readonly list: AnyFlowDef; readonly replay: AnyFlowDef; readonly dryRunReplay: AnyFlowDef; readonly discard: AnyFlowDef; }; readonly store: { readonly list: AnyFlowDef; readonly query: AnyFlowDef; readonly reveal: AnyFlowDef; readonly object: AnyFlowDef; readonly edit: AnyFlowDef; readonly delete: AnyFlowDef; readonly purgeCache: AnyFlowDef; readonly sql: AnyFlowDef; readonly preview: AnyFlowDef; readonly stats: AnyFlowDef; readonly locks: AnyFlowDef; readonly advise: AnyFlowDef; readonly kvStats: AnyFlowDef; }; readonly vault: { readonly list: AnyFlowDef; readonly set: AnyFlowDef; readonly create: AnyFlowDef; readonly rotate: AnyFlowDef; readonly rotateMaster: AnyFlowDef; readonly auditVerify: AnyFlowDef; }; readonly ai: { readonly list: AnyFlowDef; }; readonly gates: { readonly list: AnyFlowDef; readonly simulate: AnyFlowDef; readonly powers: AnyFlowDef; }; readonly access: { readonly list: AnyFlowDef; readonly effective: AnyFlowDef; readonly keyBlast: AnyFlowDef; readonly createKey: AnyFlowDef; readonly revokeKey: AnyFlowDef; readonly rotateKey: AnyFlowDef; readonly updateKey: AnyFlowDef; readonly setRoleGrants: AnyFlowDef; }; readonly diff: { readonly list: AnyFlowDef; }; readonly plugin: { readonly list: AnyFlowDef; }; readonly clock: { readonly list: AnyFlowDef; readonly runNow: AnyFlowDef; readonly pause: AnyFlowDef; readonly editSchedule: AnyFlowDef; readonly wakeEarly: AnyFlowDef; }; readonly instances: { readonly list: AnyFlowDef; }; readonly channel: { readonly list: AnyFlowDef; readonly preview: AnyFlowDef; readonly verifyAuth: AnyFlowDef; readonly reveal: AnyFlowDef; readonly sendTest: AnyFlowDef; }; }; } { const setupStatus = createSetupStatus(state); const setupClaim = createSetupClaim(state); const sessionLogin = createSessionLogin(state); const sessionMe = createSessionMe(state); const sessionLogout = createSessionLogout(); const manifestGet = createManifestGet(state); const runsList = createRunsList(state); const runsQuery = createRunsQuery(state); const actionPing = createActionPing(state); const structuralPropose = createStructuralPropose(state); const flowsIdentities = createFlowsIdentities(state); const flowsInvoke = createFlowsInvoke(state); const tracesReplay = createTracesReplay(state); const signalsList = createSignalsList(state); const signalsReplay = createSignalsReplay(state); const signalsDryRunReplay = createSignalsDryRunReplay(state); const signalsDiscard = createSignalsDiscard(state); const storeList = createStoreList(state); const storeQuery = createStoreQuery(state); const storeReveal = createStoreReveal(state); const storeObject = createStoreObject(state); const storeEdit = createStoreEdit(state); const storeDelete = createStoreDelete(state); const storePurgeCache = createStorePurgeCache(state); const storeSql = createStoreSql(state); const storePreview = createStorePreview(state); const storeStats = createStoreSqlStats(state); const storeLocks = createStoreSqlLocks(state); const storeAdvise = createStoreSqlAdvise(state); const storeKvStats = createStoreKvStats(state); const vaultList = createVaultList(state); const vaultSet = createVaultSet(state); const vaultCreate = createVaultCreate(state); const vaultRotate = createVaultRotate(state); const vaultRotateMaster = createVaultRotateMaster(state); const vaultAuditVerify = createVaultAuditVerify(state); const aiList = createAiList(state); const gatesList = createGatesList(state); const gatesSimulate = createGatesSimulate(state); const gatesPowers = createGatesPowers(state); const accessList = createAccessList(state); const accessEffective = createAccessEffective(state); const accessKeyBlast = createAccessKeyBlast(state); const accessCreateKeyFlow = createAccessCreateKey(state); const accessRevokeKeyFlow = createAccessRevokeKey(state); const accessRotateKeyFlow = createAccessRotateKey(state); const accessUpdateKeyFlow = createAccessUpdateKey(state); const accessSetRoleGrantsFlow = createAccessSetRoleGrants(state); const diffList = createDiffList(state); const pluginsList = createPluginsList(state); const clockList = createClockList(state); const instancesList = createInstancesList(state); const clockRunNow = createClockRunNow(state); const clockPause = createClockPause(state); const clockEditSchedule = createClockEditSchedule(state); const clockWakeEarly = createClockWakeEarly(state); const channelsList = createChannelsList(state); const channelPreview = createChannelPreview(state); const channelVerifyAuth = createChannelVerifyAuth(state); const channelReveal = createChannelReveal(state); const channelSendTest = createChannelSendTest(state); const bindings: Binding[] = [ bindHttp(http.get("/console/setup/status", { out: SetupStatusOut }), setupStatus), bindHttp( http.post("/console/setup/claim", { in: ClaimIn, out: SessionOut, errors: { SetupClosed, ClaimFailed }, }), setupClaim, ), bindHttp( http.post("/console/session/login", { in: LoginIn, out: SessionOut, errors: { AuthFailed, AuthRateLimited }, }), sessionLogin, ), bindHttp(http.get("/console/session/me", { out: MeOut, errors: { AuthFailed } }), sessionMe), bindHttp( http.post("/console/session/logout", { out: z.object({ ok: z.literal(true) }) }), sessionLogout, ), bindHttp( http.get("/console/manifest", { out: ManifestOut, errors: { AuthFailed } }), manifestGet, ), bindHttp(http.get("/console/runs", { out: RunsListOut, errors: { AuthFailed } }), runsList), bindHttp( http.post("/console/runs/query", { in: RunsQueryIn, out: RunsQueryOut, errors: { AuthFailed, QueryRejected, QueryTimeout, QueryFailed }, }), runsQuery, ), bindHttp( http.post("/console/action/ping", { in: ActionPingIn, out: ActionPingOut, errors: { AuthFailed }, }), actionPing, ), bindHttp( http.post("/console/structural/propose", { in: StructuralIn, out: StructuralOut, errors: { AuthFailed }, }), structuralPropose, ), bindHttp( http.get("/console/flows/identities", { out: IdentitiesOut, errors: { AuthFailed } }), flowsIdentities, ), bindHttp( http.post("/console/flows/invoke", { in: InvokeIn, out: InvokeOut, errors: { AuthFailed, NotFound, InvokeDenied, ConfirmRequired }, }), flowsInvoke, ), bindHttp( http.post("/console/traces/replay", { in: TracesReplayIn, out: TracesReplayOut, errors: { AuthFailed, NotFound, ReplayUnavailable, ReplayFailed }, }), tracesReplay, ), bindHttp( http.get("/console/signals", { out: SignalsListOut, errors: { AuthFailed } }), signalsList, ), bindHttp( http.post("/console/signals/replay", { in: SignalsReplayIn, out: SignalsReplayOut, errors: { AuthFailed, SignalNotFound, ConfirmRequired }, }), signalsReplay, ), bindHttp( http.post("/console/signals/dry-run-replay", { in: SignalsReplayIn.omit({ dryRun: true }), out: SignalsReplayOut, errors: { AuthFailed, SignalNotFound, DryRunUnsafe }, }), signalsDryRunReplay, ), bindHttp( http.post("/console/signals/discard", { in: SignalsDiscardIn, out: SignalsDiscardOut, errors: { AuthFailed, SignalNotFound, ConfirmRequired }, }), signalsDiscard, ), bindHttp(http.get("/console/store", { out: StoreListOut, errors: { AuthFailed } }), storeList), bindHttp( http.query("/console/store/query", { in: StoreQueryIn, out: StoreQueryOut, errors: { AuthFailed, TenantRequired, StoreNotFound }, }), storeQuery, ), bindHttp( http.post("/console/store/reveal", { in: StoreRevealIn, out: StoreRevealOut, errors: { AuthFailed, TenantRequired, StoreNotFound }, }), storeReveal, ), bindHttp( http.post("/console/store/object", { in: StoreFileGetIn, out: StoreFileGetOut, errors: { AuthFailed, TenantRequired, StoreNotFound }, }), storeObject, ), bindHttp( http.post("/console/store/edit", { in: StoreEditIn, out: StoreEditOut, errors: { AuthFailed, TenantRequired, ConfirmRequired, StoreNotFound }, }), storeEdit, ), bindHttp( http.post("/console/store/delete", { in: StoreDeleteIn, out: StoreDeleteOut, errors: { AuthFailed, TenantRequired, ConfirmRequired }, }), storeDelete, ), bindHttp( http.post("/console/store/purge-cache", { in: StorePurgeIn, out: StorePurgeOut, errors: { AuthFailed, ConfirmRequired }, }), storePurgeCache, ), bindHttp( http.post("/console/store/sql", { in: StoreSqlIn, out: StoreSqlOut, errors: { AuthFailed, TenantRequired, StoreNotFound }, }), storeSql, ), bindHttp( http.post("/console/store/preview", { in: StorePreviewIn, out: StorePreviewOut, errors: { AuthFailed, TenantRequired, DryRunUnsafe }, }), storePreview, ), bindHttp( http.query("/console/store/sql/stats", { in: StoreSqlStatsIn, out: StoreSqlStatsOut, errors: { AuthFailed, TenantRequired, StoreNotFound, PgStatStatementsNotPreloaded, PgStatStatementsUnsupported, PgStatStatementsNotCreated, }, }), storeStats, ), bindHttp( http.query("/console/store/sql/locks", { in: StoreSqlLocksIn, out: StoreSqlLocksOut, errors: { AuthFailed, TenantRequired, StoreNotFound, PgStatStatementsNotPreloaded, PgStatStatementsUnsupported, PgStatStatementsNotCreated, }, }), storeLocks, ), bindHttp( http.query("/console/store/kv/stats", { in: StoreKvStatsIn, out: StoreKvStatsOut, errors: { AuthFailed, TenantRequired, StoreNotFound, KvStatsUnsupported }, }), storeKvStats, ), bindHttp( http.post("/console/store/sql/advise", { in: StoreSqlAdviseIn, out: StoreSqlAdviseOut, errors: { AuthFailed, TenantRequired, StoreNotFound, PgStatStatementsNotPreloaded, PgStatStatementsUnsupported, PgStatStatementsNotCreated, }, }), storeAdvise, ), bindHttp(http.get("/console/vault", { out: VaultListOut, errors: { AuthFailed } }), vaultList), bindHttp( http.post("/console/vault/set", { in: VaultWriteIn, out: VaultWriteOut, errors: { AuthFailed, VaultNotFound }, }), vaultSet, ), bindHttp( http.post("/console/vault/create", { in: VaultCreateIn, out: VaultWriteOut, errors: { AuthFailed, VaultExists, VaultNotFound }, }), vaultCreate, ), bindHttp( http.post("/console/vault/rotate", { in: VaultWriteIn, out: VaultWriteOut, errors: { AuthFailed, VaultNotFound }, }), vaultRotate, ), bindHttp( http.post("/console/vault/rotate-master", { in: VaultRotateMasterIn, out: VaultRotateMasterOut, errors: { AuthFailed, ConfirmRequired, VaultSealed, VaultRotateBusy, VaultUnsupported }, }), vaultRotateMaster, ), bindHttp( http.get("/console/vault/audit/verify", { out: VaultAuditVerifyOut, errors: { AuthFailed, VaultUnsupported }, }), vaultAuditVerify, ), bindHttp(http.get("/console/ai", { out: AiListOut, errors: { AuthFailed } }), aiList), bindHttp(http.get("/console/gates", { out: GatesListOut, errors: { AuthFailed } }), gatesList), bindHttp( http.query("/console/gates/simulate", { in: GatesSimulateIn, out: GatesSimulateOut, errors: { AuthFailed }, }), gatesSimulate, ), bindHttp( http.query("/console/gates/powers", { in: GatesPowersIn, out: GatesPowersOut, errors: { AuthFailed }, }), gatesPowers, ), bindHttp( http.get("/console/access", { out: AccessListOut, errors: { AuthFailed } }), accessList, ), bindHttp( http.query("/console/access/effective", { in: AccessEffectiveIn, out: AccessEffectiveOut, errors: { AuthFailed, NotFound }, }), accessEffective, ), bindHttp( http.post("/console/access/key-blast", { in: AccessKeyBlastIn, out: AccessKeyBlastOut, errors: { AuthFailed, AccessKeyNotFound }, }), accessKeyBlast, ), bindHttp( http.post("/console/access/keys", { in: AccessCreateKeyIn, out: AccessCreateKeyOut, errors: { AuthFailed, AccessGrantDenied }, }), accessCreateKeyFlow, ), bindHttp( http.post("/console/access/keys/revoke", { in: AccessRevokeKeyIn, out: AccessRevokeKeyOut, errors: { AuthFailed, AccessKeyNotFound, ConfirmRequired }, }), accessRevokeKeyFlow, ), bindHttp( http.post("/console/access/keys/rotate", { in: AccessRotateKeyIn, out: AccessRotateKeyOut, errors: { AuthFailed, AccessKeyNotFound, ConfirmRequired }, }), accessRotateKeyFlow, ), bindHttp( http.post("/console/access/keys/update", { in: AccessUpdateKeyIn, out: AccessUpdateKeyOut, errors: { AuthFailed, AccessKeyNotFound, AccessGrantDenied }, }), accessUpdateKeyFlow, ), bindHttp( http.post("/console/access/roles/grants", { in: AccessSetRoleGrantsIn, out: AccessSetRoleGrantsOut, errors: { AuthFailed, AccessGrantDenied }, }), accessSetRoleGrantsFlow, ), bindHttp(http.get("/console/diff", { out: DiffListOut, errors: { AuthFailed } }), diffList), bindHttp( http.get("/console/plugins", { out: PluginsListOut, errors: { AuthFailed } }), pluginsList, ), bindHttp(http.get("/console/clock", { out: ClockListOut, errors: { AuthFailed } }), clockList), bindHttp( http.get("/console/instances", { out: InstancesListOut, errors: { AuthFailed } }), instancesList, ), bindHttp( http.post("/console/clock/run-now", { in: ClockRunNowIn, out: ClockRunNowOut, errors: { AuthFailed, ClockNotFound, ConfirmRequired }, }), clockRunNow, ), bindHttp( http.post("/console/clock/pause", { in: ClockPauseIn, out: ClockPauseOut, errors: { AuthFailed, ClockNotFound }, }), clockPause, ), bindHttp( http.post("/console/clock/edit-schedule", { in: ClockEditIn, out: ClockEditOut, errors: { AuthFailed, ClockNotFound, ScheduleNotOverridable }, }), clockEditSchedule, ), bindHttp( http.post("/console/clock/wake-early", { in: ClockWakeEarlyIn, out: ClockWakeEarlyOut, errors: { AuthFailed, ClockNotFound }, }), clockWakeEarly, ), bindHttp( http.get("/console/channels", { out: ChannelsListOut, errors: { AuthFailed } }), channelsList, ), bindHttp( http.query("/console/channels/preview", { in: ChannelPreviewIn, out: ChannelPreviewOut, errors: { AuthFailed, ChannelNotFound }, }), channelPreview, ), bindHttp( http.post("/console/channels/verify-auth", { in: ChannelVerifyAuthIn, out: ChannelVerifyAuthOut, errors: { AuthFailed }, }), channelVerifyAuth, ), bindHttp( http.post("/console/channels/reveal", { in: ChannelRevealIn, out: ChannelRevealOut, errors: { AuthFailed, ChannelNotFound }, }), channelReveal, ), bindHttp( http.post("/console/channels/send-test", { in: ChannelSendTestIn, out: ChannelSendTestOut, errors: { AuthFailed, ChannelNotFound, ConfirmRequired }, }), channelSendTest, ), ...lazyRequire( import.meta.dir, ["decisions", "flows"].join("-"), ).decisionConsoleBindings(state), ...lazyRequire( import.meta.dir, ["ai", "runs", "flows"].join("-"), ).agentConsoleBindings(state), ]; return { bindings, routes: { setup: { status: setupStatus, claim: setupClaim }, session: { login: sessionLogin, me: sessionMe, logout: sessionLogout }, manifest: { get: manifestGet }, runs: { list: runsList, query: runsQuery }, action: { ping: actionPing }, structural: { propose: structuralPropose }, flows: { identities: flowsIdentities, invoke: flowsInvoke }, traces: { replay: tracesReplay }, signals: { list: signalsList, replay: signalsReplay, dryRunReplay: signalsDryRunReplay, discard: signalsDiscard, }, store: { list: storeList, query: storeQuery, reveal: storeReveal, object: storeObject, edit: storeEdit, delete: storeDelete, purgeCache: storePurgeCache, sql: storeSql, preview: storePreview, stats: storeStats, locks: storeLocks, advise: storeAdvise, kvStats: storeKvStats, }, vault: { list: vaultList, set: vaultSet, create: vaultCreate, rotate: vaultRotate, rotateMaster: vaultRotateMaster, auditVerify: vaultAuditVerify, }, ai: { list: aiList }, gates: { list: gatesList, simulate: gatesSimulate, powers: gatesPowers, }, access: { list: accessList, effective: accessEffective, keyBlast: accessKeyBlast, createKey: accessCreateKeyFlow, revokeKey: accessRevokeKeyFlow, rotateKey: accessRotateKeyFlow, updateKey: accessUpdateKeyFlow, setRoleGrants: accessSetRoleGrantsFlow, }, diff: { list: diffList }, plugin: { list: pluginsList }, clock: { list: clockList, runNow: clockRunNow, pause: clockPause, editSchedule: clockEditSchedule, wakeEarly: clockWakeEarly, }, instances: { list: instancesList }, channel: { list: channelsList, preview: channelPreview, verifyAuth: channelVerifyAuth, reveal: channelReveal, sendTest: channelSendTest, }, }, }; } function createSetupStatus(state: ConsoleState) { return flow("console.setup.status", { plane: "operator", do: () => ({ setupClosed: state.setupClosed, claimRequired: !state.setupClosed, }), }); } function createSetupClaim(state: ConsoleState) { return flow("console.setup.claim", { plane: "operator", do: async (input: z.infer, fx) => { if (state.setupClosed) { const data = { reason: "first_operator_exists" }; return fail("SetupClosed", data, { message: consoleFailureMessage("SetupClosed", data) }); } const verified = verifyClaimCode(state.claim, input.claimCode, state.now); if (!verified.ok) { const data = { reason: verified.reason }; return fail("ClaimFailed", data, { message: consoleFailureMessage("ClaimFailed", data) }); } let op: Awaited>; try { op = await createOperator(state.operators, { email: input.email, name: input.name, password: input.password, passwordPolicy: CONSOLE_PASSWORD_POLICY, }); } catch (err) { if (err instanceof PasswordPolicyError) { const data = { reason: "password_policy", reasons: [...err.reasons], }; return fail("ClaimFailed", data, { message: consoleFailureMessage("ClaimFailed", data), }); } if (err instanceof BreachCheckError) { const data = { reason: "password_breached" }; return fail("ClaimFailed", data, { message: consoleFailureMessage("ClaimFailed", data), }); } throw err; } await state.persistOperator(op.id); clearClaimCodeArtifact(state.cwd); const issued = await issueOperatorSession(state, op.id); fx.log.info("console.setup.claim", { operatorId: op.id }); return sessionPayload(op.id, op.email, op.name, issued); }, }); } function createSessionLogin(state: ConsoleState) { return flow("console.session.login", { plane: "operator", do: async (input: z.infer, fx) => { if (touchLoginRateLimit(state.loginAttempts, input.email, state.now()) === "rate_limited") { return fail("AuthRateLimited", { reason: "too many login attempts; retry after 60s", }); } const op = await authenticateOperator(state.operators, input.email, input.password); if (!op) return fail("AuthFailed", {}); const issued = await issueOperatorSession(state, op.id); fx.log.info("console.session.login", { operatorId: op.id }); return sessionPayload(op.id, op.email, op.name, issued); }, }); } function createSessionMe(state: ConsoleState) { return flow("console.session.me", { plane: "operator", do: (_input, fx) => { const id = fx.operator.id; if (!id) return fail("AuthFailed", {}); const op = state.operators.operators.get(id); if (!op) return fail("AuthFailed", {}); return { operatorId: op.id, email: op.email, name: op.name, setupClosed: state.setupClosed, }; }, }); } function createSessionLogout() { return flow("console.session.logout", { plane: "operator", do: (_input, fx) => { fx.log.info("console.session.logout", { operatorId: fx.operator.id, }); return { ok: true as const }; }, }); } function createManifestGet(state: ConsoleState) { return flow("console.manifest.get", { plane: "operator", do: (_input, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); return { manifest: state.manifest }; }, }); } function createRunsQuery(state: ConsoleState) { return flow("console.runs.query", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); if (input.revealPii === true) { fx.log.info("console.runs.query.reveal", { operatorId: fx.operator.id, }); } try { const result = await state.queryPersistedRuns({ sql: input.sql, revealPii: input.revealPii === true, }); fx.log.info("console.runs.query", { operatorId: fx.operator.id, revealPii: input.revealPii === true, rowCount: result.rowCount, truncated: result.truncated, }); return result; } catch (err) { if (err instanceof DuckQueryTimeoutError) { return fail("QueryTimeout", { timeoutMs: err.timeoutMs }); } if (err instanceof ConsoleRunsQueryError) { if (err.code === "QueryTimeout") { const match = /^timeout:(\d+)$/.exec(err.reason); return fail("QueryTimeout", { timeoutMs: match ? Number(match[1]) : RUNS_QUERY_TIMEOUT_MS, }); } return fail(err.code, { reason: err.reason }); } return fail("QueryFailed", { reason: err instanceof Error ? err.message : String(err) }); } }, }); } function createRunsList(state: ConsoleState) { return flow("console.runs.list", { plane: "operator", do: async (_input, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); const all = await state.listRuns(); const piiFields = piiFieldNamesFromManifest(state.manifest); // Drop prior list polls — they are operator chrome, not Traces rows, // and must never re-enter the projection (nested-output bomb). return { runs: all .filter((r) => r.flow !== "console.runs.list") .map((r) => projectRun(r, piiFields)), }; }, }); } /** * Project a wide event for GET /console/runs (Runs · Traces · Overview). * * PII-classified fields are masked centrally here so every panel that reads * the shared wide-event store sees the same redaction as Store's row browser. * * @param r - Stored wide event * @param piiFields - Classified field names from the Manifest */ export function projectRun(r: WideEvent, piiFields: ReadonlySet = new Set()) { const masked = maskWideEventForConsole(r, piiFields); const dimensions: Record = {}; for (const [k, v] of Object.entries(masked.dimensions)) { if (v === undefined) continue; dimensions[k] = v; } return { id: r.id, parentId: r.parentId ?? null, flow: r.flow, unit: r.unit ?? null, trigger: r.trigger, plane: r.plane, tenant: r.tenant ?? null, principal: r.principal ?? null, gates: [...r.gates], cache: r.cache, replica: r.replica ?? null, replicaLagMs: r.replicaLagMs ?? null, cost: r.cost ?? null, inputTokens: r.inputTokens ?? null, outputTokens: r.outputTokens ?? null, promptVersion: r.promptVersion ?? null, buildVersion: r.buildVersion ?? null, startedAt: r.startedAt, endedAt: r.endedAt, durationMs: r.durationMs, error: masked.error?.code ?? null, errorMessage: masked.error?.message ?? null, sampled: masked.error ? ("error" as const) : ("sample" as const), effects: masked.effects.map((e) => ({ kind: e.kind, resource: e.resource, timestamp: e.timestamp, duration: e.duration, reversibility: e.reversibility, ...(e.external !== undefined ? { external: e.external } : {}), ...(e.agentRunId !== undefined ? { agentRunId: e.agentRunId } : {}), })), logs: masked.logs.map((line) => ({ level: line.level, message: line.message, ...(line.data !== undefined ? { data: line.data } : {}), at: line.at, })), dimensions, input: masked.input === undefined ? null : masked.input, output: masked.output === undefined ? null : masked.output, http: r.http ? redactHttpFrame(r.http) : null, }; } function createTracesReplay(state: ConsoleState) { return flow("console.traces.replay", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); const all = await state.listRuns(); const root = all.find((r) => r.id === input.rootId); if (!root) return fail("NotFound", { flowId: input.rootId }); if (root.input === undefined) { return fail("ReplayUnavailable", { rootId: input.rootId, reason: "no_stored_input" as const, }); } const irreversible = eventHasIrreversible(root); const dryRun = input.dryRun || irreversible; const runs = createRunsRuntime({ driver: "memory" }); await runs.open(); await runs.append(root); const lines: string[] = []; const code = await runReplay({ requestId: input.rootId, cwd: state.cwd, dryRun: dryRun ? true : undefined, live: dryRun ? undefined : true, runs, write: (t) => lines.push(t), ...(state.replayTrace ? { executeReplay: async (_entry: string, event: WideEvent, d: boolean) => state.replayTrace!({ event, dryRun: d }), } : {}), }); if (code !== 0) { return fail("ReplayFailed", { rootId: input.rootId, message: lines.join("").trim() || "replay failed", }); } fx.log.info("console.traces.replay", { operatorId: fx.operator.id, rootId: input.rootId, dryRun, flow: root.flow, }); return { ok: true as const, rootId: input.rootId, dryRun, at: isoAt(Date.now()), flow: root.flow, }; }, }); } function createSignalsList(state: ConsoleState) { return flow("console.signals.list", { plane: "operator", do: async (_input, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); const signals = await state.listSignals(); return { signals: [...signals] }; }, }); } function createSignalsReplay(state: ConsoleState) { return flow("console.signals.replay", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); return runSignalReplay(state, fx, { ...input, dryRun: false }); }, }); } function createSignalsDryRunReplay(state: ConsoleState) { return flow("console.signals.dryRunReplay", { plane: "operator", do: async (input: Omit, "dryRun">, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); return runSignalReplay(state, fx, { ...input, dryRun: true }); }, }); } function createSignalsDiscard(state: ConsoleState) { return flow("console.signals.discard", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); const rows = await state.listSignals(); const row = rows.find((s) => s.name === input.signal); if (!row) return fail("SignalNotFound", { signal: input.signal }); const irreversible = state.production && row.consumers.some((c) => c.external || !c.durable); if (irreversible) { if (input.confirmation !== "DISCARD" || (input.reason?.trim().length ?? 0) < 3) { return fail("ConfirmRequired", { phrase: "DISCARD" as const, reason: "discarding dead letters requires typed confirmation", }); } } const result = await state.discardSignals({ signal: input.signal, messageIds: input.messageIds, }); fx.log.info("console.signals.discard", { operatorId: fx.operator.id, signal: input.signal, discarded: result.discarded, reason: input.reason, }); return { ok: true as const, discarded: result.discarded, at: isoAt(state.now()), }; }, }); } async function runSignalReplay( state: ConsoleState, fx: { operator: { id: string | null }; log: { info: (m: string, data?: Record) => void }; }, input: z.infer, ) { const rows = await state.listSignals(); const row = rows.find((s) => s.name === input.signal); if (!row) return fail("SignalNotFound", { signal: input.signal }); if (input.dryRun) { // Same refusal spirit as Traces: if we cannot offer a safe stubbed // dry run for this consumer shape, refuse rather than risk a side effect. const safety = dryRunSafety(row); if (!safety.ok) { return fail("DryRunUnsafe", { signal: input.signal, reason: safety.reason, }); } } else { const retriggersExternal = state.production && row.consumers.some((c) => c.external) && row.consumersDurable !== true; if (retriggersExternal) { if (input.confirmation !== "REPLAY" || (input.reason?.trim().length ?? 0) < 3) { return fail("ConfirmRequired", { phrase: "REPLAY" as const, reason: "replay re-triggers an external effect; typed confirmation required", }); } } } const result = await state.replaySignals({ signal: input.signal, messageIds: input.messageIds, subscriberId: input.subscriberId, ratePerSec: input.ratePerSec, dryRun: input.dryRun, payloads: input.payloads, }); if (result.refused) { return fail("DryRunUnsafe", { signal: input.signal, reason: result.refused.reason, }); } fx.log.info(input.dryRun ? "console.signals.dryRunReplay" : "console.signals.replay", { operatorId: fx.operator.id, signal: input.signal, attempted: result.attempted, succeeded: result.succeeded, failed: result.failed, dryRun: result.dryRun, ratePerSec: input.ratePerSec, reason: input.reason, wouldHaveFired: result.wouldHaveFired.length, }); return { ok: true as const, attempted: result.attempted, succeeded: result.succeeded, failed: result.failed, dryRun: result.dryRun, results: [...result.results], wouldHaveFired: [...result.wouldHaveFired], at: isoAt(state.now()), }; } /** * Whether a dry-run can be offered safely for this signal. * * Orphaned / unknown consumers cannot be stubbed with confidence — refuse, * the same way Traces refuses a live replay when it cannot offer a safe dry run. * * @param row - Projected signal row */ function dryRunSafety(row: { readonly orphaned: boolean; readonly consumers: ReadonlyArray<{ readonly flowId: string }>; }): { readonly ok: true } | { readonly ok: false; readonly reason: string } { if (row.orphaned) { return { ok: false, reason: "Orphaned signal — consumer shape unknown; dry-run refused rather than risk a side effect.", }; } if (row.consumers.length === 0) { return { ok: false, reason: "No Manifest consumer — dry-run refused rather than invoke an unknown handler unsafely.", }; } return { ok: true }; } function createActionPing(state: ConsoleState) { return flow("console.action.ping", { plane: "operator", do: (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); fx.log.info("console.action.ping", { operatorId: fx.operator.id, note: input.note, }); return { ok: true as const, note: input.note, at: isoAt(state.now()) }; }, }); } function createStructuralPropose(state: ConsoleState) { return flow("console.structural.propose", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); const proposal = await emitStructuralDiff({ cwd: state.cwd, title: input.title, relativePath: input.relativePath, diff: createFileDiff(input.relativePath, input.contents), actorId: fx.operator.id, reason: input.reason, now: state.now, }); fx.log.info("console.structural.propose", { id: proposal.id, path: proposal.path, }); return { id: proposal.id, path: proposal.path, applied: false as const }; }, }); } function createFlowsIdentities(state: ConsoleState) { return flow("console.flows.identities", { plane: "operator", do: (_input, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); return { identities: state.identities.map((i) => ({ id: i.id, email: i.email, name: i.name, status: i.status, scopes: [...i.scopes], })), }; }, }); } function createFlowsInvoke(state: ConsoleState) { return flow("console.flows.invoke", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); const manifest = state.manifest; const declared = manifest?.flows?.[input.flowId]; if (!declared) { return fail("NotFound", { flowId: input.flowId }); } const assumed = resolveInvokeAs( { ...(input.asUserId !== undefined ? { asUserId: input.asUserId } : {}), ...(input.asGate !== undefined ? { asGate: input.asGate } : {}), }, state.identities, manifest ?? null, ); if (!assumed.ok) { return fail("InvokeDenied", { reason: assumed.reason }); } const peakTier = peakTierOf(declared); if (peakTier === "external" && state.production) { if (input.confirmation !== "INVOKE" || (input.reason?.trim().length ?? 0) < 3) { return fail("ConfirmRequired", { phrase: "INVOKE" as const, reason: "irreversible production invoke requires typed confirmation", }); } } const invoke = state.invokeUserFlow; if (!invoke) { return fail("InvokeDenied", { reason: "host invoke not configured" }); } const trigger = triggerKindOf(declared); const host = await invoke({ flowId: input.flowId, body: input.body, ...(input.pathParams !== undefined ? { pathParams: input.pathParams } : {}), principal: assumed.principal, operatorId: fx.operator.id, ...(assumed.bypassGates ? { bypassGates: true } : {}), ...(input.reason !== undefined ? { reason: input.reason } : {}), ...(input.revealPii === true ? { revealPii: true } : {}), ...(assumed.rls ? { rls: assumed.rls } : {}), }); const reveal = input.revealPii === true; const piiFields = piiFieldNamesFromManifest(manifest); if (reveal) { fx.log.info("console.flows.invoke.reveal", { operatorId: fx.operator.id, flowId: input.flowId, }); } const response = reveal ? host.output : maskPiiValue(host.output, piiFields); const failure = host.failure === undefined ? undefined : { ...host.failure, ...(host.failure.data !== undefined ? { data: reveal ? host.failure.data : maskPiiValue(host.failure.data, piiFields), } : {}), }; fx.log.info("console.flows.invoke", { operatorId: fx.operator.id, flowId: input.flowId, asUserId: assumed.asUserId, asGate: assumed.asGate, scopes: [...assumed.principal.scopes], peakTier, reason: input.reason, status: host.status, failure: host.failure?.code, runId: host.runId, revealPii: reveal, }); return { ok: true as const, flowId: input.flowId, asUserId: assumed.asUserId, asGate: assumed.asGate, trigger, response, masked: !reveal, ...(host.status !== undefined ? { status: host.status } : {}), ...(failure !== undefined ? { failure } : {}), ...(host.runId !== undefined ? { runId: host.runId } : {}), ...(host.cache !== undefined ? { cache: host.cache } : {}), ...(host.durationMs !== undefined ? { durationMs: host.durationMs } : {}), peakTier, auditedAt: state.now(), rls: { gate: assumed.rls?.gate ?? null, userId: assumed.rls?.userId ?? "", applied: assumed.rls !== null, }, }; }, }); } function peakTierOf( flow: ManifestFlow, ): "none" | "reads" | "writes" | "emits" | "external" | "capabilities" { const e = flow.effects; if (!e) return "none"; if ((e.sends?.length ?? 0) > 0 || (e.asks?.length ?? 0) > 0) return "external"; if ((e.secrets?.length ?? 0) > 0) return "capabilities"; if ((e.emits?.length ?? 0) > 0) return "emits"; if ((e.writes?.length ?? 0) > 0) return "writes"; if ((e.reads?.length ?? 0) > 0) return "reads"; return "none"; } function triggerKindOf(flow: ManifestFlow): "http" | "signal" | "clock" | "internal" | "durable" { if (flow.durable) return "durable"; if (flow.trigger?.http) return "http"; if (flow.trigger?.signal) return "signal"; if (flow.trigger?.cron || flow.trigger?.every) return "clock"; return "internal"; } async function issueOperatorSession( state: ConsoleState, operatorId: string, ): Promise { const op = state.operators.operators.get(operatorId); if (op) op.lastSeenAt = state.now(); const issued = await issueSession( state.sessions, { secret: state.secret, now: state.now, accessTtlMs: state.accessTtlMs, }, { id: operatorId, plane: "operator", scopes: ["console:*"], }, ); await state.persistSessions(); return issued; } function sessionPayload(operatorId: string, email: string, name: string, issued: IssuedSession) { return { operatorId, email, name, accessToken: issued.accessToken, refreshToken: issued.refreshToken, accessExpiresAt: issued.accessExpiresAt, }; } /** * Require tenant when `manifest.tenancy` is declared (off by default). * * @param state - Console state * @param tenant - Optional tenant from the request */ function requireTenantIfDeclared( state: ConsoleState, tenant: string | undefined, ): ReturnType | null { if (!tenancyDeclared(state.manifest)) return null; if (tenant !== undefined && tenant.length > 0) return null; if (!state.production) return null; return fail("TenantRequired", { reason: "tenancy is declared — tenant selector is required (compliance boundary)", }); } function createStoreList(state: ConsoleState) { return flow("console.store.list", { plane: "operator", do: async (_input, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); return state.listStores(); }, }); } function consoleStoreRls( state: ConsoleState, input: { readonly asGate?: string; readonly asUserId?: string }, ): | { readonly ok: true; readonly rls: RlsIdentity | null } | { readonly ok: false; readonly reason: string } { if (input.asGate !== undefined && !isKnownConsoleSqlGate(state.manifest, input.asGate)) { return { ok: false, reason: `unknown gate: ${input.asGate}` }; } if (input.asUserId !== undefined) { const identity = state.identities.find((row) => row.id === input.asUserId); if (!identity || identity.status === "disabled") { return { ok: false, reason: `unknown identity: ${input.asUserId}` }; } } return { ok: true, rls: resolveRlsIdentity({ asGate: input.asGate, asUserId: input.asUserId, identities: state.identities, manifest: state.manifest, }), }; } function createStoreQuery(state: ConsoleState) { return flow("console.store.query", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); const tenantFail = requireTenantIfDeclared(state, input.tenant); if (tenantFail) return tenantFail; if (input.revealPii === true) { fx.log.info("console.store.query.reveal", { operatorId: fx.operator.id, ref: input.ref, child: input.child, tenant: input.tenant, }); } const assumed = consoleStoreRls(state, input); if (!assumed.ok) return fail("StoreNotFound", { ref: assumed.reason }); return state.queryStore({ ref: input.ref as ResourceRef, child: input.child, tenant: input.tenant, prefix: input.prefix, limit: input.limit, vector: input.vector, q: input.q, topK: input.topK, revealPii: input.revealPii === true, ...(input.asGate !== undefined ? { asGate: input.asGate } : {}), ...(input.asUserId !== undefined ? { asUserId: input.asUserId } : {}), ...(assumed.rls ? { rls: assumed.rls } : {}), }); }, }); } function createStoreReveal(state: ConsoleState) { return flow("console.store.reveal", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); const tenantFail = requireTenantIfDeclared(state, input.tenant); if (tenantFail) return tenantFail; const result = await state.queryStore({ ref: input.ref as ResourceRef, child: input.child, tenant: input.tenant, revealPii: true, limit: 500, }); const row = (result.rows ?? []).find((r) => String(r.id ?? r.Id) === input.id); if (!row) return fail("StoreNotFound", { ref: input.ref }); fx.log.info("console.store.reveal", { operatorId: fx.operator.id, ref: input.ref, child: input.child, id: input.id, column: input.column, tenant: input.tenant, }); return { ok: true as const, value: row[input.column], at: isoAt(state.now()), }; }, }); } function createStoreObject(state: ConsoleState) { return flow("console.store.object", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); const tenantFail = requireTenantIfDeclared(state, input.tenant); if (tenantFail) return tenantFail; try { const result = await state.getStoreFile({ ref: input.ref as ResourceRef, key: input.key, tenant: input.tenant, }); fx.log.info("console.store.object", { operatorId: fx.operator.id, ref: input.ref, key: input.key, sizeBytes: result.sizeBytes, tenant: input.tenant, }); return result; } catch (err) { if (err instanceof StoreFileNotFoundError) { return fail("StoreNotFound", { ref: `${input.ref}:${input.key}` }); } return fail("StoreNotFound", { ref: `${input.ref}: ${err instanceof Error ? err.message : String(err)}`, }); } }, }); } function createStoreEdit(state: ConsoleState) { return flow("console.store.edit", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); const tenantFail = requireTenantIfDeclared(state, input.tenant); if (tenantFail) return tenantFail; const assumed = consoleStoreRls(state, input); if (!assumed.ok) return fail("StoreNotFound", { ref: assumed.reason }); const rlsFields = { ...(input.asGate !== undefined ? { asGate: input.asGate } : {}), ...(input.asUserId !== undefined ? { asUserId: input.asUserId } : {}), ...(assumed.rls ? { rls: assumed.rls } : {}), }; if (!input.commit) { // Return will-not-fire payload without applying — informational confirm. const preview = await state.editStore( { ref: input.ref as ResourceRef, child: input.child, tenant: input.tenant, id: input.id, key: input.key, patch: input.patch, ...rlsFields, }, { dryRun: true }, ); return { ok: true as const, dryRun: true, applied: false, willNotFire: preview.willNotFire, wouldHaveFired: [...preview.wouldHaveFired], at: isoAt(state.now()), ...(preview.rls ? { rls: preview.rls } : {}), }; } if (state.production) { if (input.confirmation !== "EDIT" || (input.reason?.trim().length ?? 0) < 3) { return fail("ConfirmRequired", { phrase: "EDIT" as const, reason: "direct edit is not a flow execution — typed confirmation required", }); } } const result = await state.editStore( { ref: input.ref as ResourceRef, child: input.child, tenant: input.tenant, id: input.id, key: input.key, patch: input.patch, ...rlsFields, }, { dryRun: false }, ); fx.log.info("console.store.edit", { operatorId: fx.operator.id, ref: input.ref, child: input.child, willNotFire: result.willNotFire, reason: input.reason, }); return { ok: true as const, dryRun: false, applied: result.applied, willNotFire: result.willNotFire, wouldHaveFired: [...result.wouldHaveFired], at: isoAt(state.now()), ...(result.rls ? { rls: result.rls } : {}), }; }, }); } function createStoreDelete(state: ConsoleState) { return flow("console.store.delete", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); const tenantFail = requireTenantIfDeclared(state, input.tenant); if (tenantFail) return tenantFail; if (state.production) { if (input.confirmation !== "DELETE" || (input.reason?.trim().length ?? 0) < 3) { return fail("ConfirmRequired", { phrase: "DELETE" as const, reason: "destructive store delete requires typed confirmation", }); } } const result = await state.deleteStore({ ref: input.ref as ResourceRef, child: input.child, tenant: input.tenant, ids: input.ids, keys: input.keys, }); fx.log.info("console.store.delete", { operatorId: fx.operator.id, ref: input.ref, deleted: result.deleted, reason: input.reason, }); return { ok: true as const, deleted: result.deleted, at: isoAt(state.now()), }; }, }); } function createStorePurgeCache(state: ConsoleState) { return flow("console.store.purgeCache", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); if (state.production) { if (input.confirmation !== "PURGE" || (input.reason?.trim().length ?? 0) < 3) { return fail("ConfirmRequired", { phrase: "PURGE" as const, reason: "cache purge requires typed confirmation", }); } } const result = await state.purgeStoreCache(input.resource as ResourceRef); fx.log.info("console.store.purgeCache", { operatorId: fx.operator.id, resource: input.resource, keys: result.keys, reason: input.reason, }); return { ok: true as const, keys: [...result.keys], at: isoAt(state.now()), }; }, }); } function createStoreSql(state: ConsoleState) { return flow("console.store.sql", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); const tenantFail = requireTenantIfDeclared(state, input.tenant); if (tenantFail) return tenantFail; try { if (input.revealPii === true) { fx.log.info("console.store.sql.reveal", { operatorId: fx.operator.id, ref: input.ref, tenant: input.tenant, }); } const assumed = consoleStoreRls(state, input); if (!assumed.ok) return fail("StoreNotFound", { ref: assumed.reason }); if (input.asGate !== undefined) { fx.log.info("console.store.sql.asGate", { operatorId: fx.operator.id, ref: input.ref, gate: input.asGate, tenant: input.tenant, }); } const result = await state.runStoreSql(input.ref as ResourceRef, input.sql, { allowWrite: input.allowWrite === true, revealPii: input.revealPii === true, tenant: input.tenant, ...(input.asGate !== undefined ? { asGate: input.asGate } : {}), ...(input.asUserId !== undefined ? { asUserId: input.asUserId } : {}), ...(assumed.rls ? { rls: assumed.rls } : {}), }); fx.log.info("console.store.sql", { operatorId: fx.operator.id, ref: input.ref, allowWrite: input.allowWrite === true, revealPii: input.revealPii === true, asGate: input.asGate ?? null, asUserId: input.asUserId ?? null, rowCount: result.rows.length, }); return result; } catch (err) { return fail("StoreNotFound", { ref: `${input.ref}: ${err instanceof Error ? err.message : String(err)}`, }); } }, }); } function failStoreSqlStats(err: unknown) { if (err instanceof StoreSqlStatsError) { if (err.code === PG_STAT_STATEMENTS_NOT_PRELOADED) { return fail("PgStatStatementsNotPreloaded", { reason: err.message }); } if (err.code === PG_STAT_STATEMENTS_NOT_CREATED) { return fail("PgStatStatementsNotCreated", { reason: err.message }); } return fail("PgStatStatementsUnsupported", { reason: err.message }); } return fail("PgStatStatementsUnsupported", { reason: engineErrorText(err), }); } function createStoreSqlStats(state: ConsoleState) { return flow("console.store.sql.stats", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); const tenantFail = requireTenantIfDeclared(state, input.tenant); if (tenantFail) return tenantFail; try { const result = await state.queryStoreSqlStats(input.ref as ResourceRef); fx.log.info("console.store.sql.stats", { operatorId: fx.operator.id, ref: input.ref, rowCount: result.rowCount, }); return result; } catch (err) { return failStoreSqlStats(err); } }, }); } function createStoreSqlLocks(state: ConsoleState) { return flow("console.store.sql.locks", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); const tenantFail = requireTenantIfDeclared(state, input.tenant); if (tenantFail) return tenantFail; if (input.revealPii === true) { fx.log.info("console.store.sql.stats.reveal", { operatorId: fx.operator.id, ref: input.ref, tenant: input.tenant, }); } try { const result = await state.queryStoreSqlLocks(input.ref as ResourceRef, { revealPii: input.revealPii === true, }); fx.log.info("console.store.sql.locks", { operatorId: fx.operator.id, ref: input.ref, revealPii: input.revealPii === true, rowCount: result.rows.length, }); return result; } catch (err) { return failStoreSqlStats(err); } }, }); } function createStoreSqlAdvise(state: ConsoleState) { return flow("console.store.sql.advise", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); const tenantFail = requireTenantIfDeclared(state, input.tenant); if (tenantFail) return tenantFail; try { const result = await state.adviseStoreSqlIndex(input.ref as ResourceRef, input.query); fx.log.info("console.store.sql.advise", { operatorId: fx.operator.id, ref: input.ref, suggestionCount: result.indexStatements.length, }); return result; } catch (err) { return failStoreSqlStats(err); } }, }); } function failStoreKvStats(err: unknown) { if (err instanceof StoreKvStatsError) { return fail("KvStatsUnsupported", { reason: err.message }); } return fail("KvStatsUnsupported", { reason: err instanceof Error ? err.message : String(err), }); } function createStoreKvStats(state: ConsoleState) { return flow("console.store.kv.stats", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); const tenantFail = requireTenantIfDeclared(state, input.tenant); if (tenantFail) return tenantFail; if (input.revealPii === true) { fx.log.info("console.store.kv.stats.reveal", { operatorId: fx.operator.id, ref: input.ref, tenant: input.tenant, }); } try { const result = await state.queryStoreKvStats(input.ref as ResourceRef, { revealPii: input.revealPii === true, }); fx.log.info("console.store.kv.stats", { operatorId: fx.operator.id, ref: input.ref, revealPii: input.revealPii === true, engine: result.engine, slowlogCount: result.slowlog.length, }); return result; } catch (err) { return failStoreKvStats(err); } }, }); } function createStorePreview(state: ConsoleState) { return flow("console.store.preview", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); const tenantFail = requireTenantIfDeclared(state, input.tenant); if (tenantFail) return tenantFail; try { const preview = await state.editStore( { ref: input.ref as ResourceRef, child: input.child, tenant: input.tenant, id: input.id, key: input.key, patch: input.patch, }, { dryRun: true }, ); fx.log.info("console.store.preview", { operatorId: fx.operator.id, ref: input.ref, willNotFire: preview.willNotFire, }); return { ok: true as const, dryRun: true as const, willNotFire: preview.willNotFire, wouldHaveFired: [...preview.wouldHaveFired], at: isoAt(state.now()), }; } catch (err) { if (err instanceof DryRunWriteIsolationError) { return fail("DryRunUnsafe", { ref: input.ref, reason: err.message, }); } return fail("DryRunUnsafe", { ref: input.ref, reason: err instanceof Error ? err.message : String(err), }); } }, }); } function createVaultList(state: ConsoleState) { return flow("console.vault.list", { plane: "operator", do: async (_input, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); return state.listVault(); }, }); } function createVaultCreate(state: ConsoleState) { return flow("console.vault.create", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); try { const result = await state.createVault({ name: input.name, value: input.value, kind: input.kind, ...(input.description !== undefined ? { description: input.description } : {}), ...(input.rotate !== undefined ? { rotate: input.rotate } : {}), }); fx.log.info("console.vault.create", { operatorId: fx.operator.id, name: result.name, kind: input.kind, fingerprint: result.fingerprint, }); return { ok: true as const, name: result.name, fingerprint: result.fingerprint, at: isoAt(state.now()), }; } catch (err) { const message = err instanceof Error ? err.message : String(err); if (message.includes("already declared")) { return fail("VaultExists", { name: input.name }); } return fail("VaultNotFound", { name: `${input.name}: ${message}` }); } }, }); } function createVaultSet(state: ConsoleState) { return flow("console.vault.set", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); if (!(await vaultNameKnown(state, input.name))) { return fail("VaultNotFound", { name: input.name }); } try { const result = await state.setVault({ name: input.name, value: input.value, }); // Never log the value — name + fingerprint only. fx.log.info("console.vault.set", { operatorId: fx.operator.id, name: result.name, fingerprint: result.fingerprint, reason: input.reason, }); return { ok: true as const, name: result.name, fingerprint: result.fingerprint, at: isoAt(state.now()), }; } catch (err) { return fail("VaultNotFound", { name: input.name, reason: err instanceof Error ? err.message : String(err), }); } }, }); } function createVaultRotate(state: ConsoleState) { return flow("console.vault.rotate", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); if (!(await vaultNameKnown(state, input.name))) { return fail("VaultNotFound", { name: input.name }); } try { const result = await state.rotateVault({ name: input.name, value: input.value, }); fx.log.info("console.vault.rotate", { operatorId: fx.operator.id, name: result.name, fingerprint: result.fingerprint, reason: input.reason, }); return { ok: true as const, name: result.name, fingerprint: result.fingerprint, at: isoAt(state.now()), }; } catch (err) { return fail("VaultNotFound", { name: input.name, reason: err instanceof Error ? err.message : String(err), }); } }, }); } /** * Whether a vault contract name is known to Manifest or the live runtime. * * @param state - Console state * @param name - Contract name */ function createVaultRotateMaster(state: ConsoleState) { return flow("console.vault.rotateMaster", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); if (input.confirmation !== "ROTATE_MASTER" || !input.reason || input.reason.length < 3) { return fail("ConfirmRequired", { phrase: "ROTATE_MASTER" as const, reason: "Type ROTATE_MASTER and provide a reason — both master keys stay live until remaining is 0", }); } try { const result = await state.rotateMaster(); fx.log.info("console.vault.rotateMaster", { operatorId: fx.operator.id, kekVersion: result.kekVersion, remaining: result.remaining, reason: input.reason, }); return { ok: true as const, kekVersion: result.kekVersion, remaining: result.remaining, masterKey: result.masterKey, at: isoAt(state.now()), }; } catch (err) { return mapVaultOperatorError(err); } }, }); } function createVaultAuditVerify(state: ConsoleState) { return flow("console.vault.auditVerify", { plane: "operator", do: async (_input, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); try { const result = await state.verifyVaultAudit(); fx.log.info("console.vault.audit.verify", { operatorId: fx.operator.id, ok: result.ok, brokenAt: result.brokenAt, }); return result; } catch (err) { return mapVaultOperatorError(err); } }, }); } /** * Map Console vault errors onto typed flow failures. * * @param err - Caught error */ function mapVaultOperatorError(err: unknown) { const code = err && typeof err === "object" && "code" in err ? (err as { code: string }).code : undefined; const reason = err instanceof Error ? err.message : String(err); if (code === "VaultSealed") return fail("VaultSealed", { reason }); if (code === "VaultRotateBusy") return fail("VaultRotateBusy", { reason }); if (code === "VaultUnsupported") return fail("VaultUnsupported", { reason }); return fail("VaultUnsupported", { reason }); } async function vaultNameKnown(state: ConsoleState, name: string): Promise { if (state.manifest?.vault?.[name]) return true; if (state.vaultRuntime?.contracts.has(name)) return true; const listed = await state.listVault(); return listed.secrets.some((s) => s.name === name); } function createAiList(state: ConsoleState) { return flow("console.ai.list", { plane: "operator", do: async (_input, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); const projection = await state.listAi(); return { prompts: projection.prompts.map((p) => ({ name: p.name, ...(p.version !== undefined ? { version: p.version } : {}), ...(p.model !== undefined ? { model: p.model } : {}), ...(p.evals !== undefined ? { evals: p.evals } : {}), budgetMaxCostPerCall: p.budgetMaxCostPerCall, manifestDiffPath: p.manifestDiffPath, })), agents: projection.agents.map((a) => ({ name: a.name, tools: [...a.tools], ...(a.maxSteps !== undefined ? { maxSteps: a.maxSteps } : {}), ...(a.model !== undefined ? { model: a.model } : {}), budgetMaxCostPerRun: a.budgetMaxCostPerRun, })), versions: projection.versions.map((v) => ({ ...v, outcomeCounts: { ...v.outcomeCounts }, })), allowPii: projection.allowPii.map((r) => ({ ...r, asks: [...r.asks], })), fallbackChains: projection.fallbackChains.map((c) => ({ prompt: c.prompt, ...(c.version !== undefined ? { version: c.version } : {}), attempts: c.attempts.map((a) => ({ ...a })), actualCost: c.actualCost, primaryOnlyCost: c.primaryOnlyCost, costConsequence: c.costConsequence, at: c.at, })), agentRuns: projection.agentRuns.map((r) => ({ ...r, trail: r.trail.map((t) => ({ ...t, effects: t.effects.map((e) => ({ ...e })), denial: t.denial ? { ...t.denial } : null, })), denials: r.denials.map((d) => ({ ...d })), })), denials: projection.denials.map((d) => ({ ...d })), }; }, }); } function createGatesList(state: ConsoleState) { return flow("console.gates.list", { plane: "operator", do: async (_input, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); const projection = await state.listGates(); return { moduleActions: [...projection.moduleActions], flows: projection.flows.map((f) => ({ flowId: f.flowId, plane: f.plane, gates: [...f.gates], unguarded: f.unguarded, explicitPublic: f.explicitPublic, })), gates: projection.gates.map((g) => ({ name: g.name, kind: g.kind, scopes: [...g.scopes], roles: [...g.roles], ...(g.strategy !== undefined ? { strategy: g.strategy } : {}), ...(g.max !== undefined ? { max: g.max } : {}), ...(g.per !== undefined ? { per: g.per } : {}), ...(g.keyBy !== undefined ? { keyBy: g.keyBy } : {}), overridable: g.overridable, attachedTo: [...g.attachedTo], })), principals: projection.principals.map((p) => ({ kind: p.kind, id: p.id, name: p.name, plane: p.plane, scopes: [...p.scopes], ...(p.memberCount !== undefined ? { memberCount: p.memberCount } : {}), ...(p.email !== undefined ? { email: p.email } : {}), })), violations: projection.violations.map((v) => ({ kind: v.kind, operatorId: v.operatorId, name: v.name, email: v.email, applicationScopes: [...v.applicationScopes], })), audit: { unguardedFlows: [...projection.audit.unguardedFlows], orphanPermissions: [...projection.audit.orphanPermissions], emptyRoles: [...projection.audit.emptyRoles], unattachedGates: [...projection.audit.unattachedGates], }, widenings: projection.widenings.map((w) => ({ path: w.path, category: w.category, kind: w.kind, summary: w.summary, ...(w.before !== undefined ? { before: w.before } : {}), ...(w.after !== undefined ? { after: w.after } : {}), })), }; }, }); } function createDiffList(state: ConsoleState) { return flow("console.diff.list", { plane: "operator", do: async (_input, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); const projection = await state.listDiff(); return { hasBaseline: projection.hasBaseline, severity: projection.severity, blockedCount: projection.blockedCount, acknowledgedCount: projection.acknowledgedCount, changes: projection.changes.map((c) => ({ path: c.path, category: c.category, kind: c.kind, summary: c.summary, ...(c.before !== undefined ? { before: c.before } : {}), ...(c.after !== undefined ? { after: c.after } : {}), flowName: c.flowName, runCountLastWeek: c.runCountLastWeek, blastLine: c.blastLine, weeklyDeltaUsd: c.weeklyDeltaUsd, weeklyBillLine: c.weeklyBillLine, ciGate: c.ciGate, })), }; }, }); } function createPluginsList(state: ConsoleState) { return flow("console.plugin.list", { plane: "operator", do: async (_input, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); return state.listPlugins(); }, }); } function createGatesSimulate(state: ConsoleState) { return flow("console.gates.simulate", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); const result = await state.simulateGates(input); return { flowId: result.flowId, gates: [...result.gates], evaluations: result.evaluations.map((e) => ({ name: e.name, allowed: e.allowed, kind: e.kind, ...(e.remaining !== undefined ? { remaining: e.remaining } : {}), ...(e.retryAfterMs !== undefined ? { retryAfterMs: e.retryAfterMs } : {}), ...(e.reason !== undefined ? { reason: e.reason } : {}), })), deniedAt: result.deniedAt, denial: result.denial ? { code: result.denial.code, data: { ...result.denial.data }, status: result.denial.status, } : null, allowed: result.allowed, }; }, }); } function createGatesPowers(state: ConsoleState) { return flow("console.gates.powers", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); const result = await state.powersForPrincipal(input); return { scopes: [...result.scopes], allowedFlowIds: [...result.allowedFlowIds], deniedFlowIds: [...result.deniedFlowIds], }; }, }); } /** * Actor grant ceiling — role scopes plus session `console:*`. * * @param state - Console state * @param operatorId - Acting operator */ function actorScopesOf(state: ConsoleState, operatorId: string): string[] { const roleIds = state.operators.roles.get(operatorId) ?? []; const fromRoles = [...scopesForRoles(state.roles, roleIds, "operator")]; // Console sessions mint `console:*` (see issueOperatorSession). return [...new Set([...fromRoles, "console:*"])]; } /** * Derive the issuer for a Console-minted key. * Operator-plane: the acting operator. User-plane: required `creatorUserId`. * * @param state - Console state * @param operatorId - Acting operator * @param input - Create payload */ export function resolveAccessKeyIssuer( state: ConsoleState, operatorId: string, input: { readonly plane: "user" | "operator"; readonly creatorUserId?: string }, ): | { readonly creatorId: string; readonly creatorScopes: readonly string[] } | { readonly error: string } { if (input.plane === "operator") { return { creatorId: operatorId, creatorScopes: actorScopesOf(state, operatorId) }; } const userId = input.creatorUserId; if (!userId) { return { error: "creatorUserId is required for user-plane keys" }; } const identity = state.identities.find((row) => row.id === userId); const roleIds = [...state.roleMembers.entries()] .filter(([, members]) => members.includes(userId)) .map(([id]) => id); if (!identity && roleIds.length === 0) { return { error: `unknown user: ${userId}` }; } return { creatorId: userId, creatorScopes: accessUserCeiling({ userId, identityScopes: identity?.scopes, roles: state.roles, roleMembers: state.roleMembers, }), }; } function createAccessList(state: ConsoleState) { return flow("console.access.list", { plane: "operator", do: async (_input, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); return state.listAccess(actorScopesOf(state, fx.operator.id)); }, }); } function createAccessEffective(state: ConsoleState) { return flow("console.access.effective", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); const result = await state.accessEffective(input); if (!result) { return fail("NotFound", { flowId: `${input.kind}:${input.id}` }); } return { kind: result.kind, id: result.id, plane: result.plane, scopes: result.scopes.map((s) => ({ scope: s.scope, sources: s.sources.map((src) => ({ ...src })), })), }; }, }); } function createAccessKeyBlast(state: ConsoleState) { return flow("console.access.keyBlast", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); if (!state.apiKeys.keys.has(input.keyId)) { return fail("AccessKeyNotFound", { keyId: input.keyId }); } return state.accessKeyBlast(input.keyId); }, }); } function createAccessCreateKey(state: ConsoleState) { return flow("console.access.createKey", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); try { const issued = resolveAccessKeyIssuer(state, fx.operator.id, input); if ("error" in issued) { return fail("AccessGrantDenied", { reason: issued.error }); } const created = await state.accessCreateKey({ plane: input.plane, name: input.name, scopes: input.scopes, creatorId: issued.creatorId, creatorScopes: issued.creatorScopes, expiresAt: input.expiresAt, rateLimit: input.rateLimit, ipAllowlist: input.ipAllowlist, }); fx.log.info("console.access.createKey", { keyId: created.row.id, plane: created.row.plane, operatorId: fx.operator.id, }); return { key: { ...created.row }, secret: created.secret }; } catch (err) { return fail("AccessGrantDenied", { reason: err instanceof Error ? err.message : "grant denied", }); } }, }); } function createAccessRevokeKey(state: ConsoleState) { return flow("console.access.revokeKey", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); if (input.confirmation !== "REVOKE" || (input.reason?.trim().length ?? 0) < 3) { return fail("ConfirmRequired", { phrase: "REVOKE" as const, reason: "Type REVOKE and provide a reason — revocation is irreversible", }); } const blastRadius = await state.accessKeyBlast(input.keyId); const key = await state.accessRevokeKey(input.keyId); if (!key) { return fail("AccessKeyNotFound", { keyId: input.keyId }); } fx.log.info("console.access.revokeKey", { keyId: key.id, operatorId: fx.operator.id, reason: input.reason, callVolume: blastRadius.callVolume, }); return { key: { ...key }, blastRadius }; }, }); } function createAccessRotateKey(state: ConsoleState) { return flow("console.access.rotateKey", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); if (input.confirmation !== "ROTATE" || (input.reason?.trim().length ?? 0) < 3) { return fail("ConfirmRequired", { phrase: "ROTATE" as const, reason: "Type ROTATE and provide a reason — the old secret dies immediately", }); } const blastRadius = await state.accessKeyBlast(input.keyId); const rotated = await state.accessRotateKey(input.keyId); if (!rotated) { return fail("AccessKeyNotFound", { keyId: input.keyId }); } fx.log.info("console.access.rotateKey", { keyId: rotated.row.id, operatorId: fx.operator.id, reason: input.reason, }); return { key: { ...rotated.row }, secret: rotated.secret, blastRadius, }; }, }); } function createAccessUpdateKey(state: ConsoleState) { return flow("console.access.updateKey", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); try { const key = await state.accessUpdateKey(input); if (!key) { return fail("AccessKeyNotFound", { keyId: input.keyId }); } fx.log.info("console.access.updateKey", { keyId: key.id, operatorId: fx.operator.id, }); return { key: { ...key } }; } catch (err) { return fail("AccessGrantDenied", { reason: err instanceof Error ? err.message : "grant denied", }); } }, }); } function createAccessSetRoleGrants(state: ConsoleState) { return flow("console.access.setRoleGrants", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); try { await state.accessSetRoleGrants({ roleId: input.roleId, scopes: input.scopes, actorScopes: actorScopesOf(state, fx.operator.id), }); fx.log.info("console.access.setRoleGrants", { roleId: input.roleId, operatorId: fx.operator.id, scopes: input.scopes, }); return { roleId: input.roleId, scopes: [...input.scopes] }; } catch (err) { return fail("AccessGrantDenied", { reason: err instanceof Error ? err.message : "grant denied", }); } }, }); } function createClockList(state: ConsoleState) { return flow("console.clock.list", { plane: "operator", do: async (_input, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); return state.listClocks(); }, }); } function createInstancesList(state: ConsoleState) { return flow("console.instances.list", { plane: "operator", do: async (_input, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); return state.listInstances(); }, }); } function createClockRunNow(state: ConsoleState) { return flow("console.clock.runNow", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); const list = await state.listClocks(); const cron = list.crons.find((c) => c.name === input.name); if (!cron) { return fail("ClockNotFound", { kind: "cron" as const, id: input.name }); } if (state.production && cron.external) { if (input.confirmation !== "RUN" || !input.reason || input.reason.length < 3) { return fail("ConfirmRequired", { phrase: "RUN" as const, reason: "Type RUN and provide a reason — this cron has an external effect", }); } } try { const result = await state.runCronNow(input.name); fx.log.info("console.clock.runNow", { operatorId: fx.operator.id, name: input.name, ran: result.ran, reason: input.reason, }); return { ok: true as const, name: input.name, ran: result.ran, at: isoAt(state.now()), }; } catch (err) { if (err instanceof ClockResourceNotFoundError) { return fail("ClockNotFound", { kind: err.kind, id: err.id }); } throw err; } }, }); } function createClockPause(state: ConsoleState) { return flow("console.clock.pause", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); try { const result = await state.pauseCron(input.name); fx.log.info("console.clock.pause", { operatorId: fx.operator.id, name: result.name, }); return { ok: true as const, name: result.name, status: result.status, at: isoAt(state.now()), }; } catch (err) { if (err instanceof ClockResourceNotFoundError) { return fail("ClockNotFound", { kind: err.kind, id: err.id }); } throw err; } }, }); } function createClockEditSchedule(state: ConsoleState) { return flow("console.clock.editSchedule", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); try { const result = await state.editSchedule({ name: input.name, cron: input.cron, every: input.every, }); fx.log.info("console.clock.editSchedule", { operatorId: fx.operator.id, name: result.name, }); return { ok: true as const, name: result.name, effectiveCron: result.effectiveCron, effectiveEvery: result.effectiveEvery, at: isoAt(state.now()), }; } catch (err) { if (err instanceof ScheduleNotOverridableError) { return fail("ScheduleNotOverridable", { name: err.cronName }); } if (err instanceof ClockResourceNotFoundError) { return fail("ClockNotFound", { kind: err.kind, id: err.id }); } throw err; } }, }); } function createClockWakeEarly(state: ConsoleState) { return flow("console.clock.wakeEarly", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); try { const result = await state.wakeEarly(input.runId); fx.log.info("console.clock.wakeEarly", { operatorId: fx.operator.id, runId: result.runId, resumed: result.resumed, }); return { ok: true as const, runId: result.runId, wakeAt: result.wakeAt, resumed: result.resumed, at: isoAt(state.now()), }; } catch (err) { if (err instanceof ClockResourceNotFoundError) { return fail("ClockNotFound", { kind: err.kind, id: err.id }); } throw err; } }, }); } function createChannelsList(state: ConsoleState) { return flow("console.channel.list", { plane: "operator", do: async (_input, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); return state.listChannels(); }, }); } function createChannelPreview(state: ConsoleState) { return flow("console.channel.preview", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); if ( state.manifest?.channels && !(input.template in state.manifest.channels) && !state.channelRuntime?.templates.has(input.template) ) { return fail("ChannelNotFound", { template: input.template }); } return state.previewChannel(input); }, }); } function createChannelVerifyAuth(state: ConsoleState) { return flow("console.channel.verifyAuth", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); return state.verifyChannelAuth(input.from); }, }); } function createChannelReveal(state: ConsoleState) { return flow("console.channel.reveal", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); const revealed = await state.revealChannel(input.id); if (!revealed) { return fail("ChannelNotFound", { template: input.id }); } fx.log.info("console.channel.reveal", { operatorId: fx.operator.id, id: revealed.id, }); return { ok: true as const, id: revealed.id, to: revealed.to, at: isoAt(state.now()), }; }, }); } function createChannelSendTest(state: ConsoleState) { return flow("console.channel.sendTest", { plane: "operator", do: async (input: z.infer, fx) => { if (!fx.operator.id) return fail("AuthFailed", {}); if (state.production) { if (input.confirmation !== "SEND" || (input.reason?.trim().length ?? 0) < 3) { return fail("ConfirmRequired", { phrase: "SEND" as const, reason: "send test is a real external send — typed confirmation required", }); } } if (!state.channelRuntime) { return fail("ChannelNotFound", { template: input.template }); } if ( !state.channelRuntime.templates.has(input.template) && !(state.manifest?.channels && input.template in state.manifest.channels) ) { return fail("ChannelNotFound", { template: input.template }); } try { const result = await state.sendChannelTest({ template: input.template, to: input.to, locale: input.locale, data: input.data, }); fx.log.info("console.channel.sendTest", { operatorId: fx.operator.id, template: input.template, messageId: result.messageId, ok: result.ok, reason: input.reason, }); return { ...result, at: isoAt(state.now()), }; } catch (err) { return fail("ChannelNotFound", { template: `${input.template}: ${err instanceof Error ? err.message : String(err)}`, }); } }, }); }