Proto commits in unkeyed/unkey

These commits are when the Protocol Buffers files have changed: (only the last 100 relevant commits are shown)

Commit:598d7fb
Author:Oz
Committer:ogzhanolguncu

feat(api): create deployment endpoint (#6617) * feat(api): create deployment endpoint * fix: generation * feat: add handler and tests * refactor: move audit logging to rpc and clean up callers * refactor: change ui permissions and remove old endpoints * fix: redeploy bug and add missing fork on redeploy * chore: tidy * refactor: prevent leaking internals * chore: refine comment * revert: restore old endpoint and mark them as deprecated instead * revert: rest of the removed

Commit:19c39d3
Author:Flo
Committer:Flo

feat(billing): Deploy spend-cap detection and budget alerts (ENG-2904) Set Resend Idempotency-Key on budget alert sends so a retried Restate step does not double-email after a transient failure that still reached Resend.

Commit:4a15e4b
Author:Flo
Committer:Flo

feat(billing): Deploy spend-cap detection and budget alerts (ENG-2904)

Commit:6a4c7c1
Author:Flo
Committer:Flo

feat(ctrl): rewire Deploy cancel through ctrl-api (ENG-2922)

Commit:5a80184
Author:Flo
Committer:Flo

feat(ctrl): Deploy spend-cap enforcement suspend/resume (ENG-2923) Suspend/resume via teardown, wake gate, dashboard meter parity, and deploy_spend_check integration test (requires DeployTeardownService).

Commit:b1ae472
Author:Flo
Committer:Flo

feat(ctrl): Deploy teardown service (ENG-2922)

Commit:86b6285
Author:Flo
Committer:Flo

refactor(ctrl)!: per-workspace push invocations for deploy billing Resolve close.go rebase conflict with eng-2865: keep fanout push/finalize flow and eng-2865 defer-on-close-failure behavior (no customer-scoped fallback).

Commit:0f131bc
Author:Flo
Committer:Flo

feat(ctrl): month-end invoice closing webhook for Deploy billing Stripe invoice.created webhook on ctrl-api plus backup cron to push final period usage and finalize renewal drafts. Bounded retries with Kill on exhaustion, per-workspace defer on close failures, skip when subscription id is missing. Midnight-UTC anchor at Deploy checkout; no migration needed.

Commit:264e35c
Author:Oz
Committer:ogzhanolguncu

feat(api): create deployment endpoint (#6617) * feat(api): create deployment endpoint * fix: generation * feat: add handler and tests * refactor: move audit logging to rpc and clean up callers * refactor: change ui permissions and remove old endpoints * fix: redeploy bug and add missing fork on redeploy * chore: tidy * refactor: prevent leaking internals * chore: refine comment * revert: restore old endpoint and mark them as deprecated instead * revert: rest of the removed

Commit:b0fbe85
Author:Oz
Committer:ogzhanolguncu

feat(api): create deployment endpoint (#6617) * feat(api): create deployment endpoint * fix: generation * feat: add handler and tests * refactor: move audit logging to rpc and clean up callers * refactor: change ui permissions and remove old endpoints * fix: redeploy bug and add missing fork on redeploy * chore: tidy * refactor: prevent leaking internals * chore: refine comment * revert: restore old endpoint and mark them as deprecated instead * revert: rest of the removed

Commit:36580f7
Author:James

Make slack dedupe and installed workspace wide so each project can have a channel. Make it easier to configure.

Commit:c917dee
Author:James

fix: slack approved

Commit:f7d88b8
Author:Flo
Committer:Flo

feat(ctrl): Deploy spend-cap enforcement suspend/resume (ENG-2923) Suspend/resume via teardown, wake gate, dashboard meter parity, and deploy_spend_check integration test (requires DeployTeardownService).

Commit:8840f3a
Author:Flo
Committer:Flo

feat(ctrl): rewire Deploy cancel through ctrl-api (ENG-2922)

Commit:a3ba757
Author:James

init: make slack notifications great

Commit:731790d
Author:Flo
Committer:Flo

feat(ctrl): Deploy teardown service (ENG-2922) Adds the DeployTeardownService virtual object: it snapshots a workspace's running deployments, clears apps.current_deployment_id, and schedules archive or standby with drain polling. SUSPEND records the running set so a later resume can restore it. Also removes svc/ctrl/integration/sync_test.go, which stopped compiling after the harness changes and is not re-added here.

Commit:51a392c
Author:Flo
Committer:Flo

feat(billing): Deploy spend-cap detection and budget alerts (ENG-2904)

Commit:366d4c5
Author:Oz
Committer:ogzhanolguncu

feat(api): create deployment endpoint (#6617) * feat(api): create deployment endpoint * fix: generation * feat: add handler and tests * refactor: move audit logging to rpc and clean up callers * refactor: change ui permissions and remove old endpoints * fix: redeploy bug and add missing fork on redeploy * chore: tidy * refactor: prevent leaking internals * chore: refine comment * revert: restore old endpoint and mark them as deprecated instead * revert: rest of the removed

Commit:246bcb7
Author:Flo
Committer:Flo

feat(ctrl): Deploy teardown service (ENG-2922) Adds the DeployTeardownService virtual object: it snapshots a workspace's running deployments, clears apps.current_deployment_id, and schedules archive or standby with drain polling. SUSPEND records the running set so a later resume can restore it. Also removes svc/ctrl/integration/sync_test.go, which stopped compiling after the harness changes and is not re-added here.

Commit:5c9204e
Author:Flo
Committer:Flo

feat(ctrl): Deploy spend-cap enforcement suspend/resume (ENG-2923) Suspend/resume via teardown, wake gate, dashboard meter parity, and deploy_spend_check integration test (requires DeployTeardownService).

Commit:6c89414
Author:Flo
Committer:Flo

feat(ctrl): rewire Deploy cancel through ctrl-api (ENG-2922)

Commit:430fc6e
Author:Flo
Committer:Flo

refactor(ctrl)!: per-workspace push invocations for deploy billing Not behavior-preserving. The hourly push and month-end close now fan out one Restate invocation per workspace instead of pushing inline, so each push retries and fails in isolation: one workspace's broken Stripe state no longer stalls the others or the tick. The close awaits its pushes and, when any fail, leaves those workspaces' invoices open and returns a TerminalError so the fresh-key backup cron genuinely re-pushes them rather than finalizing an under-billed total. The close also gates finalization on two durable sleeps: a 15-minute ingestion buffer after the period ends before the final ClickHouse read (late rows would otherwise be permanently unbilled once the invoice finalizes), and a 20-minute wait between the final meter push and finalization so Stripe has aggregated the events into the draft's metered lines. DEPLOY NOTE: this changes the journaled step sequence of RunDeployBillingPush and RunDeployBillingClose. Drain in-flight deploy-billing invocations before deploying, or old journals may fail replay.

Commit:bcaadb4
Author:Flo
Committer:Flo

feat(ctrl): month-end invoice closing webhook for Deploy billing Closes the last correctness gap in the Deploy money path: without this, the billed month-end total was whatever the last hourly push happened to deliver, losing up to an hour of usage at every period roll. New pkg/webhook: a small receiver framework for inbound provider webhooks (method/body policing, signature verification via pluggable verifiers, event-type routing, middleware for integration-specific concerns, and transport metrics so webhook integrations never fly blind): - unkey_webhook_events_total{provider,event,outcome} with outcomes handled / ignored / unhandled / error / verification_failed / bad_request, and unkey_webhook_handler_duration_seconds. Defined in the package itself, next to the code that emits them. - Handlers return nil (200), ErrIgnore (200, counted separately), or an error (500, provider retries) — retry semantics are explicit. - Verifiers live under pkg/webhook/verifiers/ (stripe today; the GitHub webhook can migrate later). Flow: - ctrl-api gains POST /webhooks/stripe (new StripeConfig). On invoice.created for a Deploy workspace renewal invoice it claims the draft (auto_advance off) and dispatches RunDeployBillingClose for the closed period via Restate ingress; the per-customer invoice storm at the roll dedupes onto one durable invocation through the idempotency key. Everything else is ignored and keeps Stripe's own finalization. - RunDeployBillingClose (new CronService handler, keyed by the CLOSED "YYYY-MM" period) pushes every billable workspace's final full-period usage, stamped one second before period end so the "last"-formula meters bill the complete month, then finalizes Deploy workspaces' draft renewal invoices (new internal/invoicecloser), fanned out in bounded batches with one journaled step per workspace. Refuses to close a period that has not ended; losing a finalize race counts as done. - A 01:05 UTC backup cron invokes the same handler with the same idempotency key: if the webhook ran it attaches to that invocation, otherwise drafts are still drafts (auto_advance was disabled) and the sweep closes them. Total ctrl outage degrades to Stripe's one-hour auto-finalization. Prerequisite correctness fix: subscription billing anchors now pin midnight UTC (hour/minute/second 0), not just day_of_month 1. Without it periods are not calendar months and the renewal invoice's meter window would swallow the next month's early month-to-date events, billing the new month's tiny running total instead of the closed month's final one. The hourly push and the close share one pipeline (pushUsage) with an explicit window end and meter-event timestamp; billingperiod gains End(). ENG-2865

Commit:e0b5647
Author:chronark

Merge remote-tracking branch 'origin/main' into worktree-delayed-soft-deletes # Conflicts: # dev/k8s/charts/restate-cronjobs/values.yaml # docs/engineering/docs.json # gen/proto/ctrl/v1/project.pb.go # gen/proto/hydra/v1/app.pb.go # gen/proto/hydra/v1/cron.pb.go # gen/proto/hydra/v1/cron_restate.pb.go # gen/proto/hydra/v1/environment.pb.go # gen/proto/hydra/v1/project.pb.go # pkg/db/BUILD.bazel # pkg/db/app_find_with_settings.sql_generated.go # pkg/db/app_list_by_project.sql_generated.go # pkg/db/github_repo_connection_list_deploy_context.sql_generated.go # pkg/db/project_find_by_workspace_slug.sql_generated.go # pkg/db/querier_generated.go # pkg/db/queries/app_list_by_project.sql # pkg/db/queries/project_find_by_workspace_slug.sql # svc/ctrl/api/run.go # svc/ctrl/proto/hydra/v1/app.proto # svc/ctrl/proto/hydra/v1/cron.proto # svc/ctrl/proto/hydra/v1/environment.proto # svc/ctrl/proto/hydra/v1/project.proto # svc/ctrl/services/app/delete_app.go # svc/ctrl/services/project/BUILD.bazel # svc/ctrl/services/project/delete_project.go # svc/ctrl/services/project/service.go # svc/ctrl/worker/app/delete_permanently_handler.go # svc/ctrl/worker/cron/BUILD.bazel # svc/ctrl/worker/cron/cron.go # svc/ctrl/worker/environment/delete_permanently_handler.go # svc/ctrl/worker/project/delete_handler.go # svc/ctrl/worker/run.go # web/apps/dashboard/components/navigation/sidebar-v2/sidebar-body.tsx # web/apps/dashboard/gen/proto/ctrl/v1/project_pb.ts # web/apps/dashboard/lib/flags/index.ts # web/apps/dashboard/lib/flags/resolve.ts # web/apps/dashboard/lib/navigation/leaves.ts # web/apps/dashboard/lib/trpc/routers/index.ts

Commit:405bb06
Author:ogzhanolguncu
Committer:ogzhanolguncu

refactor: move audit logging to rpc and clean up callers

Commit:793f7f1
Author:Flo
Committer:Flo

feat(ctrl): Deploy spend-cap enforcement suspend/resume (ENG-2923) Suspend/resume via teardown, wake gate, dashboard meter parity, and deploy_spend_check integration test (requires DeployTeardownService).

Commit:6aa0c1b
Author:Flo
Committer:Flo

feat(ctrl): rewire Deploy cancel through ctrl-api (ENG-2922)

Commit:264f13b
Author:Flo
Committer:Flo

feat(ctrl): Deploy teardown service (ENG-2922) Adds the DeployTeardownService virtual object: it snapshots a workspace's running deployments, clears apps.current_deployment_id, and schedules archive or standby with drain polling. SUSPEND records the running set so a later resume can restore it. Also removes svc/ctrl/integration/sync_test.go, which stopped compiling after the harness changes and is not re-added here.

Commit:19d0e5b
Author:Flo
Committer:Flo

feat(billing): Deploy spend-cap detection and budget alerts (ENG-2904) deploy-spend-check cron, workos client, deployspendcheck package, orchestrator integration test, and deployCredits tests. Drop deploy_spend_check integration test from this PR; it needs DeployTeardownService (ENG-2922+).

Commit:4837684
Author:Flo
Committer:Flo

refactor(ctrl)!: per-workspace push invocations for deploy billing Not behavior-preserving. The hourly push and month-end close now fan out one Restate invocation per workspace instead of pushing inline, so each push retries and fails in isolation: one workspace's broken Stripe state no longer stalls the others or the tick. The close awaits its pushes and, when any fail, leaves those workspaces' invoices open and returns a TerminalError so the fresh-key backup cron genuinely re-pushes them rather than finalizing an under-billed total. The close also gates finalization on two durable sleeps: a 15-minute ingestion buffer after the period ends before the final ClickHouse read (late rows would otherwise be permanently unbilled once the invoice finalizes), and a 20-minute wait between the final meter push and finalization so Stripe has aggregated the events into the draft's metered lines. DEPLOY NOTE: this changes the journaled step sequence of RunDeployBillingPush and RunDeployBillingClose. Drain in-flight deploy-billing invocations before deploying, or old journals may fail replay.

Commit:ea20455
Author:Flo
Committer:Flo

feat(ctrl): month-end invoice closing webhook for Deploy billing Closes the last correctness gap in the Deploy money path: without this, the billed month-end total was whatever the last hourly push happened to deliver, losing up to an hour of usage at every period roll. New pkg/webhook: a small receiver framework for inbound provider webhooks (method/body policing, signature verification via pluggable verifiers, event-type routing, middleware for integration-specific concerns, and transport metrics so webhook integrations never fly blind): - unkey_webhook_events_total{provider,event,outcome} with outcomes handled / ignored / unhandled / error / verification_failed / bad_request, and unkey_webhook_handler_duration_seconds. Defined in the package itself, next to the code that emits them. - Handlers return nil (200), ErrIgnore (200, counted separately), or an error (500, provider retries) — retry semantics are explicit. - Verifiers live under pkg/webhook/verifiers/ (stripe today; the GitHub webhook can migrate later). Flow: - ctrl-api gains POST /webhooks/stripe (new StripeConfig). On invoice.created for a Deploy workspace renewal invoice it claims the draft (auto_advance off) and dispatches RunDeployBillingClose for the closed period via Restate ingress; the per-customer invoice storm at the roll dedupes onto one durable invocation through the idempotency key. Everything else is ignored and keeps Stripe's own finalization. - RunDeployBillingClose (new CronService handler, keyed by the CLOSED "YYYY-MM" period) pushes every billable workspace's final full-period usage, stamped one second before period end so the "last"-formula meters bill the complete month, then finalizes Deploy workspaces' draft renewal invoices (new internal/invoicecloser), fanned out in bounded batches with one journaled step per workspace. Refuses to close a period that has not ended; losing a finalize race counts as done. - A 01:05 UTC backup cron invokes the same handler with the same idempotency key: if the webhook ran it attaches to that invocation, otherwise drafts are still drafts (auto_advance was disabled) and the sweep closes them. Total ctrl outage degrades to Stripe's one-hour auto-finalization. Prerequisite correctness fix: subscription billing anchors now pin midnight UTC (hour/minute/second 0), not just day_of_month 1. Without it periods are not calendar months and the renewal invoice's meter window would swallow the next month's early month-to-date events, billing the new month's tiny running total instead of the closed month's final one. The hourly push and the close share one pipeline (pushUsage) with an explicit window end and meter-event timestamp; billingperiod gains End(). ENG-2865

Commit:a92a44c
Author:Flo
Committer:Flo

feat(ctrl): Deploy spend-cap enforcement suspend/resume (ENG-2923)

Commit:9441965
Author:Flo
Committer:Flo

feat(ctrl): rewire Deploy cancel through ctrl-api (ENG-2922)

Commit:80ca44e
Author:Flo
Committer:Flo

feat(ctrl): Deploy teardown service (ENG-2922) Adds the DeployTeardownService virtual object: it snapshots a workspace's running deployments, clears apps.current_deployment_id, and schedules archive or standby with drain polling. SUSPEND records the running set so a later resume can restore it. Also removes svc/ctrl/integration/sync_test.go, which stopped compiling after the harness changes and is not re-added here.

Commit:a122957
Author:Flo
Committer:Flo

feat(billing): Deploy spend-cap detection and budget alerts (ENG-2904) deploy-spend-check cron prices each budgeted workspace's month-to-date Deploy usage locally from ClickHouse, computes net-of-credit overage against the configured budget, and emails the workspace at 50/75/100%. Enforcement (ENG-2923 SUSPEND) is gated on the ENG-2922 teardown primitive and follows. Plan: todo/eng-2904-2923-spend-cap-enforcement.md

Commit:f7d71a5
Author:Flo
Committer:Flo

refactor(ctrl)!: per-workspace push invocations for deploy billing Not behavior-preserving. The hourly push and month-end close now fan out one Restate invocation per workspace instead of pushing inline, so each push retries and fails in isolation: one workspace's broken Stripe state no longer stalls the others or the tick. The close awaits its pushes and, when any fail, leaves those workspaces' invoices open and returns a TerminalError so the fresh-key backup cron genuinely re-pushes them rather than finalizing an under-billed total. The close also gates finalization on two durable sleeps: a 15-minute ingestion buffer after the period ends before the final ClickHouse read (late rows would otherwise be permanently unbilled once the invoice finalizes), and a 20-minute wait between the final meter push and finalization so Stripe has aggregated the events into the draft's metered lines. DEPLOY NOTE: this changes the journaled step sequence of RunDeployBillingPush and RunDeployBillingClose. Drain in-flight deploy-billing invocations before deploying, or old journals may fail replay.

Commit:c96c91b
Author:James P
Committer:GitHub

feat: allow ratelimit configuration for keys (#6562) * feat: allow ratelimit configuration for keys * implement union with some refining * remove required

Commit:65142cf
Author:Flo
Committer:Flo

feat(ctrl): month-end invoice closing webhook for Deploy billing Closes the last correctness gap in the Deploy money path: without this, the billed month-end total was whatever the last hourly push happened to deliver, losing up to an hour of usage at every period roll. New pkg/webhook: a small receiver framework for inbound provider webhooks (method/body policing, signature verification via pluggable verifiers, event-type routing, middleware for integration-specific concerns, and transport metrics so webhook integrations never fly blind): - unkey_webhook_events_total{provider,event,outcome} with outcomes handled / ignored / unhandled / error / verification_failed / bad_request, and unkey_webhook_handler_duration_seconds. Defined in the package itself, next to the code that emits them. - Handlers return nil (200), ErrIgnore (200, counted separately), or an error (500, provider retries) — retry semantics are explicit. - Verifiers live under pkg/webhook/verifiers/ (stripe today; the GitHub webhook can migrate later). Flow: - ctrl-api gains POST /webhooks/stripe (new StripeConfig). On invoice.created for a Deploy workspace renewal invoice it claims the draft (auto_advance off) and dispatches RunDeployBillingClose for the closed period via Restate ingress; the per-customer invoice storm at the roll dedupes onto one durable invocation through the idempotency key. Everything else is ignored and keeps Stripe's own finalization. - RunDeployBillingClose (new CronService handler, keyed by the CLOSED "YYYY-MM" period) pushes every billable workspace's final full-period usage, stamped one second before period end so the "last"-formula meters bill the complete month, then finalizes Deploy workspaces' draft renewal invoices (new internal/invoicecloser), fanned out in bounded batches with one journaled step per workspace. Refuses to close a period that has not ended; losing a finalize race counts as done. - A 01:05 UTC backup cron invokes the same handler with the same idempotency key: if the webhook ran it attaches to that invocation, otherwise drafts are still drafts (auto_advance was disabled) and the sweep closes them. Total ctrl outage degrades to Stripe's one-hour auto-finalization. Prerequisite correctness fix: subscription billing anchors now pin midnight UTC (hour/minute/second 0), not just day_of_month 1. Without it periods are not calendar months and the renewal invoice's meter window would swallow the next month's early month-to-date events, billing the new month's tiny running total instead of the closed month's final one. The hourly push and the close share one pipeline (pushUsage) with an explicit window end and meter-event timestamp; billingperiod gains End(). ENG-2865

Commit:3ecbefa
Author:Flo
Committer:Flo

feat(ctrl): Deploy spend-cap enforcement suspend/resume (ENG-2923)

Commit:aa56584
Author:Flo
Committer:Flo

feat(ctrl): rewire Deploy cancel through ctrl-api (ENG-2922)

Commit:5394fd0
Author:Flo
Committer:Flo

feat(billing): Deploy spend-cap detection and budget alerts (ENG-2904) deploy-spend-check cron prices each budgeted workspace's month-to-date Deploy usage locally from ClickHouse, computes net-of-credit overage against the configured budget, and emails the workspace at 50/75/100%. Enforcement (ENG-2923 SUSPEND) is gated on the ENG-2922 teardown primitive and follows. Plan: todo/eng-2904-2923-spend-cap-enforcement.md

Commit:0b1144c
Author:Flo
Committer:Flo

feat(ctrl): Deploy teardown service (ENG-2922) Adds the DeployTeardownService virtual object: it snapshots a workspace's running deployments, clears apps.current_deployment_id, and schedules archive or standby with drain polling. SUSPEND records the running set so a later resume can restore it. Also removes svc/ctrl/integration/sync_test.go, which stopped compiling after the harness changes and is not re-added here.

Commit:71c119b
Author:Flo
Committer:Flo

refactor(ctrl)!: per-workspace push invocations for deploy billing Not behavior-preserving. The hourly push and month-end close now fan out one Restate invocation per workspace instead of pushing inline, so each push retries and fails in isolation: one workspace's broken Stripe state no longer stalls the others or the tick. The close awaits its pushes and, when any fail, leaves those workspaces' invoices open and returns a TerminalError so the fresh-key backup cron genuinely re-pushes them rather than finalizing an under-billed total. The close also gates finalization on two durable sleeps: a 15-minute ingestion buffer after the period ends before the final ClickHouse read (late rows would otherwise be permanently unbilled once the invoice finalizes), and a 20-minute wait between the final meter push and finalization so Stripe has aggregated the events into the draft's metered lines. DEPLOY NOTE: this changes the journaled step sequence of RunDeployBillingPush and RunDeployBillingClose. Drain in-flight deploy-billing invocations before deploying, or old journals may fail replay.

Commit:3d0fcb0
Author:Flo
Committer:Flo

feat(ctrl): month-end invoice closing webhook for Deploy billing Closes the last correctness gap in the Deploy money path: without this, the billed month-end total was whatever the last hourly push happened to deliver, losing up to an hour of usage at every period roll. New pkg/webhook: a small receiver framework for inbound provider webhooks (method/body policing, signature verification via pluggable verifiers, event-type routing, middleware for integration-specific concerns, and transport metrics so webhook integrations never fly blind): - unkey_webhook_events_total{provider,event,outcome} with outcomes handled / ignored / unhandled / error / verification_failed / bad_request, and unkey_webhook_handler_duration_seconds. Defined in the package itself, next to the code that emits them. - Handlers return nil (200), ErrIgnore (200, counted separately), or an error (500, provider retries) — retry semantics are explicit. - Verifiers live under pkg/webhook/verifiers/ (stripe today; the GitHub webhook can migrate later). Flow: - ctrl-api gains POST /webhooks/stripe (new StripeConfig). On invoice.created for a Deploy workspace renewal invoice it claims the draft (auto_advance off) and dispatches RunDeployBillingClose for the closed period via Restate ingress; the per-customer invoice storm at the roll dedupes onto one durable invocation through the idempotency key. Everything else is ignored and keeps Stripe's own finalization. - RunDeployBillingClose (new CronService handler, keyed by the CLOSED "YYYY-MM" period) pushes every billable workspace's final full-period usage, stamped one second before period end so the "last"-formula meters bill the complete month, then finalizes Deploy workspaces' draft renewal invoices (new internal/invoicecloser), fanned out in bounded batches with one journaled step per workspace. Refuses to close a period that has not ended; losing a finalize race counts as done. - A 01:05 UTC backup cron invokes the same handler with the same idempotency key: if the webhook ran it attaches to that invocation, otherwise drafts are still drafts (auto_advance was disabled) and the sweep closes them. Total ctrl outage degrades to Stripe's one-hour auto-finalization. Prerequisite correctness fix: subscription billing anchors now pin midnight UTC (hour/minute/second 0), not just day_of_month 1. Without it periods are not calendar months and the renewal invoice's meter window would swallow the next month's early month-to-date events, billing the new month's tiny running total instead of the closed month's final one. The hourly push and the close share one pipeline (pushUsage) with an explicit window end and meter-event timestamp; billingperiod gains End(). ENG-2865

Commit:1546a98
Author:Oz
Committer:GitHub

feat(api): add app delete endpoint (#6502) * feat(api): add app delete endpoint * fix: accept both slug and id * fix: correlation id and retryable auditlogs * fix: permissions and tests * chore: tidy

Commit:2f35562
Author:James P
Committer:GitHub

Merge branch 'main' into perkinsjr/eng-2979-allow-configuring-sentinel-policy-rate

Commit:9a52e6b
Author:Flo
Committer:Flo

feat(ctrl): Deploy spend-cap enforcement suspend/resume (ENG-2923)

Commit:4f203b9
Author:Flo
Committer:Flo

feat(ctrl): rewire Deploy cancel through ctrl-api (ENG-2922)

Commit:7b20494
Author:Flo
Committer:Flo

feat(ctrl): Deploy teardown service (ENG-2922) Adds the DeployTeardownService virtual object: it snapshots a workspace's running deployments, clears apps.current_deployment_id, and schedules archive or standby with drain polling. SUSPEND records the running set so a later resume can restore it. Also removes svc/ctrl/integration/sync_test.go, which stopped compiling after the harness changes and is not re-added here.

Commit:393c67f
Author:Flo
Committer:Flo

feat(billing): Deploy spend-cap detection and budget alerts (ENG-2904) deploy-spend-check cron prices each budgeted workspace's month-to-date Deploy usage locally from ClickHouse, computes net-of-credit overage against the configured budget, and emails the workspace at 50/75/100%. Enforcement (ENG-2923 SUSPEND) is gated on the ENG-2922 teardown primitive and follows. Plan: todo/eng-2904-2923-spend-cap-enforcement.md

Commit:bcee0d1
Author:Flo
Committer:Flo

refactor(ctrl)!: per-workspace push invocations for deploy billing Not behavior-preserving. The hourly push and month-end close now fan out one Restate invocation per workspace instead of pushing inline, so each push retries and fails in isolation: one workspace's broken Stripe state no longer stalls the others or the tick. The close awaits its pushes and, when any fail, leaves those workspaces' invoices open and returns a TerminalError so the fresh-key backup cron genuinely re-pushes them rather than finalizing an under-billed total.

Commit:0f74434
Author:Flo
Committer:Flo

feat(ctrl): month-end invoice closing webhook for Deploy billing Closes the last correctness gap in the Deploy money path: without this, the billed month-end total was whatever the last hourly push happened to deliver, losing up to an hour of usage at every period roll. New pkg/webhook: a small receiver framework for inbound provider webhooks (method/body policing, signature verification via pluggable verifiers, event-type routing, middleware for integration-specific concerns, and transport metrics so webhook integrations never fly blind): - unkey_webhook_events_total{provider,event,outcome} with outcomes handled / ignored / unhandled / error / verification_failed / bad_request, and unkey_webhook_handler_duration_seconds. Defined in the package itself, next to the code that emits them. - Handlers return nil (200), ErrIgnore (200, counted separately), or an error (500, provider retries) — retry semantics are explicit. - Verifiers live under pkg/webhook/verifiers/ (stripe today; the GitHub webhook can migrate later). Flow: - ctrl-api gains POST /webhooks/stripe (new StripeConfig). On invoice.created for a Deploy workspace renewal invoice it claims the draft (auto_advance off) and dispatches RunDeployBillingClose for the closed period via Restate ingress; the per-customer invoice storm at the roll dedupes onto one durable invocation through the idempotency key. Everything else is ignored and keeps Stripe's own finalization. - RunDeployBillingClose (new CronService handler, keyed by the CLOSED "YYYY-MM" period) pushes every billable workspace's final full-period usage, stamped one second before period end so the "last"-formula meters bill the complete month, then finalizes Deploy workspaces' draft renewal invoices (new internal/invoicecloser), fanned out in bounded batches with one journaled step per workspace. Refuses to close a period that has not ended; losing a finalize race counts as done. - A 01:05 UTC backup cron invokes the same handler with the same idempotency key: if the webhook ran it attaches to that invocation, otherwise drafts are still drafts (auto_advance was disabled) and the sweep closes them. Total ctrl outage degrades to Stripe's one-hour auto-finalization. Prerequisite correctness fix: subscription billing anchors now pin midnight UTC (hour/minute/second 0), not just day_of_month 1. Without it periods are not calendar months and the renewal invoice's meter window would swallow the next month's early month-to-date events, billing the new month's tiny running total instead of the closed month's final one. The hourly push and the close share one pipeline (pushUsage) with an explicit window end and meter-event timestamp; billingperiod gains End(). ENG-2865

Commit:2bc349a
Author:ogzhanolguncu
Committer:ogzhanolguncu

fix: correlation id and retryable auditlogs

Commit:43ef8e1
Author:ogzhanolguncu
Committer:ogzhanolguncu

feat(api): add app delete endpoint

Commit:743c25b
Author:James P
Committer:GitHub

feat: Allow custom build commands for railpack (#6583) * Railpack config for builds and installs * fix: remove install * Fix: Remove the install error

Commit:aded925
Author:James

fix: remove install

Commit:0ef7dfe
Author:ogzhanolguncu
Committer:ogzhanolguncu

fix: correlation id and retryable auditlogs

Commit:e595899
Author:ogzhanolguncu
Committer:ogzhanolguncu

feat(api): add app delete endpoint

Commit:44d9c73
Author:James

Railpack config for builds and installs

Commit:c32d40d
Author:Flo
Committer:Flo

feat(ctrl): Deploy spend-cap enforcement suspend/resume (ENG-2923)

Commit:9a8d4d3
Author:Flo
Committer:Flo

feat(ctrl): Deploy teardown service (ENG-2922) Adds the DeployTeardownService virtual object: it snapshots a workspace's running deployments, clears apps.current_deployment_id, and schedules archive or standby with drain polling. SUSPEND records the running set so a later resume can restore it. Also removes svc/ctrl/integration/sync_test.go, which stopped compiling after the harness changes and is not re-added here.

Commit:ab519bf
Author:Flo
Committer:Flo

feat(ctrl): rewire Deploy cancel through ctrl-api (ENG-2922)

Commit:b7d22e7
Author:Flo
Committer:Flo

feat(billing): Deploy spend-cap detection and budget alerts (ENG-2904) deploy-spend-check cron prices each budgeted workspace's month-to-date Deploy usage locally from ClickHouse, computes net-of-credit overage against the configured budget, and emails the workspace at 50/75/100%. Enforcement (ENG-2923 SUSPEND) is gated on the ENG-2922 teardown primitive and follows. Plan: todo/eng-2904-2923-spend-cap-enforcement.md

Commit:d5971e6
Author:Flo
Committer:Flo

refactor(ctrl)!: per-workspace push invocations for deploy billing Not behavior-preserving. The hourly push and month-end close now fan out one Restate invocation per workspace instead of pushing inline, so each push retries and fails in isolation: one workspace's broken Stripe state no longer stalls the others or the tick. The close awaits its pushes and, when any fail, leaves those workspaces' invoices open and returns a TerminalError so the fresh-key backup cron genuinely re-pushes them rather than finalizing an under-billed total.

Commit:d023aaf
Author:Flo
Committer:Flo

feat(ctrl): month-end invoice closing webhook for Deploy billing Closes the last correctness gap in the Deploy money path: without this, the billed month-end total was whatever the last hourly push happened to deliver, losing up to an hour of usage at every period roll. New pkg/webhook: a small receiver framework for inbound provider webhooks (method/body policing, signature verification via pluggable verifiers, event-type routing, middleware for integration-specific concerns, and transport metrics so webhook integrations never fly blind): - unkey_webhook_events_total{provider,event,outcome} with outcomes handled / ignored / unhandled / error / verification_failed / bad_request, and unkey_webhook_handler_duration_seconds. Defined in the package itself, next to the code that emits them. - Handlers return nil (200), ErrIgnore (200, counted separately), or an error (500, provider retries) — retry semantics are explicit. - Verifiers live under pkg/webhook/verifiers/ (stripe today; the GitHub webhook can migrate later). Flow: - ctrl-api gains POST /webhooks/stripe (new StripeConfig). On invoice.created for a Deploy workspace renewal invoice it claims the draft (auto_advance off) and dispatches RunDeployBillingClose for the closed period via Restate ingress; the per-customer invoice storm at the roll dedupes onto one durable invocation through the idempotency key. Everything else is ignored and keeps Stripe's own finalization. - RunDeployBillingClose (new CronService handler, keyed by the CLOSED "YYYY-MM" period) pushes every billable workspace's final full-period usage, stamped one second before period end so the "last"-formula meters bill the complete month, then finalizes Deploy workspaces' draft renewal invoices (new internal/invoicecloser), fanned out in bounded batches with one journaled step per workspace. Refuses to close a period that has not ended; losing a finalize race counts as done. - A 01:05 UTC backup cron invokes the same handler with the same idempotency key: if the webhook ran it attaches to that invocation, otherwise drafts are still drafts (auto_advance was disabled) and the sweep closes them. Total ctrl outage degrades to Stripe's one-hour auto-finalization. Prerequisite correctness fix: subscription billing anchors now pin midnight UTC (hour/minute/second 0), not just day_of_month 1. Without it periods are not calendar months and the renewal invoice's meter window would swallow the next month's early month-to-date events, billing the new month's tiny running total instead of the closed month's final one. The hourly push and the close share one pipeline (pushUsage) with an explicit window end and meter-event timestamp; billingperiod gains End(). ENG-2865

Commit:ab2b45b
Author:ogzhanolguncu
Committer:ogzhanolguncu

fix: correlation id and retryable auditlogs

Commit:dc9bc67
Author:ogzhanolguncu
Committer:ogzhanolguncu

feat(api): add app delete endpoint

Commit:73f569c
Author:Flo
Committer:Flo

feat(ctrl): Deploy spend-cap enforcement suspend/resume (ENG-2923)

Commit:bdedbb2
Author:Flo
Committer:Flo

feat(ctrl): rewire Deploy cancel through ctrl-api (ENG-2922)

Commit:0741848
Author:Flo
Committer:Flo

feat(ctrl,frontline): Deploy teardown service + offline 503 (ENG-2922)

Commit:edea2d1
Author:Flo
Committer:Flo

feat(billing): Deploy spend-cap detection and budget alerts (ENG-2904) deploy-spend-check cron prices each budgeted workspace's month-to-date Deploy usage locally from ClickHouse, computes net-of-credit overage against the configured budget, and emails the workspace at 50/75/100%. Enforcement (ENG-2923 SUSPEND) is gated on the ENG-2922 teardown primitive and follows. Plan: todo/eng-2904-2923-spend-cap-enforcement.md

Commit:a164652
Author:Flo
Committer:Flo

refactor(ctrl): per-workspace push invocations for deploy billing Replace the journaled-batch push (one big invocation, per-workspace failures recorded as a bool) with a fan-out to DeployBillingPushService: the orchestrator resolves billable workspaces and dispatches one push invocation per workspace, keyed by workspace id. Each push retries and fails in isolation as its own visible invocation and returns a real error. Hourly orchestrator fires-and-forgets; the month-end close awaits the pushes so the closing invoice sees the final total before finalizing.

Commit:94dffb3
Author:Flo
Committer:Flo

feat(ctrl): month-end invoice closing webhook for Deploy billing Closes the last correctness gap in the Deploy money path: without this, the billed month-end total was whatever the last hourly push happened to deliver, losing up to an hour of usage at every period roll. New pkg/webhook: a small receiver framework for inbound provider webhooks (method/body policing, signature verification via pluggable verifiers, event-type routing, middleware for integration-specific concerns, and transport metrics so webhook integrations never fly blind): - unkey_webhook_events_total{provider,event,outcome} with outcomes handled / ignored / unhandled / error / verification_failed / bad_request, and unkey_webhook_handler_duration_seconds. Defined in the package itself, next to the code that emits them. - Handlers return nil (200), ErrIgnore (200, counted separately), or an error (500, provider retries) — retry semantics are explicit. - Verifiers live under pkg/webhook/verifiers/ (stripe today; the GitHub webhook can migrate later). Flow: - ctrl-api gains POST /webhooks/stripe (new StripeConfig). On invoice.created for a Deploy workspace renewal invoice it claims the draft (auto_advance off) and dispatches RunDeployBillingClose for the closed period via Restate ingress; the per-customer invoice storm at the roll dedupes onto one durable invocation through the idempotency key. Everything else is ignored and keeps Stripe's own finalization. - RunDeployBillingClose (new CronService handler, keyed by the CLOSED "YYYY-MM" period) pushes every billable workspace's final full-period usage, stamped one second before period end so the "last"-formula meters bill the complete month, then finalizes Deploy workspaces' draft renewal invoices (new internal/invoicecloser), fanned out in bounded batches with one journaled step per workspace. Refuses to close a period that has not ended; losing a finalize race counts as done. - A 01:05 UTC backup cron invokes the same handler with the same idempotency key: if the webhook ran it attaches to that invocation, otherwise drafts are still drafts (auto_advance was disabled) and the sweep closes them. Total ctrl outage degrades to Stripe's one-hour auto-finalization. Prerequisite correctness fix: subscription billing anchors now pin midnight UTC (hour/minute/second 0), not just day_of_month 1. Without it periods are not calendar months and the renewal invoice's meter window would swallow the next month's early month-to-date events, billing the new month's tiny running total instead of the closed month's final one. The hourly push and the close share one pipeline (pushUsage) with an explicit window end and meter-event timestamp; billingperiod gains End(). ENG-2865

Commit:dfbaef3
Author:James

feat: allow ratelimit configuration for keys

Commit:0794235
Author:ogzhanolguncu
Committer:ogzhanolguncu

fix: correlation id and retryable auditlogs

Commit:a2e0115
Author:ogzhanolguncu
Committer:ogzhanolguncu

feat(api): add app delete endpoint

Commit:a139754
Author:Oz
Committer:GitHub

feat(api): add app create endpoint (#6489) * feat(dashboard): add app create * refactor: revert rbac coz ui doesn't know how to handle it * refactor: move audit to ctrl api * fix: use actor * refactor: use projectId instead of projectSlug * fix: permission explanation we are still using the old convention * refactor: use project slug instead of projectId * fix: create app accept both project id and slug * fix: adjust query name * fix: openapi schema * chore: tidy permission ui * fix: regex and permission

Commit:1ee9c9c
Author:Flo
Committer:Flo

feat(ctrl,frontline): Deploy teardown service + offline 503 (ENG-2922)

Commit:5d9c0c3
Author:Flo
Committer:Flo

feat(billing): Deploy spend-cap detection and budget alerts (ENG-2904) deploy-spend-check cron prices each budgeted workspace's month-to-date Deploy usage locally from ClickHouse, computes net-of-credit overage against the configured budget, and emails the workspace at 50/75/100%. Enforcement (ENG-2923 SUSPEND) is gated on the ENG-2922 teardown primitive and follows. Plan: todo/eng-2904-2923-spend-cap-enforcement.md

Commit:6080894
Author:Flo
Committer:Flo

feat(ctrl): Deploy spend-cap enforcement suspend/resume (ENG-2923)

Commit:855c64e
Author:Flo
Committer:Flo

feat(ctrl): rewire Deploy cancel through ctrl-api (ENG-2922)

Commit:b3e8b7c
Author:Flo
Committer:Flo

refactor(ctrl): per-workspace push invocations for deploy billing Replace the journaled-batch push (one big invocation, per-workspace failures recorded as a bool) with a fan-out to DeployBillingPushService: the orchestrator resolves billable workspaces and dispatches one push invocation per workspace, keyed by workspace id. Each push retries and fails in isolation as its own visible invocation and returns a real error. Hourly orchestrator fires-and-forgets; the month-end close awaits the pushes so the closing invoice sees the final total before finalizing.

Commit:d6c4011
Author:Flo
Committer:Flo

feat(ctrl): month-end invoice closing webhook for Deploy billing Closes the last correctness gap in the Deploy money path: without this, the billed month-end total was whatever the last hourly push happened to deliver, losing up to an hour of usage at every period roll. New pkg/webhook: a small receiver framework for inbound provider webhooks (method/body policing, signature verification via pluggable verifiers, event-type routing, middleware for integration-specific concerns, and transport metrics so webhook integrations never fly blind): - unkey_webhook_events_total{provider,event,outcome} with outcomes handled / ignored / unhandled / error / verification_failed / bad_request, and unkey_webhook_handler_duration_seconds. Defined in the package itself, next to the code that emits them. - Handlers return nil (200), ErrIgnore (200, counted separately), or an error (500, provider retries) — retry semantics are explicit. - Verifiers live under pkg/webhook/verifiers/ (stripe today; the GitHub webhook can migrate later). Flow: - ctrl-api gains POST /webhooks/stripe (new StripeConfig). On invoice.created for a Deploy workspace renewal invoice it claims the draft (auto_advance off) and dispatches RunDeployBillingClose for the closed period via Restate ingress; the per-customer invoice storm at the roll dedupes onto one durable invocation through the idempotency key. Everything else is ignored and keeps Stripe's own finalization. - RunDeployBillingClose (new CronService handler, keyed by the CLOSED "YYYY-MM" period) pushes every billable workspace's final full-period usage, stamped one second before period end so the "last"-formula meters bill the complete month, then finalizes Deploy workspaces' draft renewal invoices (new internal/invoicecloser), fanned out in bounded batches with one journaled step per workspace. Refuses to close a period that has not ended; losing a finalize race counts as done. - A 01:05 UTC backup cron invokes the same handler with the same idempotency key: if the webhook ran it attaches to that invocation, otherwise drafts are still drafts (auto_advance was disabled) and the sweep closes them. Total ctrl outage degrades to Stripe's one-hour auto-finalization. Prerequisite correctness fix: subscription billing anchors now pin midnight UTC (hour/minute/second 0), not just day_of_month 1. Without it periods are not calendar months and the renewal invoice's meter window would swallow the next month's early month-to-date events, billing the new month's tiny running total instead of the closed month's final one. The hourly push and the close share one pipeline (pushUsage) with an explicit window end and meter-event timestamp; billingperiod gains End(). ENG-2865

Commit:d92216c
Author:ogzhanolguncu
Committer:ogzhanolguncu

refactor: move audit to ctrl api

Commit:0fae7c9
Author:ogzhanolguncu
Committer:ogzhanolguncu

fix: correlation id and retryable auditlogs

Commit:f275272
Author:ogzhanolguncu
Committer:ogzhanolguncu

feat(api): add app delete endpoint

Commit:2f333f1
Author:ogzhanolguncu
Committer:ogzhanolguncu

refactor: move audit to ctrl api

Commit:685a760
Author:Andreas Thomas
Committer:GitHub

feat: stop/start and autoscale previews to 0 (#6488) * feat: stop/start and autoscale previews to 0 * clean up * fix: claude hallucinations * fix: address oz comments * merge

Commit:7f655e8
Author:James

fix: Clickhouse user lock down

Commit:f80fe50
Author:Flo
Committer:Flo

feat(billing): Deploy spend-cap detection and budget alerts (ENG-2904) deploy-spend-check cron prices each budgeted workspace's month-to-date Deploy usage locally from ClickHouse, computes net-of-credit overage against the configured budget, and emails the workspace at 50/75/100%. Enforcement (ENG-2923 SUSPEND) is gated on the ENG-2922 teardown primitive and follows. Plan: todo/eng-2904-2923-spend-cap-enforcement.md

Commit:b48b3a7
Author:Flo
Committer:Flo

refactor(ctrl): per-workspace push invocations for deploy billing Replace the journaled-batch push (one big invocation, per-workspace failures recorded as a bool) with a fan-out to DeployBillingPushService: the orchestrator resolves billable workspaces and dispatches one push invocation per workspace, keyed by workspace id. Each push retries and fails in isolation as its own visible invocation and returns a real error. Hourly orchestrator fires-and-forgets; the month-end close awaits the pushes so the closing invoice sees the final total before finalizing.

Commit:4aa093c
Author:Flo
Committer:Flo

feat(ctrl): month-end invoice closing webhook for Deploy billing Closes the last correctness gap in the Deploy money path: without this, the billed month-end total was whatever the last hourly push happened to deliver, losing up to an hour of usage at every period roll. New pkg/webhook: a small receiver framework for inbound provider webhooks (method/body policing, signature verification via pluggable verifiers, event-type routing, middleware for integration-specific concerns, and transport metrics so webhook integrations never fly blind): - unkey_webhook_events_total{provider,event,outcome} with outcomes handled / ignored / unhandled / error / verification_failed / bad_request, and unkey_webhook_handler_duration_seconds. Defined in the package itself, next to the code that emits them. - Handlers return nil (200), ErrIgnore (200, counted separately), or an error (500, provider retries) — retry semantics are explicit. - Verifiers live under pkg/webhook/verifiers/ (stripe today; the GitHub webhook can migrate later). Flow: - ctrl-api gains POST /webhooks/stripe (new StripeConfig). On invoice.created for a Deploy workspace renewal invoice it claims the draft (auto_advance off) and dispatches RunDeployBillingClose for the closed period via Restate ingress; the per-customer invoice storm at the roll dedupes onto one durable invocation through the idempotency key. Everything else is ignored and keeps Stripe's own finalization. - RunDeployBillingClose (new CronService handler, keyed by the CLOSED "YYYY-MM" period) pushes every billable workspace's final full-period usage, stamped one second before period end so the "last"-formula meters bill the complete month, then finalizes Deploy workspaces' draft renewal invoices (new internal/invoicecloser), fanned out in bounded batches with one journaled step per workspace. Refuses to close a period that has not ended; losing a finalize race counts as done. - A 01:05 UTC backup cron invokes the same handler with the same idempotency key: if the webhook ran it attaches to that invocation, otherwise drafts are still drafts (auto_advance was disabled) and the sweep closes them. Total ctrl outage degrades to Stripe's one-hour auto-finalization. Prerequisite correctness fix: subscription billing anchors now pin midnight UTC (hour/minute/second 0), not just day_of_month 1. Without it periods are not calendar months and the renewal invoice's meter window would swallow the next month's early month-to-date events, billing the new month's tiny running total instead of the closed month's final one. The hourly push and the close share one pipeline (pushUsage) with an explicit window end and meter-event timestamp; billingperiod gains End(). ENG-2865

Commit:518d0be
Author:ogzhanolguncu
Committer:ogzhanolguncu

feat(api): add app delete endpoint

Commit:5538717
Author:ogzhanolguncu
Committer:ogzhanolguncu

refactor: move audit to ctrl api

Commit:ef6d064
Author:Oz
Committer:GitHub

feat(api): add project delete (#6476) * feat(api): add project delete * fix: regex * refactor: move audit to ctrl api * refactor: actor usage * refactor: use id instead of slug

Commit:686f9fb
Author:ogzhanolguncu
Committer:ogzhanolguncu

feat(api): add app delete endpoint

Commit:ecdf259
Author:ogzhanolguncu
Committer:ogzhanolguncu

refactor: move audit to ctrl api

Commit:a57b3ca
Author:ogzhanolguncu
Committer:ogzhanolguncu

refactor: move audit to ctrl api

Commit:1f4fbba
Author:Oz
Committer:GitHub

feat(api): add project creation endpoint (#6472) * feat(api): add project creation endpoint * chore: rename query query name was off. it felt like we are querying projects by workspaceSlug and workspaceID * refactor: add projectID to response * refactor: stricter slug * fix: nits * chore: address comments * fix: pullfrog comment * chore: tidy * refactor: allow deleteProtection flag * refactor: call ctrl instead for billing integrations * feat: allow audit in ctrl * chore: fmt * refactor: allow actor util to accept session

Commit:7688166
Author:Flo
Committer:Flo

feat(billing): Deploy spend-cap detection and budget alerts (ENG-2904) deploy-spend-check cron prices each budgeted workspace's month-to-date Deploy usage locally from ClickHouse, computes net-of-credit overage against the configured budget, and emails the workspace at 50/75/100%. Enforcement (ENG-2923 SUSPEND) is gated on the ENG-2922 teardown primitive and follows. Plan: todo/eng-2904-2923-spend-cap-enforcement.md