Partner Portalby PenSnap SoftwareLegal

Data Retention & Deletion Policy

Document owner:
Kirk McCoy, Founder, PenSnap Software, LLC
Effective date:
2026-05-21
Last reviewed:
2026-05-21
Next review due:
2027-05-21
Version:
1.0

1. Purpose

This policy defines how PenSnap Software, LLC (“we,” “us,” operator of Partner Portal — the “Service”) retains, reviews, and deletes data we collect, process, or store on behalf of our users and our users' contacts. The policy implements the commitments made in our Privacy Policy and exists to satisfy:

  • Industry-standard data-protection expectations (CCPA/CPRA, ColoradoPA, VCDPA, TDPSA, UCPA, CTDPA).
  • Plaid's production-access security review (financial-data handling).
  • Our own internal commitment to never hold data longer than it serves a legitimate business purpose.

2. Scope

This policy applies to all production data systems operated by PenSnap Software, LLC, including:

  • Application databases (PostgreSQL hosted on Railway; secrets and tokens inside it are encrypted by us with AES-256-GCM).
  • Application secret stores (Railway environment variables, encrypted in transit + at rest).
  • Application logs (Railway log aggregation; vendor-side retention).
  • Backups and disaster-recovery snapshots (Railway-managed).
  • Third-party processors we route data through (Plaid, Resend, Twilio/RepLine, Google Maps, Anthropic).

3. Roles & responsibilities

RoleResponsibility
Policy ownerApproves the policy + every revision. Currently: Founder.
Data protection leadOperationalizes retention windows, builds enforcement crons, runs the periodic review. Currently: Founder.
EngineeringImplements deletion mechanisms in code + verifies they fire.
All usersHonor the policy in day-to-day use; report any data category that lacks a defined retention window.

4. Data categories & retention windows

4.1. Authentication data

DataRetentionDeletion mechanism
Password hash (bcrypt)While account existsHard-deleted on account deletion.
MFA secret (AES-256-GCM encrypted)Until user disables 2FA or admin resets itCleared synchronously on disable / reset action.
MFA backup codes (bcrypt-hashed, legacy)Dormant — no longer issued or acceptedCleared on 2FA disable / reset; retained otherwise as inert historical data.
Session cookies30 days from issuanceAuto-expires; explicit logout clears immediately.
Mobile JWT tokens30 days from issuance`tokenVersion` bump invalidates instantly.

4.2. User account data

DataRetentionDeletion mechanism
Active user recordWhile account is `active = true`N/A.
Deactivated user record30 days after `active = false`Daily cron purges users with `deactivatedAt > 30d` AND zero downstream activity references. Users with history are retained for audit trail.
Account deletion requestHard-deleted within 30 days of requestManual admin action initiates; cron finalizes after 30-day grace period.

4.3. Partner & contact records

DataRetentionDeletion mechanism
Active partner recordWhile the creator's account is activeN/A.
Archived partner (`archivedAt` set)365 days from archivalAnnual cron purges archived partners past the window.
Partner after creator account closure30 days after the creator's account is hard-deleted, then purgedCron sweep tied to user-deletion finalization.

4.4. Financial account data (Plaid)

This section reflects our specific obligations under Plaid's Production Access Terms and our public Privacy Policy.

DataRetentionDeletion mechanism
Plaid access token (AES-256-GCM encrypted)Until user disconnects the cardCleared synchronously on disconnect action.
Plaid item id, account ids, last-4, cardholder nameUntil disconnect + 90 daysDaily cron purges `LinkedCard` rows + cascades to all referenced data 90 days after `disconnectedAt`.
Card transactions (merchant, amount, date, Plaid category)Until disconnect + 90 daysSame cron as above.
Webhook payloads from Plaid30 daysDaily cron purges raw payload rows older than 30 days.

Special handling:

  • We do not store full card numbers (PAN), CVV, PIN, or bank-account/routing numbers. These never enter our systems.
  • On user-initiated disconnect, we immediately call Plaid's /item/remove endpoint to invalidate the access token on Plaid's side before deleting our local copy.
  • Users may also revoke access directly via Plaid Portal (https://my.plaid.com); when Plaid notifies us of revocation, we follow the same 90-day purge for derived data.

4.5. Communications data

DataRetentionDeletion mechanism
Email message body (outbound, marketing)Not stored — handed to Resend at send timeResend retains per its own policy (~30 days).
Email message metadata (recipient, subject, status)90 daysDaily cron purges email-log rows older than 90 days.
SMS message bodyRouted through RepLine; not stored in Partner Portal long-termRepLine retains per its own policy.
SMS consent record (Partner.smsConsent)Permanent for the lifetime of the partner recordDeleted only when the partner record is deleted.
Activity entries (call/email/visit notes)Tied to the partner record's lifecycleDeleted when the parent partner is deleted.

4.6. Audit log

DataRetentionDeletion mechanism
Standard tenant audit entries24 months from creationWeekly cron purges audit-log rows older than the window.
Super-admin / cross-tenant actionsRetained indefinitelyExcluded from the cron's WHERE clause.
Authentication failures (rate-limit hits)30 daysIn-memory only; cleared on server restart.

4.7. Operational / observability data

DataRetentionDeletion mechanism
Application stdout / stderrRailway-managed (~30 days)Railway log retention policy.
Error reports (via observability webhook)Per third-party sink's policyWe pass through; do not duplicate locally.
Database backupsPer Railway backup scheduleRailway-managed; older snapshots auto-pruned.

5. Enforcement

5.1. Automated mechanisms

Each retention cron writes an AuditLog entry summarizing rows purged so the policy owner can verify enforcement on demand.

5.2. Manual mechanisms

  • Account deletion on user request. Submitted via the contact email in our Privacy Policy. Processed within 30 days; hard-deletes the user row + all data linked to them where retention windows don't dictate otherwise.
  • Subject access requests (SAR). Processed within 30 days of verified request. Includes a JSON export of all data tied to the requestor's account.
  • Right-to-be-forgotten requests (CCPA/CPRA/state equivalents). Processed within 30 days of verified request.
  • Plaid-initiated revocation (user revokes via my.plaid.com). Plaid sends a webhook; we mark the connection disconnected and trigger the 90-day purge.

6. Data subject requests

DataRetentionDeletion mechanism
AccessEmail the contact address listed in the Privacy Policy30 days
CorrectionEmail; we update the record30 days
Deletion (account or specific data)Email; we hard-delete within the grace period30 days
Portability (data export)Email; we provide a JSON export30 days
Opt-out of saleN/A — we do not sell personal information—
Opt-out of marketing emailUnsubscribe link in any marketing emailImmediate
Opt-out of SMSReply STOPImmediate
Disconnect a financial account"Disconnect" action in-app; or revoke via my.plaid.comImmediate (token); 90 days (transaction data)

All requests require identity verification (matching email-of-record + at least one additional factor for sensitive deletions).

7. Periodic review

This policy is reviewed at minimum annually, and additionally when:

  • A new category of data is collected (new processor, new feature).
  • A material change in applicable law (e.g., a new state privacy law, GDPR amendments).
  • An incident or near-incident involving retention practices.

Each review records the date, reviewer, and any changes. The policy owner signs off on each new version.

8. Incident response

If a retention violation is discovered (data held past its window):

  1. Purge the offending data immediately as a one-off operation.
  2. Document the incident (cause, scope, count of rows, affected users).
  3. Fix the root cause (cron failure, missing enforcement) within 7 days.
  4. If the violation affected EU/UK residents in a way that triggers GDPR notification thresholds, notify the relevant supervisory authority within 72 hours.
  5. If affected individuals' rights are materially impacted, notify them directly.

9. Version history

VersionDateAuthorSummary
1.02026-05-21Kirk McCoyInitial policy. Defines retention windows for all data categories. Plaid-specific section per Plaid Production Access requirements.

10. Approval

This policy is in effect and binding on PenSnap Software, LLC's operation of the Partner Portal Service as of 2026-05-21.

Name: Kirk McCoy
Forward-facing title: Founder
Legal capacity: Member, PenSnap Software, LLC
Date: 2026-05-21

The canonical source of this policy lives at docs/legal/data-retention-policy.md in our source repository. If this page and the markdown drift, the markdown is canonical; this route is regenerated from it on the next deployment.