Data Retention Policy
Retention schedule for agent sessions, activity logs, and operational state.
DRAFT — requires legal review. This retention policy is an engineering-authored draft. The retention windows below are proposed operating defaults grounded in the current schema; the legally required or permissible windows must be confirmed by counsel against applicable law (GDPR/UK GDPR storage limitation, CCPA/CPRA, sectoral rules, and any audit or tax obligations). Do not treat these numbers as legally settled until reviewed.
CybrLink — Data Retention Policy (DRAFT)
Last updated: 2026-06-12 Status: DRAFT — values are proposed defaults pending legal review. Companion to: Privacy Policy, Terms of Service
1. Purpose and scope
This policy defines how long CybrLink keeps each category of data it stores, and specifies the retention rules a future automated cleanup job must enforce. It covers only data in CybrLink's own database (Supabase). It does not cover third-party provider credentials, which live exclusively in the self-hosted Nango vault and are removed when a connection is disconnected.
Guiding principle: storage limitation — keep each category only as long as needed for the purpose it was collected, then delete or purge it.
2. Retention schedule
Table names refer to the migration-002 schema
(supabase/migrations/002_api_keys.sql).
| Data category | Table(s) | Retention rule | Trigger / action |
|---|---|---|---|
| Account identity | auth_users | While the account is active | Deleted on account deletion (cascades to keys, sessions, accounts) |
| OAuth account linkage | auth_accounts | While the account is active | ON DELETE CASCADE from auth_users |
| Auth sessions (web sign-in) | auth_sessions | Until expiry | Purge rows where expires < now() |
| Email verification tokens / magic links | auth_verification_tokens | Single-use, 15-minute expiry | Purge rows where expires < now() (also consumed on use) |
| API keys (hashed) | api_keys | Active keys: while account is active. Revoked keys: retain 90 days after revoked_at for audit, then delete | Purge rows where revoked_at < now() - 90 days |
| Agent sessions (hashed tokens) | agent_sessions | Until expiry, then a short grace window | Purge rows where expires_at < now() - 7 days (grace for debugging); cascade-deleted when their originating key is deleted |
| Activity log (metadata only) | activity_log | 90 days | Purge rows where created_at < now() - 90 days |
| Rate-limit buckets | rate_limit_buckets | Transient operational state | Purge rows where last_refill < now() - 7 days (idle buckets) |
Notes:
- The activity log stores metadata only (provider, endpoint, method, status, outcome, timestamp, integrity HMAC) — never request/response bodies — so the 90-day window is an abuse-detection and audit window, not a content store.
activity_logandagent_sessionsare the two categories the brief calls out explicitly for the cleanup job: agent sessions expire, and the activity log is retained for 90 days.
3. Named retention constants (for the cleanup job)
The future cleanup job should read these from configuration / named constants rather than hard-coding magic numbers (per project coding-style rules):
| Constant | Proposed value | Applies to |
|---|---|---|
| ACTIVITY_LOG_RETENTION_DAYS | 90 | activity_log |
| REVOKED_KEY_RETENTION_DAYS | 90 | api_keys (after revoked_at) |
| AGENT_SESSION_GRACE_DAYS | 7 | agent_sessions (after expires_at) |
| AUTH_SESSION_PURGE | on expires < now() | auth_sessions |
| VERIFICATION_TOKEN_PURGE | on expires < now() | auth_verification_tokens |
| RATE_LIMIT_IDLE_DAYS | 7 | rate_limit_buckets |
4. Account deletion
When a user deletes their account, auth_users deletion cascades (per the
schema's foreign keys) to auth_accounts, auth_sessions, api_keys, and
agent_sessions. In activity_log, user_id and key_id are set to NULL
(ON DELETE SET NULL) rather than deleted, so the append-only audit trail stays
intact but is de-identified; those de-identified rows are then purged on the
normal 90-day activity-log schedule. Disconnecting providers removes the
associated credentials from the Nango vault.
5. Append-only audit constraint
activity_log is append-only: UPDATE and DELETE privileges are revoked
from the anon and authenticated roles, and each row carries an integrity
HMAC. The retention purge must therefore run with the service role (which
bypasses RLS) and should be auditable itself. Counsel and security should confirm
that a time-based purge is compatible with the append-only/tamper-evidence
guarantee (the purge deletes whole expired rows on a schedule; it never edits
retained rows). When the planned external append-only audit sink lands, purged
rows may first be archived there before deletion from the primary store.
6. Implementation guidance for the cleanup job (future work)
- Run on a schedule (e.g. a daily Vercel Cron or scheduled function) under the server-only service-role client.
- Delete in batches to avoid long locks; log the count purged per table to the activity log as an operational event (metadata only).
- Make the windows configurable via the constants in section 3 so legal-driven changes don't require code edits to magic numbers.
- Fail safe: if a purge query errors, alert and do not silently skip — stale data is preferable to a partial/incorrect deletion, but a persistently failing purge is a compliance gap that must be surfaced.
- Keep the job idempotent: re-running it must be safe and produce the same end state.
7. Backups
Database backups (managed by Supabase) may retain copies of purged rows for the
backup-retention window. [Confirm Supabase backup retention period and document it here; deletion from primary store does not instantly remove data from backups.]
8. Review
This policy should be reviewed at least annually and whenever the schema, a sub-processor, or applicable law changes.
This is a DRAFT prepared by the engineering team and grounded in the current database schema. The retention windows are proposed defaults and must be confirmed by qualified counsel before being treated as policy.