auth configs / projects
Stack: Batch Revoke — Apollo side · PR 4 of 4
Towards DASH-814
We're adding batch-revoke support to the platform: the ability to revoke every connected account in a scope (org / project / auth config / connected account) asynchronously, plus opt-in revoke-on-delete on the public DELETE endpoints. This PR stack is the Apollo side over the Thermos workflow machinery (separate stack).
Apollo-side stack (a DAG — merge bottom-up):
apollo-jobs-table — jobs ownership table + oj_/pj_ ids (base: master)apollo-lib — shared, auth-agnostic revoke-job lib (base: 1)
apollo-endpoints — dashboard + platform job endpoints (base: 2)apollo-delete-cascade — opt-in revoke-on-delete on DELETE handlers ← this PR (base: 2)Base:
apollo-lib— review/merge PRs 1 and 2 first. This PR is a sibling of PR 3 (both build on the shared lib; this one wires itsenqueueRevokeForDeleteinto the DELETE handlers).
Soft-deleting a connection, auth config, project, or org leaves the upstream credentials of its connections live, so tearing an entity down and revoking its credentials are two separate steps today. This adds opt-in cascade revoke so a single DELETE can also start revocation.
All seven DELETE handlers that own connections gain an additive ?revoke_on_delete= query
(default false — byte-identical to today's soft-delete-only behavior, with no dependency on the
revoke service) and an additive revoke_job_id response field:
connected_accounts/{id}, auth_configs/{id}, org/owner/project/{nano_id}connected-accounts/{id}, consumer/auth-configs/{id},
projects/delete/{projectId}, org/{nano_id}A shared enqueueRevokeForDelete(scope) helper enumerates the live connections in scope and
starts a connection_delete revoke job, attaching to any run already in flight for the scope.
It runs enqueue-first, before the soft-delete, so a failed enqueue returns non-2xx and leaves
the entity intact (fail-closed — never a deleted-but-unrevoked orphan). job_class is
project-class for connection/auth_config scopes and org-class for project/org scopes.
Response schemas document only revoke_job_id and keep returning the existing
success/message/status fields through the pass-through .new(), matching the prior
OperationResponseSchema convention. Platform revoke_job_id descriptions point callers to the
dashboard to track the job since the poll API is not yet public; the dashboard org delete gates
the irreversible revoke behind the same admin check DB_ORG_DELETE enforces.
The cascade is thin wiring over the shared lib (PR 2) into seven existing DELETE handlers across two surfaces; the high-value cases are behavioral (per handler) rather than unit, and cross the Thermos enqueue seam — so there is no automated coverage of the handler wiring in this PR.
revoke_on_delete absent/false) → response byte-identical to today,
no Thermos call (no regression on the untouched path).revoke_on_delete=true) → revoke_job_id present and pollable on
the matching surface's job endpoint (dashboard delete → dashboard job endpoint; v3 delete →
platform job endpoint), authorized by job_class.job_id and proceeds (no 409 surfaced).200 + a
trivial/empty job (enumeration is live-only, nothing left to revoke).DB_ORG_DELETE enforces.auth configs / projects