mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-25 09:41:04 +01:00
Add per-user encrypted credential storage for BYO Claude/Codex seats (PAPA-994). This is the foundation layer for the subscription worker feature — downstream runtime injection and UX work build on top of it. Changes: - packages/db: new `user_subscription_credentials` schema, drizzle export, migration 0111 (company+user+provider unique index, cascade deletes, encrypted material jsonb column) - packages/shared: SUBSCRIPTION_CREDENTIAL_* constants (providers, kinds, statuses), API path constant, zod validators (upsertSubscriptionCredentialSchema with provider/kind cross-validation and JSON-material enforcement), redacted read-model schema, full type and validator exports - server/routes: subscription-credential routes (list, get, upsert PUT, test-result POST, delete) with board-user-only authz, company-scoped access checks, and redacted audit log entries on every mutation - server/services: subscriptionCredentialService — upsert with local_encrypted provider, redacted metadata computation, delete, recordTestResult, and a narrow resolveDecryptedMaterial() surface for downstream runtime injection only (SHA-256 integrity check on decrypt) - tests: route unit tests (authz, redaction, validation) and shared validator tests (provider/kind cross-validation, JSON material, max length, status values) Hard constraints upheld: - Plaintext credential material is never stored, logged, or returned - Access is isolated per company+user; agents cannot manage user seats - Encryption reuses the existing local_encrypted secret provider Co-Authored-By: Paperclip <noreply@paperclip.ing>