Skip to content

Runbook: Voice clone moderation

Voice cloning requires explicit user consent (via the consent flow in the app). Clone model artefacts are stored in kc-clone-eu-{env}. The voice_clone table records owner, consent timestamp, and status.

-- Soft-disable: prevents the clone from being used in new TTS jobs
UPDATE voice_clone
SET status = 'disabled', updated_at = now()
WHERE id = '<clone_id>';

In-flight TTS jobs using this clone will fail with voice_not_found and enter failed state — no data is served.

  1. Disable the clone first (above).
  2. Note the R2 object key from voice_clone.artefact_key.
  3. Delete from R2:
Terminal window
AWS_ACCESS_KEY_ID="$R2_ACCESS_KEY_ID" \
AWS_SECRET_ACCESS_KEY="$R2_SECRET_ACCESS_KEY" \
aws s3 rm "s3://$R2_BUCKET_CLONE/<artefact_key>" \
--endpoint-url "$R2_ENDPOINT"
  1. Hard-delete the DB row (or retain for audit with status = 'deleted'):
UPDATE voice_clone SET status = 'deleted', artefact_key = null, updated_at = now()
WHERE id = '<clone_id>';
  1. In Coolify → API service shell, or via a bun run script:
Terminal window
# Disable all voice clones for the user
psql "$DATABASE_URL" -c "UPDATE voice_clone SET status = 'suspended' WHERE user_id = '<user_id>';"
  1. Revoke the Better-Auth session: invalidate all sessions for the user via the admin panel or directly:
DELETE FROM session WHERE user_id = '<user_id>';
  1. Optionally set user.banned = true in the Better-Auth user table (if banned field exists in schema).
-- Show consent records for a given clone
SELECT id, user_id, consent_at, status, created_at
FROM voice_clone
WHERE user_id = '<user_id>'
ORDER BY created_at DESC;

On a verified erasure request for a user:

  1. Disable and delete all voice clones (above).
  2. Delete media_file, media_job, and user_credit rows for the user.
  3. Delete the Better-Auth user + account rows.
  4. Document the erasure in the operator’s GDPR log (external to this repo).