feat(gitlab): add admin job runner for credential migration#4625
Conversation
Add a database-backed job runner that drives the GitLab credential migration (public audit, backfill, private audit, scrub, final audits) in resumable, lease-fenced batches of 100 integrations: - New gitlab_credential_migration_jobs table (migration 0190) with a singleton active-job partial unique index, lease fencing, cursor checkpoints, and audit count persistence - Admin tRPC router to start (confirmation-gated), run, inspect, list, and cancel migration jobs - Private-audit client for the git-token service credential-audit endpoint with bounded responses and retry classification - Refactor the migration core into processGitLabCredentialMigrationBatch with keyset pagination; the anomaly audit now only counts orphaned credentials so legitimate non-GitLab rows do not block the gate
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Executive SummaryThe previous suggestion regarding Files Reviewed (1 file)
Previous Review Summary (commit e97ff57)Current summary above is authoritative. Previous snapshots are kept for context only. Previous review (commit e97ff57)Status: 1 Issue Found | Recommendation: Merge (address suggestion when convenient) Executive SummaryA minor data-durability footgun exists in the checkpoint repository function for private-audit key metadata, but current callers already avoid triggering it; no CRITICAL or WARNING issues were found across the migration job repository, state machine, batch processor, private-audit HTTP client, admin tRPC router, or the new database migration. Overview
Issue Details (click to expand)SUGGESTION
Files Reviewed (11 files)
Reviewed by claude-sonnet-5 · Input: 18 · Output: 2.9K · Cached: 355.3K Review guidance: REVIEW.md from base branch |
…heckpoint checkpointGitLabCredentialMigrationJob accepted optional privateAuditKeyId/privateAuditPublicKeySha256 and wrote them with ?? null, so a caller omitting them would silently clear persisted private-audit key metadata. Make both parameters required so the choice between preserving the persisted value and clearing it is explicit at compile time.
Summary
Adds a database-backed job runner that executes the GitLab credential migration (the follow-up to #4539's encryption-at-rest work) in resumable, lease-fenced batches instead of a single long-running invocation.
gitlab_credential_migration_jobstable (migration 0190): phase state machine (public_audit→backfill/scrub→private_audit→ final audits), lease token + expiry, cursor checkpoints, persisted audit counts, and a singleton active-job partial unique index keyed on a constant expression so only one queued/running job can exist.adminGitLabCredentialMigrationRouter) to start (confirmation-string gated for backfill/scrub), run one batch per call, inspect, list, and cancel jobs. Every state mutation is fenced by the lease token, and the requesting admin is re-validated on each step./internal/gitlab/credential-auditendpoint: internal service token with a dedicated audience, bounded 16 KB responses, 30 s timeout, and terminal/retryable error classification.processGitLabCredentialMigrationBatchwith keyset pagination. The credential-table anomaly audit now counts only orphaned credentials — previously it counted any non-GitLab parent, which would have blocked every run in production since Bitbucket legitimately shares those tables.Visual Changes
N/A
Reviewer Notes
schema.ts: theUQ_gitlab_credential_migration_jobs_activepartial unique index intentionally uses a constant expression ((1)) — keying it onstatuswould allow one queued + one running job and turn lease acquisition into an unhandled 23505.credential-migration.tsauditOrphanedCredentials: deliberately only flags credentials whose parent integration is gone.