Skip to content

Commit 8d33928

Browse files
committed
feat(audit): tamper-evident hash-chained audit trail (#1116)
Synced from sferarc/pgbeam@bcae254
1 parent 4268c38 commit 8d33928

7 files changed

Lines changed: 182 additions & 1 deletion

File tree

src/generated/describe-map.gen.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,9 @@ export const describeByOperationId: Record<string, DescribeEndpoint> = {
4141
"listApprovalRequests": {"operationId":"listApprovalRequests","method":"GET","path":"/v1/projects/{project_id}/approvals","summary":"List approval requests","description":"Lists approval requests for the project, newest first, optionally filtered by status.","parameters":[{"name":"project_id","in":"path","required":true,"type":"string","description":"Unique project identifier (prefixed, e.g. prj_xxx)."},{"name":"status","in":"query","required":false,"type":"\"pending\" | \"approved\" | \"rejected\" | \"expired\" | \"executed\" | \"failed\"","description":"Filter to a single status."},{"name":"page_size","in":"query","required":false,"type":"number","description":"Maximum number of items to return (1-100, default 20)."},{"name":"page_token","in":"query","required":false,"type":"string","description":"Opaque token for cursor-based pagination."}],"requestBodyType":"","requestBodyRequired":false,"responseType":"{ approvals: ({ credential_id?: string; decided_at?: string; decided_by?: string; expires_at: string; id: string; normalized_sql?: string; policy_profile_id: string; project_id: string; reason?: string; region?: string; requested_at: string; session_id?: string; sql: string; statement_kind?: string; status: \"pending\" | \"approved\" | \"rejected\" | \"expired\" | \"executed\" | \"failed\" })[]; next_page_token?: string }","responseStatus":"200"},
4242
"approveApprovalRequest": {"operationId":"approveApprovalRequest","method":"POST","path":"/v1/projects/{project_id}/approvals/{approval_id}/approve","summary":"Approve a held statement","description":"Approves a pending approval request, releasing the held statement.","parameters":[{"name":"project_id","in":"path","required":true,"type":"string","description":"Unique project identifier (prefixed, e.g. prj_xxx)."},{"name":"approval_id","in":"path","required":true,"type":"string","description":"Unique approval request identifier (prefixed, e.g. apr_xxx)."}],"requestBodyType":"{ reason?: string }","requestBodyRequired":false,"responseType":"{ credential_id?: string; decided_at?: string; decided_by?: string; expires_at: string; id: string; normalized_sql?: string; policy_profile_id: string; project_id: string; reason?: string; region?: string; requested_at: string; session_id?: string; sql: string; statement_kind?: string; status: \"pending\" | \"approved\" | \"rejected\" | \"expired\" | \"executed\" | \"failed\" }","responseStatus":"200"},
4343
"rejectApprovalRequest": {"operationId":"rejectApprovalRequest","method":"POST","path":"/v1/projects/{project_id}/approvals/{approval_id}/reject","summary":"Reject a held statement","description":"Rejects a pending approval request, denying the held statement.","parameters":[{"name":"project_id","in":"path","required":true,"type":"string","description":"Unique project identifier (prefixed, e.g. prj_xxx)."},{"name":"approval_id","in":"path","required":true,"type":"string","description":"Unique approval request identifier (prefixed, e.g. apr_xxx)."}],"requestBodyType":"{ reason?: string }","requestBodyRequired":false,"responseType":"{ credential_id?: string; decided_at?: string; decided_by?: string; expires_at: string; id: string; normalized_sql?: string; policy_profile_id: string; project_id: string; reason?: string; region?: string; requested_at: string; session_id?: string; sql: string; statement_kind?: string; status: \"pending\" | \"approved\" | \"rejected\" | \"expired\" | \"executed\" | \"failed\" }","responseStatus":"200"},
44-
"listAuditLogs": {"operationId":"listAuditLogs","method":"GET","path":"/v1/projects/{project_id}/audit-logs","summary":"List agent audit logs","description":"Returns agent statement audit entries for the project, newest first, with optional credential, event, decision, source and date-range filters.","parameters":[{"name":"project_id","in":"path","required":true,"type":"string","description":"Unique project identifier (prefixed, e.g. prj_xxx)."},{"name":"credential_id","in":"query","required":false,"type":"string","description":"Filter to a single agent credential."},{"name":"event","in":"query","required":false,"type":"string","description":"Filter to a single event type (e.g. blocked, masked, query)."},{"name":"decision","in":"query","required":false,"type":"\"allow\" | \"block\" | \"mask\" | \"truncate\"","description":"Coarse outcome filter that groups events. `allow` = query; `block` = blocked, budget_exhausted, auth_failed, credential_expired; `mask` = masked; `truncate` = truncated."},{"name":"source","in":"query","required":false,"type":"\"wire\" | \"mcp\" | \"control\"","description":"Filter by statement origin (wire, mcp, or control)."},{"name":"start","in":"query","required":false,"type":"string","description":"Return entries at or after this timestamp (inclusive lower bound)."},{"name":"end","in":"query","required":false,"type":"string","description":"Return entries strictly older than this timestamp (cursor / upper bound)."},{"name":"before","in":"query","required":false,"type":"string","description":"Return entries strictly older than this timestamp (keyset pagination cursor)."},{"name":"page_size","in":"query","required":false,"type":"number","description":"Maximum number of items to return (1-100, default 20)."}],"requestBodyType":"","requestBodyRequired":false,"responseType":"{ entries: ({ bytes_out?: number; cache_status?: string; client_ip?: string; credential_id?: string; decision_rule?: string; event: string; id: string; latency_ms?: number; normalized_sql?: string; project_id: string; query_hash?: string; reason?: string; region?: string; rows_returned?: number; session_id?: string; source?: string; sql?: string; statement_kind?: string; ts: string })[]; next_page_token?: string }","responseStatus":"200"},
44+
"listAuditLogs": {"operationId":"listAuditLogs","method":"GET","path":"/v1/projects/{project_id}/audit-logs","summary":"List agent audit logs","description":"Returns agent statement audit entries for the project, newest first, with optional credential, event, decision, source and date-range filters.","parameters":[{"name":"project_id","in":"path","required":true,"type":"string","description":"Unique project identifier (prefixed, e.g. prj_xxx)."},{"name":"credential_id","in":"query","required":false,"type":"string","description":"Filter to a single agent credential."},{"name":"event","in":"query","required":false,"type":"string","description":"Filter to a single event type (e.g. blocked, masked, query)."},{"name":"decision","in":"query","required":false,"type":"\"allow\" | \"block\" | \"mask\" | \"truncate\"","description":"Coarse outcome filter that groups events. `allow` = query; `block` = blocked, budget_exhausted, auth_failed, credential_expired; `mask` = masked; `truncate` = truncated."},{"name":"source","in":"query","required":false,"type":"\"wire\" | \"mcp\" | \"control\"","description":"Filter by statement origin (wire, mcp, or control)."},{"name":"start","in":"query","required":false,"type":"string","description":"Return entries at or after this timestamp (inclusive lower bound)."},{"name":"end","in":"query","required":false,"type":"string","description":"Return entries strictly older than this timestamp (cursor / upper bound)."},{"name":"before","in":"query","required":false,"type":"string","description":"Return entries strictly older than this timestamp (keyset pagination cursor)."},{"name":"page_size","in":"query","required":false,"type":"number","description":"Maximum number of items to return (1-100, default 20)."}],"requestBodyType":"","requestBodyRequired":false,"responseType":"{ entries: ({ bytes_out?: number; cache_status?: string; client_ip?: string; credential_id?: string; decision_rule?: string; entry_hash?: string; event: string; id: string; latency_ms?: number; normalized_sql?: string; prev_hash?: string; project_id: string; query_hash?: string; reason?: string; region?: string; rows_returned?: number; seq?: number; session_id?: string; source?: string; sql?: string; statement_kind?: string; ts: string })[]; next_page_token?: string }","responseStatus":"200"},
4545
"exportAuditLogs": {"operationId":"exportAuditLogs","method":"GET","path":"/v1/projects/{project_id}/audit-logs/export","summary":"Export agent audit logs as CSV","description":"Streams the project's agent audit entries as a CSV file, newest first, honoring the same credential, event, decision, source and date-range filters as the list endpoint. The full filtered set is streamed (no pagination); the result is suitable for spreadsheets, SIEM ingestion, and compliance archives.","parameters":[{"name":"project_id","in":"path","required":true,"type":"string","description":"Unique project identifier (prefixed, e.g. prj_xxx)."},{"name":"credential_id","in":"query","required":false,"type":"string","description":"Filter to a single agent credential."},{"name":"event","in":"query","required":false,"type":"string","description":"Filter to a single event type (e.g. blocked, masked, query)."},{"name":"decision","in":"query","required":false,"type":"\"allow\" | \"block\" | \"mask\" | \"truncate\"","description":"Coarse outcome filter that groups events. `allow` = query; `block` = blocked, budget_exhausted, auth_failed, credential_expired; `mask` = masked; `truncate` = truncated."},{"name":"source","in":"query","required":false,"type":"\"wire\" | \"mcp\" | \"control\"","description":"Filter by statement origin (wire, mcp, or control)."},{"name":"start","in":"query","required":false,"type":"string","description":"Return entries at or after this timestamp (inclusive lower bound)."},{"name":"end","in":"query","required":false,"type":"string","description":"Return entries strictly older than this timestamp (cursor / upper bound)."}],"requestBodyType":"","requestBodyRequired":false,"responseType":"","responseStatus":"200"},
46+
"verifyAuditChain": {"operationId":"verifyAuditChain","method":"GET","path":"/v1/projects/{project_id}/audit-logs/verify","summary":"Verify the tamper-evident audit chain","description":"Recomputes the project's audit hash chain over an optional time range and reports whether it is intact. Each audit entry is linked to its predecessor with a SHA-256 hash, so editing or deleting any row breaks the chain. On a break, the response reports the first sequence number where a tampered or deleted entry was detected. Requires the same audit:read permission as the list and export endpoints.","parameters":[{"name":"project_id","in":"path","required":true,"type":"string","description":"Unique project identifier (prefixed, e.g. prj_xxx)."},{"name":"start","in":"query","required":false,"type":"string","description":"Return entries at or after this timestamp (inclusive lower bound)."},{"name":"end","in":"query","required":false,"type":"string","description":"Return entries strictly older than this timestamp (cursor / upper bound)."}],"requestBodyType":"","requestBodyRequired":false,"responseType":"{ chain_end_seq?: number; chain_start_seq?: number; failure_reason?: string; first_broken_seq?: number; ok: boolean; unchained_count: number; verified_at: string; verified_count: number }","responseStatus":"200"},
4647
"listPlans": {"operationId":"listPlans","method":"GET","path":"/v1/plans","summary":"List available plans","description":"Returns all available plan tiers with their limits and pricing.","parameters":[],"requestBodyType":"","requestBodyRequired":false,"responseType":"{ plans: ({ annual_price?: number; description?: string; label: string; limits: { audit_retention_days: number; bytes_per_month: number; included_seats: number; max_agent_credentials: number; max_connections: number; max_databases: number; max_projects: number; max_query_shapes: number; queries_per_day: number; queries_per_second: number; sandbox_idle_seconds: number; sandbox_max_branches: number; sandbox_max_upstream_bytes: number; sandbox_ttl_seconds: number }; monthly_price: number; name: string; overage_text?: string; trial_days?: number })[] }","responseStatus":"200"},
4748
"getOrganizationPlan": {"operationId":"getOrganizationPlan","method":"GET","path":"/v1/organizations/{org_id}/plan","summary":"Get organization plan","description":"Returns the current plan and limits for the organization.","parameters":[{"name":"org_id","in":"path","required":true,"type":"string","description":"Unique organization identifier."}],"requestBodyType":"","requestBodyRequired":false,"responseType":"{ billing_provider?: \"stripe\" | \"vercel\" | \"aws\" | \"manual\"; created_at?: string; current_period_end?: string; custom_pricing?: boolean; enabled?: boolean; limits: { audit_retention_days: number; bytes_per_month: number; included_seats: number; max_agent_credentials: number; max_connections: number; max_databases: number; max_projects: number; max_query_shapes: number; queries_per_day: number; queries_per_second: number; sandbox_idle_seconds: number; sandbox_max_branches: number; sandbox_max_upstream_bytes: number; sandbox_ttl_seconds: number }; org_id: string; plan: \"starter\" | \"pro\" | \"scale\" | \"enterprise\"; spend_capped?: boolean; spend_capped_at?: string; spend_limit?: number; subscription_status?: \"none\" | \"active\" | \"trialing\" | \"past_due\" | \"canceled\" | \"unpaid\" | \"incomplete\" | \"incomplete_expired\" | \"paused\"; updated_at?: string }","responseStatus":"200"},
4849
"getVercelInstallation": {"operationId":"getVercelInstallation","method":"GET","path":"/v1/organizations/{org_id}/vercel-installation","summary":"Get Vercel Marketplace installation status","description":"Returns the Vercel Marketplace installation for the organization,\nincluding its provisioned resources and their current-period usage.\nReturns 404 when the organization was not provisioned through the\nVercel Marketplace. Powers the dashboard's Vercel integration page.\n","parameters":[{"name":"org_id","in":"path","required":true,"type":"string","description":"Unique organization identifier."}],"requestBodyType":"","requestBodyRequired":false,"responseType":"{ created_at?: string; installation_id: string; plan: string; resources: ({ billing_plan_id: string; name: string; period_bytes: number; period_queries: number; project_id: string; resource_id: string; status: \"ready\" | \"suspended\" | \"deleted\" })[]; status: string; vercel_account_id: string }","responseStatus":"200"},

src/generated/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export type { AnomalyAlert, AnomalyAlertSeverityEnumKey, AnomalyAlertStatusEnumK
55
export type { ApprovalDecisionRequest } from "./types/ApprovalDecisionRequest";
66
export type { ApprovalRequest, ApprovalRequestStatusEnumKey } from "./types/ApprovalRequest";
77
export type { ApproveApprovalRequestData, ApproveApprovalRequestPathApprovalId, ApproveApprovalRequestPathProjectId, ApproveApprovalRequestRequestConfig, ApproveApprovalRequestResponse, ApproveApprovalRequestResponses, ApproveApprovalRequestStatus200, ApproveApprovalRequestStatus400, ApproveApprovalRequestStatus401, ApproveApprovalRequestStatus403, ApproveApprovalRequestStatus404, ApproveApprovalRequestStatus409 } from "./types/ApproveApprovalRequest";
8+
export type { AuditChainVerification } from "./types/AuditChainVerification";
89
export type { AuditDecision, AuditDecisionKey } from "./types/AuditDecision";
910
export type { AuditLogEntry } from "./types/AuditLogEntry";
1011
export type { AuditSource, AuditSourceKey } from "./types/AuditSource";
@@ -176,6 +177,7 @@ export type { UpdateWebhookEndpointData, UpdateWebhookEndpointPathProjectId, Upd
176177
export type { UsageResponse } from "./types/UsageResponse";
177178
export type { VercelInstallationStatus } from "./types/VercelInstallationStatus";
178179
export type { VercelResourceStatus, VercelResourceStatusStatusEnumKey } from "./types/VercelResourceStatus";
180+
export type { VerifyAuditChainPathProjectId, VerifyAuditChainQueryEnd, VerifyAuditChainQueryStart, VerifyAuditChainRequestConfig, VerifyAuditChainResponse, VerifyAuditChainResponses, VerifyAuditChainStatus200, VerifyAuditChainStatus400, VerifyAuditChainStatus401, VerifyAuditChainStatus403, VerifyAuditChainStatus404, VerifyAuditChainStatus429 } from "./types/VerifyAuditChain";
179181
export type { VerifyCustomDomainPathDomainId, VerifyCustomDomainPathProjectId, VerifyCustomDomainRequestConfig, VerifyCustomDomainResponses, VerifyCustomDomainStatus200, VerifyCustomDomainStatus400, VerifyCustomDomainStatus401, VerifyCustomDomainStatus403, VerifyCustomDomainStatus404, VerifyCustomDomainStatus429 } from "./types/VerifyCustomDomain";
180182
export type { VerifyCustomDomainResponse } from "./types/VerifyCustomDomainResponse";
181183
export type { WebhookEndpoint, WebhookEndpointFormatEnumKey } from "./types/WebhookEndpoint";

0 commit comments

Comments
 (0)