/** * `@sylphx/management/adminResources` — operator recovery for stuck resources. * * Mirrors `DELETE /admin/resources/:id` in * `apps/api/src/server/platform/routes/admin/resources.ts`. Replaces the * raw `DELETE FROM managed_resources WHERE id=...` historically run from * psql per `docs/how-to/teardown-failure.md`. * * Typical use: an on-call engineer mints a service token scoped to * `platform:resources:forcedelete`, points the CLI * (`sylphx admin resources force-delete `) at the cluster, and the * CLI calls `forceDelete()` here. CI / cron / dashboards call this SDK * directly. */ import type { Client } from './client.js'; export interface ForceDeleteResourceInput { /** * Required. Goes verbatim into the audit row. Min 3 chars. */ readonly reason: string; /** * When `true`, also tears down polymorphic dependents * (`project_resource_bindings` rows; the FK-cascading * `project_platform_resources` row is removed automatically and * counted in `dependentsDeleted`). Default `false`. */ readonly cascade?: boolean; /** * Escape hatch for rows whose `reconcile_status` is NOT `terminating`. * Default `false`. The endpoint refuses the row otherwise — the * reconciler should drive normal teardown; only rows already in * `terminating` are valid candidates. */ readonly reallyForce?: boolean; } export interface ForceDeleteResourceResult { /** TypeID (`res_xxx`). */ readonly id: string; /** `reconcile_status` value the row carried just before the DELETE landed. */ readonly previousStatus: string; /** Echo of the request flag. */ readonly cascade: boolean; /** Echo of the request flag. */ readonly reallyForce: boolean; /** Count of polymorphic dependents removed (always 0 when cascade=false). */ readonly dependentsDeleted: number; } export type VolumeRecoveryClassification = 'unrecoverable-imported-legacy' | 'rebuildable' | 'disposable' | 'replaced-from-source'; export interface RetireBrokenVolumeInput { readonly reason: string; readonly dataClassification: VolumeRecoveryClassification; readonly expectedNamespace: string; readonly expectedPvcName: string; readonly expectedVolumeHandle: string; } export interface RetireBrokenVolumeResult { readonly id: string; readonly previousStatus: string; readonly expectedNamespace: string; readonly expectedPvcName: string; readonly expectedVolumeHandle: string; readonly pvName?: string; readonly pvcDeleted: boolean; readonly mountsDeleted: number; readonly dependentsDeleted: number; readonly environmentsTriggered: ReadonlyArray; readonly dataClassification: VolumeRecoveryClassification; } export interface RepairCnpgIdentityInput { readonly reason: string; readonly expectedClusterName: string; readonly expectedCurrentEngine: 'cnpg' | 'self-hosted'; readonly desiredDbName: string; readonly desiredDbUser: string; } export interface RepairCnpgIdentityResult { readonly id: string; readonly previousStatus: string; readonly clusterName: string; readonly previousEngine: string; readonly engine: 'cnpg'; readonly desiredDbName: string; readonly desiredDbUser: string; readonly generation: number; readonly reconcileQueued: boolean; } /** * Force-delete a stuck `managed_resources` row. Refuses the call when * `reconcile_status !== 'terminating'` unless `reallyForce=true`. Returns * 404 when the row does not exist; 409 on the wrong-status path. */ export declare const forceDelete: (client: Client, id: string, input: ForceDeleteResourceInput) => Promise; /** * Retire a broken imported legacy volume through the audited platform * lifecycle path. The API cross-checks namespace/PVC/CSI handle before * detaching mounts, deleting the PVC, and removing the DB row. */ export declare const retireBrokenVolume: (client: Client, id: string, input: RetireBrokenVolumeInput) => Promise; /** * Repair a misclassified CNPG managed database row by updating Platform * desired state and queueing managed-resource reconciliation. The request * verifies the expected current engine and desired non-secret identity. */ export declare const repairCnpgIdentity: (client: Client, id: string, input: RepairCnpgIdentityInput) => Promise; export interface ResealResourcesInput { /** * The active KEK ID the operator believes the platform is serving with. * The endpoint refuses with 409 if the live ring's `activeKeyId` does * not match — protecting against split-brain rotations where two * operators race. */ readonly keyId: string; /** * Reserved for future per-row scoping. Today the registry walks all * rows under retired keys; the filter is logged as ignored. */ readonly filter?: { readonly projectId?: string; readonly envId?: string; }; } export interface ResealResourcesFieldResult { readonly fieldName: string; readonly rowsSeen: number; readonly rowsRotated: number; readonly rowsFailed: number; readonly failures: ReadonlyArray<{ readonly id: string; readonly reason: string; }>; } export interface ResealResourcesResult { /** The active KEK id the server is serving with (echo of input on success). */ readonly activeKeyId: string; /** Total rows rewritten across all fields. */ readonly totalRotated: number; /** Total rows that failed to rotate (per-row failures, not pass-level). */ readonly totalFailed: number; /** Per-field rotation breakdown. Mirrors `RotationFieldResult`. */ readonly fields: ReadonlyArray; } /** * Walk the canonical rotation registry and re-encrypt every row whose * envelope is not under the active KEK. Idempotent: re-running after * convergence rewrites zero rows. Returns 409 on `keyId` mismatch. */ export declare const reseal: (client: Client, input: ResealResourcesInput) => Promise; //# sourceMappingURL=adminResources.d.ts.map