Data map
Last reviewed 2026-08-13
Inventory of every personal data field HiringCoachAI stores, where it lives, who processes it, and how long it is retained.
Firestore collections
User-scoped subcollections live under users/{uid}/.... Top-level collections that key on userId (or equivalent) are listed flat. Operational and admin-internal collections that hold no customer personal data are excluded; the automated data-map audit maintains an explicit allowlist for those.
User identity and authentication
| Collection | Fields | Classification | Retention | Lawful basis (GDPR) | Processors |
|---|---|---|---|---|---|
users | id, name, email, emailVerified, phone, photoURL, displayName, lastAuthAt, role, cookieConsent (necessary, analytics, marketing, version, decidedAt; written by the cookie-consent API on user action), preferences, coach-owned coachClientRosterSchema custom imported CRM field definitions | Confidential | Until account deletion + audit retention | Contract (6.1.b), consent for optional analytics/marketing tracking | Firebase/GCP; Mailchimp for account/customer communications and communication-list management |
users/{uid}/userDetails | extended profile fields, updatedAt | Confidential | Until account deletion | Contract | Firebase |
users/{uid}/onboardingTaskCategories | id (slug), name (coach-authored category label for client-onboarding tasks), createdAt, updatedAt. Coach-authored taxonomy only; holds no client personal data | Confidential | Until account deletion | Contract | Firebase |
accounts (ordinary NextAuth provider rows) | userId, provider, providerAccountId, type, and provider identity metadata; reusable OAuth credential fields are removed | Confidential | Until account deletion | Contract | Firebase |
accounts/google-drive:{uid} | userId, provider, providerAccountId, credential revision, field-encrypted access_token and refresh_token, expires_at, token_type, exact scope, connected Google email, connectedAt, updatedAt | Restricted | Stored until account deletion; provider revocation makes the credentials unusable but does not currently delete this record | Contract | Firebase / Google OAuth |
sessions | userId, sessionToken, expires | Restricted | Max 7 d (customer) / 12 h (admin) | Contract | Firebase |
authTokens | userId, tokenHash, createdAt, expiresAt | Restricted | 5 min TTL | Contract | Firebase |
verificationTokens | identifier, tokenHash, expires | Restricted | TTL per token (typically 24 h) | Contract | Firebase |
account_deletion_challenges | challengeId, userId, confirmTokenHash, createdAt, expiresAt | Restricted | 15 min TTL | Contract | Firebase |
Resumes, applications, and job-search content
| Collection | Fields | Classification | Retention | Lawful basis (GDPR) | Processors |
|---|---|---|---|---|---|
users/{uid}/resumes | File name, extracted text, metadata, createdAt | Confidential | Until account deletion | Contract | Firebase/GCS, OpenAI (on generation; per-request store: false, no Zero Data Retention (ZDR) amendment), ElevenLabs (TTS output only) |
users/{uid}/files | fileId, ownerUserId, original file name, content type, size, SHA-256 hash, storage bucket/object path, source, status, created/updated/deleted timestamps | Confidential | Until account deletion | Contract | Firebase/GCS |
users/{uid}/resumeMetadata | resume tags, ATS scoring, last-edit timestamps | Confidential | Until account deletion | Contract | Firebase |
users/{uid}/coverLetters | Job title, company, content, status | Confidential | Until account deletion | Contract | Firebase, OpenAI (per-request store: false, no Zero Data Retention (ZDR) amendment) |
users/{uid}/applications | jobId, current status/stage, dates, notes, attached resume reference, server-maintained bounded recent-history cache and reached-stage projection, latest operation ID, transition sequence, server-only lifecycle-deletion coordination flag/time, and recordedStageFirstReachedAt (canonical stage ID to first real server-commit timestamp; migration baselines and inferred dates excluded) so /jobs can consume durable ledger evidence without loading the transition subcollection | Confidential | Until the application or account is deleted | Contract | Firebase |
users/{uid}/applications/{applicationId}/statusTransitions | Append-only versioned status/stage transition events: owner/application/operation IDs, monotonic sequence, event/evidence type, from/to status and stage, source, outcome/last-active-stage context when present, and server timestamp | Confidential | Until the parent application or account is deleted through the authenticated server deletion path | Contract | Firebase |
users/{uid}/drafts | in-progress application materials | Confidential | Until account deletion | Contract | Firebase |
users/{uid}/messageDrafts | recipient and relationship context, message type, subject/body, linked job or contact, generation state, send/archive status and timestamps; nested versions retain complete subject/body/label snapshots and creation time | Confidential | Until account deletion | Contract | Firebase, OpenAI (when the user requests generation) |
users/{uid}/pitchProfiles | profile label, positioning brief (career thesis, differentiator, target opportunities, anchor story and framing), master narrative, tone preset, source resume ID and timestamps; nested audiences include contact/job context, tone overrides, generated formats, guidance, practice bullets and coaching thread | Confidential | Until account deletion | Contract | Firebase, OpenAI (when the user requests generation) |
users/{uid}/pitchSuites | legacy pitch-suite and audience content retained for existing users, including audience/contact/job context, pitch formats, guidance, practice content and timestamps | Confidential | Until account deletion | Contract | Firebase, OpenAI (when the user requests generation) |
users/{uid}/customQuestions | question, responses, createdAt | Confidential | Until account deletion | Contract | Firebase, OpenAI (per-request store: false, no Zero Data Retention (ZDR) amendment) |
users/{uid}/shortAnswers | short-answer responses for application packets | Confidential | Until account deletion | Contract | Firebase |
users/{uid}/fitAnalysis | per-job fit analysis records | Confidential | Until account deletion | Contract | Firebase, OpenAI |
users/{uid}/candidateAnalysis | candidate-evaluation outputs | Confidential | Until account deletion | Contract | Firebase, OpenAI |
users/{uid}/intelBriefings | per-company intel briefings | Confidential | Until account deletion | Contract | Firebase, OpenAI, Perplexity |
users/{uid}/interviewAnalyses | user-pasted interview transcript/notes, job and company context, model and processing status, normalized analysis and feedback outputs, timestamps | Confidential | Until account deletion | Contract | Firebase, OpenAI |
users/{uid}/explore | exploration session state (saved searches, comparisons) | Confidential | Until account deletion | Contract | Firebase |
users/{uid}/toolState | offer-negotiation workspace state (offer terms, compensation figures, priorities, negotiation plan, saved offers), updatedAt | Confidential | Until account deletion | Contract | Firebase |
adminResumeBenchFixtures | benchmark fixture labels, anonymized resume text, source label, content hash, creator, notes | Confidential | Until admin deletion of fixture or superseded benchmark corpus | Legitimate interest (quality assurance and model evaluation) | Firebase |
adminResumeBenchRuns | benchmark run configuration, sampled fixture/model IDs, status, cost/quality summary, creator, timestamps | Confidential | 2 years or until admin deletion | Legitimate interest (quality assurance and model evaluation) | Firebase, OpenAI, Anthropic, Google Gemini |
adminResumeBenchRuns/{runId}/attempts | per-fixture/model attempt status, run number, parser/judge outputs and scores, latency, token/cost metadata, error details | Confidential | 2 years or until parent run deletion | Legitimate interest (quality assurance and model evaluation) | Firebase, OpenAI, Anthropic, Google Gemini |
Coaching, interview prep, and pep-talks
| Collection | Fields | Classification | Retention | Lawful basis (GDPR) | Processors |
|---|---|---|---|---|---|
users/{uid}/interviewQuestions | generated practice questions per role | Confidential | Until account deletion | Contract | Firebase, OpenAI |
users/{uid}/interviewResearchCases | research-case payloads for interview prep | Confidential | Until account deletion | Contract | Firebase, OpenAI, Perplexity |
users/{uid}/pepTalks | generated pep-talks (text + audio) | Confidential | Until account deletion | Contract | Firebase, OpenAI, ElevenLabs / Google Cloud Text-to-Speech |
users/{uid}/tasks | title, description, status, dueDate, tags, and source-specific workflow metadata; coach content-permission requests use a deterministic Mission Control task containing the relationship ID, coach ID/name, bounded requested-scope keys, stable permission request ID and operation ID, a fixed Coach Management deep link, and completion/audit timestamps, but no client content | Confidential | Until account deletion | Contract | Firebase |
users/{uid}/onboarding | onboarding progress / preferences | Confidential | Until account deletion | Contract | Firebase |
coachProfileDrafts | coach user ID; display name, headline, biography, location, languages, specialties, audience, industries, career stages, style, credentials, services, links, photo metadata, section visibility; publication/directory state; moderation status, findings, analysis, submitted snapshot, and reviewer decision metadata | Confidential | Until coach account deletion; embedded moderation records remain until replaced or deleted, subject to legal holds | Contract, legitimate interest (content integrity, fraud and abuse prevention) | Firebase/GCP; OpenAI for profile text, link-field, and photo moderation; SendGrid or Gmail when a human-review notification is requested |
coachPublicProfiles | published coach profile projection, coach user ID, public link, photo metadata, contact links, section visibility, publication/directory/admin state, and review snapshot metadata | Public for published fields; otherwise Confidential | Until coach account deletion; public availability ends when unpublished | Contract, legitimate interest (directory integrity) | Firebase/GCP |
coachPublicProfileSlugs | public-profile slug, coach user ID while active, pseudonymous owner hash, active/reserved/redirect/tombstone state, redirect target, and timestamps | Internal / Confidential | Active association until profile deletion; redirects, tombstones, and pseudonymous owner hash retained while needed to prevent impersonation or link takeover and preserve link integrity | Legitimate interest (anti-impersonation and stable public links) | Firebase |
coachCustomDomains, coachCustomDomainOwners | coach user ID, normalized forwarding hostname, hashed one-time DNS verification token, verification status/check timestamps, canonical HiringCoachAI redirect target, removal expiry, and deterministic one-domain ownership pointer | Confidential before activation; hostname and redirect are public after coach-configured forwarding | Active while configured; removed domain records expire after 30 days via expiresAt TTL; pointer and ownership are removed immediately on domain removal or account deletion | Contract, legitimate interest (domain ownership verification, anti-hijacking, and reliable forwarding) | Firebase; coach-selected registrar/DNS provider |
coachProfileReviewNotifications | review ID, coach name/email, full submitted profile snapshot, highlighted findings, automated analysis, reviewer URL, delivery status, attempt/lease timestamps, and expiry | Confidential | 30 days via Firestore TTL | Legitimate interest (policy enforcement and reliable administrative delivery) | Firebase; SendGrid or Gmail for administrative delivery |
coachRelationships | coach/client user IDs and emails, names, status, permissions (including the client's account-controlled per-category content-sharing grants and a bounded per-scope permission-request state containing request/task IDs, pending/granted/denied status, requested/responded/denied/last-sent timestamps, resend-attempt count, and idempotency operation IDs), accepted/ended dates, notification preferences, billing linkage, relationship summary stats, purchase-bound shared-offer access state with immutable snapshot and expiration bindings, optional coach-only importedPractice metadata (imported display name, notes, package, sessions remaining, next session date, and arbitrary coach-imported custom CRM values) stashed through bulk practice import | Confidential | Imported practice metadata is erased when either participant deletes their account; shared-offer access state follows its engagement and commercial evidence; remaining relationship data follows the relationship and evidence schedules below | Contract, legitimate interest (coach-client access control and billing audit) | Firebase, Stripe for billing linkage |
coachRelationships (deletion-only restricted fields) | Normal participant IDs, emails, and names are nulled on deletion. Server-only deletion metadata retains deletedParticipantKeys (stable pseudonymous subject digests) and, for a deleted coach, billingOwnerTombstone (version, relationshipId, coachUserIdHash, deletedSubjectKey, status, retentionReason, createdAt, deletedAt). These values are pseudonymous, linkable or re-identifiable by authorized systems, and are not anonymous. | Restricted | Retain only while required for deletion retry, provider-event authentication, refunds, disputes, subscription shutdown, the applicable financial or legal-claim period, or a legal hold under the founder-approved schedule. | Contract, legitimate interest, legal obligation or claims where applicable | Firebase |
coachProspects | coach's prospect/CRM pipeline: prospect name/email, coach user ID, pipeline status, source (e.g. declined invitation), linked relationship/engagement/payment-alias IDs, desired service, target timeline, follow-up/lost-reason notes, activity timestamps | Confidential | Until coach account deletion | Contract, legitimate interest (coach CRM/pipeline management) | Firebase |
coachServiceCatalog | coach ID; editable package copy, scope, delivery and checkout settings; pricing options and encrypted coupon configuration; entitlement and appointment-credit templates; bounded landing blocks, including testimonial text/attribution, publication permission and truth/substantiation attestations, public results/material-connection disclosures, and coach-selected image/video URLs; and (Workstream F) an optional onboardingRecipeId reference to a coach-owned coachOnboardingRecipes entry, resolved to a published version before the offer can go live | Confidential; Restricted for encrypted coupon configuration; selected fields become Public only through a published offer snapshot | Until coach account deletion or earlier coach deletion; archived entries remain until deletion to preserve coach history | Contract; legitimate interest (offer integrity, consumer transparency, and abuse prevention) | Firebase |
coachPublicOffers | coach and catalog IDs, public slug, visibility and lifecycle state, hashed invite capability, immutable published versions of public offer descriptions, pricing, entitlements, and package access duration (Workstream F: including the sealed onboardingRecipeId reference, when configured), and private coupon fingerprints | Public for published offer fields; Restricted for invite and coupon hashes | Until coach account deletion; public availability ends when archived | Contract, legitimate interest (stable offer links and purchase integrity) | Firebase |
coachPublicOfferSlugs | normalized public offer slug, coach user ID, public offer ID, catalog item ID, lifecycle timestamps, and tenant-safe routing metadata | Internal | Until offer or coach deletion, subject to uniqueness-tombstone retention in the deletion workflow | Contract; legitimate interest (stable, tenant-safe public offer routing) | Firebase |
coachOfferAnalytics | HMAC-pseudonymous browser session hash, offer ID, and allowlisted event, source and day. No raw IP, user agent, referrer or participant PII. | Confidential / Pseudonymous | Approximately 25 months via Firestore TTL | Legitimate interest (privacy-preserving practice reporting) | Firebase |
coachReportPreferences | coach ID, explicit weekly-report opt-in, delivery schedule, last-delivered week, and bounded delivery lease and failure metadata | Confidential | Until coach account deletion | Consent for weekly email; legitimate interest (reliable delivery) | Firebase; SendGrid or Gmail for delivery |
coachRelationships.sms | While a client is opted in: E.164 U.S./Canadian mobile number, SHA-256 phone hash, last four digits, country, timezone, consent disclosure version/hash, consent method/status/timestamps, and carrier block state. The consent method also records WHICH surface captured the gesture (authenticated_client for the coach-portal panel, client_onboarding_wizard for the token-gated Client Onboarding Recipes wizard); the consent standard, disclosure binding, and evidence record are identical either way. The raw number is cleared on opt-out. | Restricted | Active opt-in or account deletion; non-reversible consent metadata may remain in the separate consent-evidence record | Consent; contract (requested non-promotional coaching notifications); legitimate interest (opt-out enforcement) | Firebase |
coachSmsMessages | coach/client/relationship IDs, purpose, message body, phone hash and last four digits, consent disclosure binding, scheduled time/timezone, delivery state, provider message ID/status, and bounded retry/lease metadata. No raw destination number is copied to this collection. | Confidential; Restricted delivery metadata | 30 days after the scheduled delivery time via Firestore TTL, or earlier account deletion | Consent; contract; legitimate interest (reliable and non-duplicative delivery) | Firebase; Twilio Programmable Messaging |
coachSmsConsentEvents | coach/client/relationship and actor IDs, opt-in/opt-out/provider-unblock action, source, phone hash and last four digits, country, exact disclosure version/hash, event time, and retention expiry. No raw phone number or message content. | Restricted legal/compliance evidence | Six years from each event via Firestore TTL under the current conservative policy; legal review may revise this period | Consent; legitimate interest and legal claims (prove and enforce consent/revocation) | Firebase |
coachLeadCaptureSettings | coach-owned public opt-in configuration: enabled state, heading, description, button label, and timestamps | Internal / Public when enabled | Until coach account deletion | Contract, legitimate interest (coach practice management) | Firebase |
coachWebhookSubscriptions | coach user ID, connection name, HTTPS destination URL, selected event types, enabled state, AES-256-GCM-encrypted signing secret, non-secret suffix hint, and delivery-health timestamps | Restricted | Until connection deletion or coach account deletion | Contract, legitimate interest (coach-requested workflow automation) | Firebase; coach-selected Zapier or custom webhook destination |
coachWebhookSubscriptionQuotas | coach user ID and automation-connection count used only to enforce the ten-connection limit transactionally | Internal | Until coach account deletion; count is updated on connection create/delete | Contract, legitimate interest (abuse prevention and service integrity) | Firebase |
coachWebhookEvents | coach user ID, coach-scoped stable event ID, event type, occurrence timestamp, minimal producer-supplied JSON payload, and related delivery IDs | Confidential | 90 days via expiresAt TTL, or coach account deletion | Contract, legitimate interest (reliable coach-requested workflow automation) | Firebase |
coachWebhookDeliveries | coach user ID, coach-scoped event/delivery/subscription IDs, delivery state, attempt and lease metadata, bounded HTTP status/error evidence, retry time, and success/failure timestamps | Confidential | 90 days via expiresAt TTL, or coach account deletion | Contract, legitimate interest (reliable delivery, troubleshooting, and replay) | Firebase; coach-selected Zapier or custom webhook destination |
coachLeadOptInVerifications | hashed one-time verification token as document ID; coach ID; claimed email/name; exact consent disclosure version/hash; hashed request metadata; status and expiry | Confidential | Valid for 24 hours; personal fields are cleared after confirmation and the deployed Firestore TTL policy deletes expired records asynchronously | Consent, legitimate interest (double opt-in integrity and abuse prevention) | Firebase, SendGrid or Gmail for verification delivery |
coachProspectEmailMappings | coach ID, keyed email HMAC, and prospect ID used to deduplicate public opt-ins without storing the email in the mapping | Internal / Pseudonymous | Until coach account deletion | Legitimate interest (deduplication and consent-state integrity) | Firebase |
publicPurchaseIntents | Public-offer workflow state containing coach/offer/version references; purchaser, payer, recipient, and participant names/emails/roles; verified user and fulfilled relationship references; immutable pricing, entitlement, and package-duration snapshot; consent/authorization choices; hashed coupon and resume capabilities; state; workflow expiry; server-authored completion request time and purchase-bound accessExpiresAt; and (Workstream F) the sealed offer snapshot's onboardingRecipeId plus a fulfillment.onboardingHandoff outcome record (timestamp and either the spawned clientOnboardingRuns run ID, a skip reason, or an error message, never response content) | Confidential | Unverified and abandoned intents expire after 24 hours via Firestore TTL. The TTL is cleared after verified relationship fulfillment so the record remains until account deletion or it can be safely rebuilt from the durable commercial and financial records. | Steps at the request of the data subject before entering a contract; contract where formed; legitimate interest (secure resumability, fulfillment integrity, and fraud prevention) | Firebase; SendGrid or Gmail for verification |
publicPurchaseIntentRequests | 24-hour idempotency record containing a hashed request ID, intent/coach/offer references, request fingerprint, and expiry; no plaintext contact details | Internal / Pseudonymous | 24 hours via Firestore TTL | Legitimate interest (duplicate-purchase prevention and request integrity) | Firebase |
coachPublicOfferPurchases | Purchase, public-intent, coach, client, payer, relationship, engagement, agreement, obligation, offer, and offer-version references; status; snapshot hash; immutable commercial snapshots; purchase-bound accessExpiresAt; content-access binding IDs; and timestamps | Confidential / Restricted commercial workflow | Until a participant account is deleted, or earlier when safely rebuilt from retained legal and financial records; applicable financial and contract evidence follows its own retention policy | Contract; legitimate interest (reliable offer fulfillment, access enforcement, and reconciliation); legal obligation where applicable | Firebase; Stripe identifiers where payment is required |
engagementBookingRecords | coach/client relationship and engagement IDs, session type, appointment time/timezone/status, attendee contact details supplied for the booking, location, cancellation/reschedule links, calendar-delivery status/operation metadata, and customer meeting join URL when generated | Confidential | Until coach account deletion or booking-record deletion under the scheduling retention policy | Contract | Firebase; Google Calendar, Microsoft Outlook, Apple CalDAV, or Zoom only when the coach enables the corresponding integration |
coachSchedulingLinks | SHA-256 link ID as the non-authorizing URL-path handle; optional AES-256-GCM-encrypted raw booking bearer for links created in the authenticated coach scheduling dashboard; coach, relationship, engagement, booking, session type, scope, audience, redisplayable flag, status, use-count, expiry, and revocation metadata. New links carry the raw bearer only in the browser fragment until it is exchanged for a signed capability cookie; the path handle never authorizes by itself. | Restricted | Until coach account deletion; link validity ends immediately at expiry, use limit, coach Delete/revocation, or account-deletion cleanup | Contract; legitimate interest (secure, coach-controlled scheduling) | Firebase |
coachCalendarConnections | coach user ID, provider account identity where supplied by the provider, selected busy-calendar IDs, writable destination calendar ID, sync/failure/invitation preferences, encrypted OAuth tokens or CalDAV app passwords, token expiry, one-use OAuth state hash, connection revision, health/error timestamps | Restricted | Credentials and provider-selection metadata are retained until provider-specific disconnect, permanent credential revocation, or coach account deletion. A minimal disconnected/revoked status record may remain until account deletion; see the external-system rows below. | Consent, contract | Firebase; Google Calendar, Microsoft Outlook, or Apple CalDAV |
coachCalendars | calendar owner and authorized member IDs, sharing roles, name, description, color key, lifecycle state, optimistic version, and timestamps | Confidential | Until the owner archives/deletes the calendar or deletes the account; a departing shared member is removed from the access list | Contract, legitimate interest (coach-controlled scheduling workspace) | Firebase |
coachCalendarEvents | calendar and organizer IDs, event type/title, start/recurrence time zone, optional end time zone, timed or date-only range, recurrence and exceptions, attendees and responses, location, description, HTTPS conference/resource links, reminders and bounded in-app delivery lease/state metadata, visibility/free-busy state, guest permissions, canonical client/session/booking references, lifecycle state, optimistic version, and timestamps | Confidential | Until calendar/event deletion or organizer account deletion; canceled event tombstones are retained only as required for recurrence and synchronization correctness | Contract, legitimate interest (coach-controlled scheduling and client-session coordination) | Firebase; configured meeting or calendar provider only for separately enabled canonical booking flows |
coachCalendarWorkspaceVersions | coach user ID, monotonically increasing workspace revision, last changed source, and timestamp; contains no event, booking, or task content | Internal | Until coach account deletion | Legitimate interest (bounded real-time calendar invalidation) | Firebase |
coachCalendarPreferences | user ID, visible/default calendars, locale/time-zone and week/time format choices, working display preferences, event defaults, and keyboard-shortcut preference | Internal | Until account deletion | Contract, legitimate interest (remember user-requested calendar settings) | Firebase |
coachCalendarMutationReceipts | actor user ID, client-generated idempotency key, resulting event ID, creation time, and expiry; no event content or attendee details | Internal / Pseudonymous | Seven days via Firestore TTL, or earlier account deletion | Legitimate interest (prevent duplicate calendar writes during retries) | Firebase |
coachMeetingConnections | coach user ID, Zoom user/account IDs, encrypted OAuth access/rotating refresh tokens, granted scope, connection revision, one-use OAuth state hash, status, connection time, health/error state, and token expiry | Restricted | Until disconnect, Zoom deauthorization, credential revocation, or coach account deletion | Consent, contract | Firebase; Zoom |
coachAppointmentCalendarFeeds | coach user ID, active/disabled state, hash of the private appointments-feed bearer, rotation/disable timestamps; raw bearer is reveal-once and is never stored | Restricted | Until coach disables the feed or deletes the account | Consent, contract | Firebase; subscribed calendar provider chosen by the coach |
coachBookingRateLimits | hashed booking/feed credential, authenticated account ID, or request-source key; route bucket; fixed-window count; expiry timestamp | Internal | Firestore TTL at twice the applicable rate-limit window (at most 2 hours for current buckets) | Legitimate interest (abuse prevention) | Firebase |
coachBookingEmailVerifications | hashed verification token as document ID; scheduling-link and hold IDs; claimed email, name, note, and timezone; sealed but not-yet-attributed legal acknowledgment; status and expiry | Confidential | The verification token is valid for eight minutes. After successful use, the service immediately attempts to clear all personal and staged-assent fields; the TTL policy remains the fallback if that best-effort cleanup write fails. Unused expired records are deletion-eligible under the deployed Firestore TTL policy; cleanup is asynchronous and typically occurs within 24 hours after expiry, not necessarily at the eight-minute mark. | Contract, legitimate interest (public-booking abuse prevention and reliable consent attribution) | Firebase, SendGrid or Gmail for verification delivery |
coachContractNotifications | durable contract-email outbox containing relationship/engagement/version and party IDs, recipient role/email, delivery operation ID, delivery status and retry/lease metadata, provider message ID, document hash, and PDF attachment hash manifest; detailed JSON evidence is never attached | Confidential | Delivery evidence follows the related agreement-evidence period. Queued recipient data is canceled/redacted on account deletion; provider-accepted evidence is retained for the surviving party and applicable evidence floor; repeated known failures become dead_letter; ambiguous provider outcomes remain blocked in outcome_unknown until traceable administrative resolution. Legal holds extend retention. | Contract, legitimate interest (reliable delivery and evidence integrity), legal obligation where applicable | Firebase; SendGrid or Gmail for delivery |
contractEvidenceLegalHolds and nested events | scoped relationship/engagement/version IDs, idempotent operation IDs, matter reference, reason code, status, placing/releasing administrator IDs, timestamps, post-release purge requirement, and immutable placement/release history | Restricted | Evidence is preserved for the full active hold and is not automatically released. Authorized release after both parties have deleted marks an explicit purge requirement; purge remains blocked while another applicable hold exists or the hold registry cannot be read. Placement/release history remains as legal-claim and control evidence. | Legal obligation, establishment/exercise/defense of legal claims | Firebase |
contractEvidenceDeletionLocks | relationship and account-deletion/purge operation IDs, deletion kind/state, worker owner token, lease and fenced-recovery lineage, irreversible-deletion marker, evidence counts, hold-change metadata, post-release purge state, active hold IDs, and timestamps used to serialize evidence deletion against hold changes | Restricted | Persistent control record retained with account-deletion, legal-hold, and contract-evidence audit records; no automatic TTL is configured. A completed irreversible-deletion marker is not reset by retry. Expired post-release purge leases may be resumed by a new fenced worker; every evidence deletion transaction rechecks current ownership. | Legal obligation, establishment/exercise/defense of legal claims, legitimate interest (race-free deletion) | Firebase |
coachIntakeTemplates | coach user ID, template name/description, section and field definitions, choice options, upload requirements, status, revision and published-version references, content hash, operation metadata, and timestamps; nested activity and operations record actor/action/version metadata | Confidential | Until coach account deletion | Contract | Firebase |
coachIntakeTemplates/{templateId}/versions | immutable published template definition, coach/publisher user IDs, version number, content hash, and publication timestamp | Confidential | With the parent template; deleted on coach account deletion | Contract, legitimate interest (stable assigned-form history) | Firebase |
engagementIntakeForms | relationship, engagement, coach and client IDs; immutable template snapshot; client responses; linked file, resume, job, and application references; missing-item state; coach feedback; waiver, status, due-date, version, and actor metadata; nested activity and operations record action and replay metadata | Confidential | Until client account deletion; if the coach account is deleted first, client-owned responses remain while coach identifiers and feedback are redacted and operation records are removed | Contract | Firebase/GCP for referenced files |
coachCourses | coach user ID, course title/summary, module and lesson definitions, private Material references, published-version pointer, lifecycle state, version, idempotency metadata, and timestamps; nested activity records actor/action/version metadata | Confidential | Until coach account deletion | Contract | Firebase |
coachCourseVersions | coach user ID, immutable published course snapshot, content hash, publisher, version number, and publication timestamp | Confidential | Until coach account deletion; assigned enrollments retain their own immutable snapshot until either participant deletes their account | Contract, legitimate interest (stable assigned-course history) | Firebase |
coachCourseEnrollments | relationship, coach and client IDs; immutable assigned course snapshot; enrollment, drip, progress, completion, revocation, version, idempotency, and timestamps; purchase-scoped public-offer access grants containing intent/purchase/offer/snapshot provenance, status, grant type, and optional accessExpiresAt; nested activity records progress actions | Confidential | Until the coach or client account is deleted; purchase-scoped grants remain with the enrollment for access and commercial audit integrity | Contract; legitimate interest (access enforcement and commercial integrity) | Firebase |
coachFormAutomationRules | coach user ID, reusable trigger and course/lesson filters, published form-template reference, delay and completion-gate settings, lifecycle state, version, idempotency metadata, and timestamps; nested activity records rule changes | Confidential | Until coach account deletion | Contract | Firebase |
coachFormAutomationAssignments | coach, client, relationship, course, enrollment, lesson, rule, and published form-template references; due time, worker lease/retry state, assigned intake-form reference, completion and error metadata, and timestamps | Confidential | Until the coach or client account is deleted | Contract, legitimate interest (reliable form delivery and retry audit) | Firebase |
coachRelationships/{relationshipId}/comments | page path, selected text/element anchor, comment body, suggestion text, mentions, status, resolver/deletion metadata | Confidential | Until both accounts are deleted; redacted on user deletion/redaction request | Contract | Firebase, SendGrid/Gmail for notification delivery |
coachRelationships/{relationshipId}/comments/{commentId}/replies | reply body, author role/user ID, status, timestamps | Confidential | Until both accounts are deleted; redacted on user deletion/redaction request | Contract | Firebase, SendGrid/Gmail for notification delivery |
coachRelationships/{relationshipId}/messages | relationship-scoped inbox message body, author role/user ID, inbound email metadata, redaction/deletion metadata | Confidential | Until both accounts are deleted; redacted on user deletion/redaction request | Contract | Firebase, SendGrid/Gmail for notification delivery |
coachRelationships/{relationshipId}/threads | inbox thread grouping for the relationship: subject, participant user IDs, per-user unread/sender flags, last-message preview snippet and author role, message count, status, timestamps | Confidential | Until both accounts are deleted; redacted on user deletion/redaction request | Contract | Firebase, SendGrid/Gmail for notification delivery |
coachRelationships/{relationshipId}/privateNotes | coach-only private notes, coach user ID, status, timestamps | Confidential | Until coach account deletion or coach deletion of the note | Contract, legitimate interest (coach recordkeeping) | Firebase; OpenAI only when the coach explicitly invokes Thought Partner with private context, per-request store: false, with OpenAI's standard API retention applying because no ZDR amendment is documented |
coachRelationships/{relationshipId}/sessions | booking and relationship IDs, coach/client user IDs, schedule and status, shared agenda, notes, summary, decisions, outcome, next-session plan, version and operation metadata | Confidential | Until client account deletion; if the coach account is deleted first, shared session content remains with coach identifiers redacted while private notes and operation records are removed | Contract | Firebase; OpenAI only when the coach explicitly invokes Thought Partner or assignment ideation with safe session content, per-request store: false, with OpenAI's standard API retention applying because no ZDR amendment is documented |
coachRelationships/{relationshipId}/sessions/{sessionId}/privateNotes | coach-only session notes, coach and relationship IDs, version and operation metadata, timestamps | Confidential | Until coach account deletion or coach deletion of the note | Contract, legitimate interest (coach recordkeeping) | Firebase |
coachRelationships/{relationshipId}/sessions/{sessionId}/operations and nested private-note operations | idempotency operation ID, action, actor user ID, session ID, resulting status/version, timestamp | Internal / Confidential | With the parent session or private-note record | Legitimate interest (integrity and replay prevention) | Firebase |
coachRelationships/{relationshipId}/goals | goal title and rationale, kind, owner role, metric, baseline/target/current value, target date, status, health, sort key, coach/client/creator/updater IDs, version and operation metadata | Confidential | Until client account deletion; if the coach account is deleted first, shared goal content remains with coach identifiers redacted | Contract | Firebase |
coachRelationships/{relationshipId}/milestones | goal link, title, completion criteria, evidence, target/completion dates, linked task IDs, status, sort key, coach/client/creator/updater IDs, version and operation metadata | Confidential | Until client account deletion; if the coach account is deleted first, shared milestone content remains with coach identifiers redacted | Contract | Firebase |
coachRelationships/{relationshipId}/goalCheckIns | goal and milestone links, progress type, note, value, health, correction/supersession links, coach/client/actor IDs, version and timestamps | Confidential | Until client account deletion; if the coach account is deleted first, shared check-in content remains with coach identifiers redacted | Contract | Firebase |
coachRelationships/{relationshipId}/goalOperations | idempotency operation ID, action, actor user ID/role, request hash, entity type/ID, non-content result snapshot, and timestamp | Internal / Confidential | Removed when either participant account is deleted | Legitimate interest (integrity and replay prevention) | Firebase |
coachRelationships/{relationshipId}/targetEntries | target type (role/company), title, priority, rationale, decision criteria, hypothesis, planned entry points, status, closed reason, coach leveling annotation (band, confidence, source, note), linked contact/application IDs, sort key, coach/client/creator/updater IDs, version and operation metadata (operation ledger shared with goalOperations above) | Confidential | Until client account deletion; if the coach account is deleted first, shared target-strategy content remains with coach identifiers redacted | Contract | Firebase |
coachRelationships/{relationshipId}/networkingTargets | networking-plan target: person name, company, role, linked contact ID (validated against the client's contacts), objective, relationship stage, sequenced outreach steps (label, kind, due-offset days, completion timestamp), notes, sort key, coach/client/creator/updater IDs, version and operation metadata (operation ledger shared with goalOperations above) | Confidential | Until client account deletion; if the coach account is deleted first, shared networking-plan content remains with coach identifiers redacted | Contract | Firebase |
coachRelationships/{relationshipId}/activity | relationship activity type, actor user ID/role, summary, related comment/message/task IDs, timestamps | Confidential | Until both accounts are deleted; retained as audit metadata after relationship end | Contract, legitimate interest (coach-client access and deletion audit) | Firebase |
coachRelationships/{relationshipId}/sessions | booking/session and engagement IDs, agenda, preparation state, shared notes and summary, decisions, outcome, next-session plan, lifecycle status, actor IDs, timestamps | Confidential | Retained read-only after relationship end; deleted on client account deletion; coach account deletion redacts coach identity and private fields | Contract, legitimate interest (coaching record continuity) | Firebase |
coachRelationships/{relationshipId}/sessions/{sessionId}/privateNotes | coach-only session notes, coach user ID, version and timestamps | Confidential | Until the session is deleted; removed/redacted when the coach or client account-deletion workflow processes the workspace | Contract, legitimate interest (coach recordkeeping) | Firebase |
coachRelationships/{relationshipId}/sessions/{sessionId}/operations | idempotency operation ID, action, actor user ID, session/status/version result metadata and timestamps | Internal / Confidential | Until either relationship participant deletes their account or the parent session is deleted | Legitimate interest (safe retry and auditability) | Firebase |
coachRelationships/{relationshipId}/goals | goal title/rationale, owner, metric, baseline/target/current values, target date, status, health/evidence, ordering, actor IDs, timestamps | Confidential | Retained read-only after relationship end; deleted on client account deletion; coach account deletion redacts coach identity | Contract | Firebase |
coachRelationships/{relationshipId}/milestones | linked goal and task IDs, title, completion criteria, target date, status, evidence, ordering, actor IDs, timestamps | Confidential | Retained read-only after relationship end; deleted on client account deletion; coach account deletion redacts coach identity | Contract | Firebase |
coachRelationships/{relationshipId}/goalCheckIns | linked goal/milestone/session IDs, progress or blocker note, health and value evidence, correction chain, actor IDs/role, effective date, timestamps | Confidential | Retained read-only after relationship end; deleted on client account deletion; coach account deletion redacts coach identity | Contract, legitimate interest (progress history integrity) | Firebase |
coachRelationships/{relationshipId}/goalOperations | idempotency operation ID, actor ID/role, request fingerprint, goal/milestone/check-in result snapshot, timestamps | Internal / Confidential | Until either relationship participant deletes their account or the parent relationship is deleted | Legitimate interest (safe retry and auditability) | Firebase |
coachRelationships/{relationshipId}/opportunityTriage | per-application coach triage verdict (pursue/investigate/deprioritize/skip), rationale, recommended next step, coach user ID, timestamps | Confidential | Until either participant account is deleted or the mark is cleared | Contract | Firebase |
coachRelationships/{relationshipId}/scorecard | coach-set weekly activity targets (applications, outreach, follow-ups, interviews), updater ID, timestamps | Confidential | Until either participant account is deleted | Contract | Firebase |
coachRelationships/{relationshipId}/artifactReviews | reviewed artifact kind/ID, approval status, coach feedback note, reviewer ID, artifact-version snapshot, timestamps | Confidential | Until either participant account is deleted or the review is cleared | Contract | Firebase |
coachRelationships/{relationshipId}/programApplications | applied program template ID/name, start date, per-item creation results, applier ID, request fingerprint, timestamps | Confidential | Until either participant account is deleted | Contract, legitimate interest (safe retry and auditability) | Firebase |
coachRelationships/{relationshipId}/rubricAssessments | scored rubric template ID, frozen rubric name/criteria snapshot at scoring time, scored subject (artifact kind/ID or free-text label), per-criterion scores and notes, overall note, weighted total/max, client-visibility flag, scorer ID, version and operation metadata | Confidential | Until either participant account is deleted | Contract, legitimate interest (safe retry and auditability) | Firebase |
coachRelationships/{relationshipId}/assessments | assessment title, provider/type, completion date, bounded notes, server-verified source-file metadata and owning user ID, separate coach-only report, explicitly publishable client summary, original visibility flag, lifecycle status, version and operation metadata. Client projections omit source ownership, private notes and coach reports. | Confidential | Retained read-only for the coach after relationship end; client access ends with the relationship or explicit unpublish. Deleted on either participant account deletion, together with nested operation records. | Contract, legitimate interest (coaching record continuity and safe retry) | Firebase; original files remain in the owning user's private file storage; OpenAI only when the coach explicitly invokes Thought Partner with assessment or private relationship evidence, per-request store: false, with OpenAI's standard API retention applying because no ZDR amendment is documented |
coachRelationships/{relationshipId}/assessments/{assessmentId}/operations | assessment mutation idempotency ID, action, request fingerprint, version/result metadata and timestamps; server-only retry ledger with no file bytes | Internal / Confidential | Until the parent assessment is deleted or the applicable relationship participant account is deleted | Legitimate interest (safe retry and auditability) | Firebase |
coachRelationships/{relationshipId}/journeyNarratives | bounded period, coach-edited source-grounded narrative sections, safe source labels/links, named evidence warnings, approval/version/publication state, and mutation metadata. Generation prompts, model metadata, raw evidence text, and coach writing-profile contents are not stored. Client projections omit source IDs and coach-only warnings. | Confidential | Retained read-only for the coach after relationship end; client access requires explicit publication and ends on unpublish or relationship end. Deleted on either participant account deletion, together with nested operation records. | Contract, legitimate interest (coaching record continuity and safe review) | Firebase; OpenAI for ephemeral narrative generation, per-request store: false, with OpenAI's standard API retention applying because no ZDR amendment is documented |
coachRelationships/{relationshipId}/journeyNarratives/{narrativeId}/operations | journey narrative save/publication idempotency ID, action, request fingerprint, version/result metadata and timestamps; server-only retry ledger with no raw evidence or prompts | Internal / Confidential | Until the parent narrative is deleted or the applicable relationship participant account is deleted | Legitimate interest (safe retry and auditability) | Firebase |
coachRelationships/{relationshipId}/placements | role/title, company, linked application ID, compensation (base/bonus cents, equity note, currency -- optional, coach or client may decline to share), transition type, start/accepted dates, computed time-to-outcome, note, recorder ID/role, retraction metadata, post-placement check-in plan stamp (created timestamp, touchpoint keys/dates/task references), version and timestamps | Confidential | Until both accounts are deleted | Contract | Firebase |
coachRelationships/{relationshipId}/evidenceHighlights | coach-curated before/after highlight title, category, before/after text, optional metric (label/from/to), optional linked artifact reference, pin timestamp, creator ID, timestamps | Confidential | Until both accounts are deleted | Contract | Firebase |
coachRelationships/{relationshipId}/careerPlan | shared career-plan narrative doc (strategy): positioning summary, channel strategy, risk list (label/mitigation), updater ID/role, version and timestamps; the rest of the composed plan (targets, primary goal, weekly scorecard, pipeline summary, latest placement) is read live from those domains' own already-registered collections, not stored here | Confidential | Until both accounts are deleted | Contract | Firebase |
users/{uid}/programTemplates | coach-authored program name/description and sequenced assignment/goal blueprints with relative due offsets, version and operation metadata | Confidential | Until coach account deletion or template archival/deletion | Contract | Firebase |
users/{uid}/assignmentTemplates | coach-authored assignment template title/instructions, task category, relative due offset, review-required flag, material/survey attachment references (type, id, label), status, assignment counters, version and operation metadata | Confidential | Until coach account deletion or template archival/deletion | Contract | Firebase; OpenAI only when the coach explicitly invokes assignment ideation using active technique/template and safe session content, per-request store: false, with OpenAI's standard API retention applying because no ZDR amendment is documented |
users/{uid}/rubricTemplates | coach-authored rubric name/description, applicable content areas, weighted scoring criteria (label, description, weight, scale), version and operation metadata | Confidential | Until coach account deletion or template archival/deletion | Contract | Firebase |
coachIntakeTemplates/{templateId}/versions | coach ID, customizable section/question/file-upload definition, required-field rules, immutable published version, content hash, status, timestamps | Confidential | Until coach account deletion; archived templates and published versions remain for assigned-form integrity | Contract | Firebase |
coachIntakeTemplates/{templateId}/operations | template mutation idempotency ID, actor ID/role, request fingerprint, action/result metadata, timestamps; sibling activity records hold the same lifecycle audit context | Internal / Confidential | Until coach account deletion with the parent template | Legitimate interest (safe retry and template auditability) | Firebase |
engagementIntakeForms | relationship/engagement and coach/client IDs, immutable template snapshot, custom questions, responses and uploaded-artifact references, completion requirements, status, due/submission/waiver metadata, timestamps | Confidential | Deleted on client account deletion; coach account deletion retains the form for the client while redacting coach identity, private feedback and waiver reason | Contract | Firebase/GCS for referenced uploads |
engagementIntakeForms/{intakeFormId}/operations | intake mutation idempotency ID, actor ID/role, request fingerprint, action/result metadata, timestamps; sibling activity records hold lifecycle changes | Internal / Confidential | Until the parent intake form is deleted | Legitimate interest (safe retry and intake auditability) | Firebase |
coachContractTemplates/{templateId}/versions | coach ID, reusable agreement name, immutable template version text, content hash, status, timestamps | Confidential | Until coach account deletion or earlier template deletion | Contract | Firebase |
coachContractDocuments/{documentId} and /versions/{versionId} | coach owner ID; display and original file names; active version; bounded binding count; archive state; PDF type, size, and page count; server-derived source hash; exact source object generation; custody state and timestamps. PDF bytes are Restricted. Direct Firestore access is denied. Authenticated server APIs list only coach-owned roots. | Restricted | Quarantine and source objects plus coach library roots and versions are deleted on expiry, earlier owner action where allowed, or coach account deletion. The immutable agreement envelope and locked archive evidence remain separately retained for delivered or signed agreements. | Contract; legitimate interest in evidence integrity and legal claims | Firebase; private GCS quarantine and source buckets |
coachContractDocumentOperations | coach ID, action, idempotency operation ID, request hash, bounded upload object reference, result reference, outcome state, and timestamps. This collection contains no PDF bytes and is server-only. | Internal / Restricted | Unbound upload operations are deleted with the coach account or earlier workflow expiry. Any future operation promoted into bound agreement evidence must follow that agreement's retention policy. | Legitimate interest in safe retry, upload reconciliation, and abuse prevention | Firebase |
coachContractDocumentBindings | deterministic binding version and ID; coach, relationship, engagement, agreement, document, and version IDs; document and outer-envelope manifest hashes; status and creation timestamp. The row is a server-only index into immutable evidence, not the evidence itself. | Restricted | Deleted with the coach library after source custody cleanup. The agreement envelope and locked archive evidence survive according to the agreement retention schedule. | Contract; legitimate interest in deterministic binding and replay safety | Firebase |
coachContractDocumentViews | bound relationship, engagement, agreement, document and version references; participant role or subject reference; document and outer manifest hashes; first and latest viewed timestamps; and hashed request telemetry. Storage paths, signed URLs, IP or user-agent hashes, upload internals, scanner details, and key-management details are excluded from the identity-verified assisted export projection. | Restricted contract evidence | Retained with the bound agreement evidence, normally at least seven years. A surviving party keeps access; legal holds extend retention. | Contract; legitimate interest in proving document presentation and legal claims | Firebase |
coachRelationships/{relationshipId}/engagements | coach/client and relationship IDs, engagement type/title/status, current agreement version, pricing/delivery summary, package expirationDate, active obligation IDs, billing state, Stripe subscription ID/status/current-period and cancellation timestamps; immutable subscription routing snapshot (connected-account ID, mode, model) and signed-agreement binding (agreement version/content hash, signed renewal terms, initial-payment obligation ID); shared-participant access engagements also bind the source relationship, engagement, agreement, purchase intent, snapshot hash, and accessExpiresAt | Restricted | Unaccepted drafts: until owner deletion or earlier deletion. Accepted or billed records and shared access projections follow applicable financial-record retention and, for automatic renewal, are retained at least three years from the recorded consent or one year after verified subscription termination, whichever is later. Unknown termination and legal holds prevent purge. | Contract; legal obligation; legitimate interest in billing integrity, access enforcement, and establishing, exercising, or defending legal claims | Firebase; Stripe for subscription processing |
coachRelationships/{relationshipId}/engagements/{engagementId}/paymentObligations | agreement version and engagement IDs, obligation type/sequence/status, amount/currency/due date, Stripe payment-intent/invoice/charge identifiers, paid/refund/dispute/offline-payment state, fee/tax/routing metadata, checkout-time platform-refund-policy version/hash snapshot, idempotency and timestamps | Restricted | Up to seven years where retained as billing/tax evidence; never shorter than the applicable automatic-renewal consent-evidence floor; legal holds extend retention. Raw card data is not stored. | Contract; legal obligation; legitimate interest in billing integrity and dispute handling | Firebase; Stripe |
coachRelationships/{relationshipId}/engagements/{engagementId}/paymentObligations/{obligationId}/refundReservations | refund operation, coach, relationship, engagement, obligation, actor, and approval-request IDs; reserved amount, reason, immutable provider-routing snapshot, reservation/provider status, Stripe refund ID, and timestamps | Restricted | Retained with the parent payment obligation for the applicable financial-record and claims period, up to seven years where required; legal holds extend retention | Contract; legal obligation; legitimate interest in preventing duplicate or excessive refunds and reconciling provider outcomes | Firebase; Stripe identifiers |
coachRelationships/{relationshipId}/engagements/{engagementId}/paymentObligations/{obligationId}/clientRefundRequests | authenticated client, coach, relationship, engagement, obligation and request IDs; requested amount/currency/reason and limited client statement; immutable payment, signed-policy and delivery snapshots; request hash; hash-chained lifecycle, reviewer and internal target evidence; exact Stripe refund/charge/payment-intent bindings and provider outcome | Restricted financial and claims-case evidence | Retained with the payment obligation for the applicable financial, refund, dispute and claims period, up to seven years under the founder-approved schedule; legal holds extend retention. Exact identity, statement and hashes remain unchanged where necessary to preserve case integrity; access and disclosure use the restricted assisted DSR process. | Contract; legal obligation where applicable; legitimate interest in refund handling, reconciliation and establishing, exercising or defending claims | Firebase; Stripe identifiers |
coachRelationships/{relationshipId}/engagements/{engagementId}/agreementVersions | immutable server-authored legal and pricing snapshots; non-operative coach service descriptions wrapped under the current content-policy version; versioned/hash-bound platform minimum refund rights and ordinary-evidence retention policy; signed renewal price/frequency/first-renewal date; document hash; delivery/view events; verified signer email and user ID; typed or drawn signature artifact; disclosure version/text; versioned signer representation that the signer has legal capacity and self/entity authority as applicable; IP address and user-agent evidence; event hashes; completion certificate and platform seal | Restricted | Unheld, undelivered unsigned drafts: until coach account deletion or earlier deletion. Delivered/signed non-renewing versions: at least seven years from the latest verified delivery, signature, completion, or later verified engagement termination; active or unverifiably terminated signed engagements, missing/altered schedules, and evidence-integrity failures remain blocked for review under the founder-approved v2 policy. An automatic-renewal consent record is retained at least three years from consent or one year after verified subscription termination, whichever is later; unknown termination and legal holds extend retention. Related financial records follow their separate schedule. Free-form coach legal clauses are not accepted. | Contract; legal obligation where applicable; legitimate interest in establishing, exercising, or defending the parties' agreement | Firebase/GCP |
coachPaymentReminders | relationship/engagement and coach IDs, trigger and delivery state, recipient-safe payment link or note, retry/lease/provider outcome metadata; automatic-renewal rows additionally bind the agreement version/content hash, initial-payment obligation, signed service and renewal terms, Stripe-derived occurrence date, cancellation path, and administrative provider-outcome resolution evidence | Confidential; Restricted for automatic-renewal evidence | General reminders are canceled/redacted during relationship account deletion; no automatic TTL is currently configured. Provider-accepted, in-flight, or unknown-outcome automatic-renewal evidence follows the later of three years from consent or one year after verified subscription termination. Unknown outcomes require traceable resolution; legal holds extend retention. | Contract; legitimate interest (reliable service communications); legal obligation where applicable | Firebase; SendGrid or Gmail for delivery |
coachClientPaymentAuditEvents | event type, actor/coach/relationship/engagement/obligation/operation IDs, Stripe object/event IDs, target resource, action/decision/reason, before/after hashes, amount/currency, hashed IP/user-agent, retention class, and traceable legal-hold, purge, notification, or reminder-outcome resolution metadata | Internal / Restricted | No automatic TTL is currently configured. audit_default follows the two-year application-audit target; billing_records may be retained up to seven years; contract_evidence follows the related evidence period; legal_hold remains for the hold and applicable claims/audit period. No class is purged while an applicable hold remains. | Legal obligation; legitimate interest (billing integrity, fraud prevention, forensics, safe administrative resolution, legal claims) | Firebase |
coachPaymentProfiles | Coach UID and document key; connected-account IDs by mode; account, readiness, capability, and admin-approval state; restricted paymentAccessRevocation lifecycle including request and attempt IDs, requesting and attempting admin IDs, timestamps, status, counts, bounded provider account or subscription failure details, error codes and messages, and exception ID | Restricted | Active while payments are enabled; on account deletion retained only as disabled or tombstoned routing and revocation evidence for unresolved provider or financial events, then for the financial-record period (up to seven years where applicable) plus holds | Contract, legitimate interest, legal obligation or claims | Firebase; Stripe IDs only |
coachConnectAccountOwners | Server-only immutable Stripe connected-account ID to coach UID to test/live mode registry, plus deletion status and timestamp. The direct UID is intentionally retained as restricted operational identity; it is not anonymized. | Restricted | Through the period in which provider events, refunds, disputes, payouts, or subscription cancellation may require authentication or reconciliation; up to the applicable financial period plus holds | Contract, legitimate interest, legal obligation or claims | Firebase; Stripe |
coachClientPaymentStripeLookups | Immutable Stripe object, connected-account, and resource routing; coach, relationship, engagement, obligation, mode, and binding version. Direct identifiers are restricted; deleted-subject display and contact data is redacted. | Restricted | Provider replay and reconciliation period and the financial-claim period, up to seven years where applicable, plus holds | Contract, legitimate interest, legal obligation or claims | Firebase; Stripe |
clientPaymentOperations | Ordinary provider operation type/state/lease/idempotency/request hash/outcome; high-assurance contract operations additionally store validated top-level coach/client/actor/relationship/engagement/agreement routing, the complete signed operation and pending projection (including evidence payloads and, when supplied by an electronic-signature transition, raw IP address, user-agent, disclosure/consent text, and typed or drawn signature artifact), a signed/hash-bound replay descriptor and domain-pending-patch hash, HSM-signed canonical envelope and reservation, RFC 3161 timestamp receipt, immutable GCS package/generation receipt, release-artifact binding, prerequisite receipt chain, and final receipt. This is not a hash-only record. Non-final high-assurance stages are queried by operation version, stage, and oldest update time for bounded deterministic replay; retry state records exponential backoff, attempt count, outcome certainty, and durable manual-review/dead-letter disposition. | Restricted; exact legal evidence for high-assurance operations | Ordinary operations follow provider replay/reconciliation and financial-claim periods, up to seven years where applicable. Recognized high-assurance operation versions v1, v2, and v3 are preserved byte-for-byte through the related contract/claims period and any hold because redaction invalidates the evidence chain; assisted DSR only. The replay worker may advance only the current v3 operation through its signed handler, exact subject routing, and exact pending projection; v1/v2 operations are retained for manual review and are never silently upgraded or replayed. No automatic TTL under the founder-approved schedule. | Contract; legitimate interest in integrity, deterministic recovery, replay prevention, fraud prevention, and legal claims; legal obligation where applicable | Firebase; Google Cloud KMS; RFC 3161 timestamp authority; locked Google Cloud Storage |
coachRecurringBillingIncidents | Global recurring-billing emergency authorization/reconciliation evidence: action and reason, server-derived requesting/retry admin IDs and roles, timestamps, hashes, provider inventory counts, and bounded exact provider-object failures/state | Restricted | Seven years after completion; longer while unresolved, while the control is active, or under legal hold. No TTL under the founder-approved schedule. | Legitimate interests in fraud prevention, financial control, and legal claims; legal obligation where applicable | Firebase; Stripe |
coachRecurringBillingControl | Singleton fail-closed barrier: active state, generation, incident/action, activating admin ID/role/time, and immutable incident hash | Restricted | Preserve while active, then with the incident for seven years; holds extend retention | Legitimate interests in financial controls; legal obligation where applicable | Firebase |
coachRecurringBillingAttempts | Append-only attempt/retry evidence: incident/hash, random attempt ID and sequence, server-derived operator ID/role/rationale, start/completion, action/outcome/counts, and attempt/completion hashes | Restricted | Seven years after completion; longer while unresolved or under hold. No TTL under the founder-approved schedule. | Legitimate interests in audit, fraud prevention, financial control, and legal claims | Firebase; Stripe |
coachRefundApprovalRequests | Coach, relationship, engagement, obligation, and operation IDs; amount, currency, refund reason, and routing snapshot; request hash; maker, reviewer or checker, and consumer user IDs and roles; decision, status, review evidence, and timestamps | Restricted | Seven years from final disposition or transaction, or longer for an active legal hold, under the founder-approved schedule | Legal obligation, legitimate interest, establishment, exercise, or defense of claims | Firebase; Stripe identifiers |
coachPaymentLedger, coachStatements, coachTaxYearSummaries, coachTaxDocumentStatuses, coachPaymentCorrections, and retainerEntitlements | Transaction, service, fee, payout, refund, dispute, statement, tax-status, correction, and entitlement evidence; resource IDs and actor, coach, and relationship references. Deleting-subject contact and display data is redacted and a restricted pseudonymous tombstone, policy class, and reason are added. | Restricted / Confidential | Up to seven years for accounting, tax, or claims records, extended by holds, under the founder-approved schedule | Contract, legal obligation, legitimate interest or claims | Firebase; Stripe where applicable |
coachRevenueEntries | Coach-typed manual bookkeeping rows for the coach's own practice: coach user ID, entry ID, date, signed amount in cents, currency, kind (income, refund, expense), free-text category, label and memo, and an optional relationship ID plus denormalized client display name the coach chose to attach. Server-only; no client read or write. | Confidential | Retained with the coach's practice accounting records for the applicable financial and claims period, up to seven years under the founder-approved schedule; deleted on coach request or account deletion | Contract, legitimate interest (coach practice bookkeeping) | Firebase |
engagementHourEntries | Coach, client, relationship, engagement, agreement and hour-entry IDs; work date, duration, description, approval/correction state, actor and operation evidence, hourly-rate snapshot, billable amount/currency and invoice-obligation binding | Restricted / Confidential | Retained with the related accepted agreement, service-delivery and billing records for the applicable contract, financial and claims period, up to seven years under the founder-approved schedule; holds extend retention | Contract; legal obligation where applicable; legitimate interest in billing integrity and establishing, exercising or defending claims | Firebase |
coachLegalAcceptances | Exact append-only coach clickwrap and electronic-signature proof: acceptance ID; coach and accepting-user IDs; normalized accepting email; document, version, effective-date, content, and approval-manifest hashes; acknowledgments; disclosure, intent, and fresh signing-authority evidence; hashed IP and user agent; operation ID; canonical acceptance timestamp; evidence hash; and a rotatable-key HMAC platform seal over the complete evidentiary payload and its stored projections. Identity is deliberately retained unchanged because removing it would impair proof of assent. Server-only; assisted DSR only. | Restricted legal evidence | Applicable contract, limitations, or claims period plus holds; no automatic account-deletion mutation under the founder-approved schedule. | Contract, legal obligation, establishment, exercise, or defense of claims | Firebase |
consumerLegalAcceptances | Exact append-only consumer clickwrap proof: user ID and email, document version and content hash, acknowledgments, method, hashed IP and user agent, timestamps, and evidence fields. Identity is deliberately retained unchanged to prove assent. Server-only; assisted DSR only. | Restricted legal evidence | Applicable contract, limitations, or claims period plus holds; no automatic account-deletion mutation under the founder-approved schedule. | Contract, legal obligation, establishment, exercise, or defense of claims | Firebase |
anonymousPurchaseLegalAcceptances | Exact append-only clickwrap and purchase evidence for a buyer who is not signed in: normalized purchaser email; exact legal-release snapshot and acknowledgment labels; purchase kind; Stripe object type and ID; amount and currency; hashed IP and user agent; stable operation ID; canonical acceptance timestamp; evidence hash; and rotatable-key HMAC platform seal. The plaintext email is retained because it attributes the assent and supports receipts, disputes, and data-rights matching. Server-only; assisted DSR only. | Restricted legal and billing evidence | Applicable contract, financial, limitations, or claims period plus holds; no automatic deletion TTL under the founder-approved schedule. | Contract; legal obligation where applicable; legitimate interest in transaction integrity, disputes, and legal claims | Firebase; Stripe identifiers only |
anonymousBookingLegalAcceptances | Exact append-only clickwrap evidence for a signed-out booking, created only after the visitor proves control of the claimed email: verified normalized email; exact legal-release snapshot and acknowledgment labels; booking-link and hold IDs; hashed IP and user agent; stable operation ID; acknowledgment and email-verification timestamps; evidence hash; and rotatable-key HMAC platform seal. The plaintext verified email is retained to attribute assent and support data-rights matching. Server-only; assisted DSR only. | Restricted legal evidence | Applicable contract, limitations, or claims period plus holds; no automatic deletion TTL under the founder-approved schedule. | Contract; legitimate interest in reliable booking formation, consent integrity, disputes, and legal claims | Firebase |
anonymousPurchaseFulfillmentExceptions | Provider object and payment-intent IDs, purchase kind, amount/currency, evidence-failure code, refund ID/status, webhook event ID, exception version/status, and timestamp for a legacy or unverifiable gift that was automatically refunded instead of fulfilled. It contains no plaintext purchaser email. | Restricted billing reconciliation evidence | With the related refund and financial record, up to seven years where applicable; holds extend retention under the founder-approved schedule. | Contract; legal obligation where applicable; legitimate interest in refund reconciliation and preventing unverified fulfillment | Firebase; Stripe identifiers only |
coachNotifications | notification recipient identifiers, event type, title/body preview, delivery status, email provider status, action URL | Confidential | 90 days target for delivery state; account deletion removes user-linked records | Contract, legitimate interest (service notifications) | Firebase, SendGrid/Gmail |
coachNotificationDailyState | per-recipient daily notification throttle keys, relationship ID, event type, send-count metadata, timestamps | Internal / Confidential | 90 days target | Legitimate interest (notification rate limiting) | Firebase |
supportThreads | HiringCoachAI Support conversations: ownerUserId, owner role, subject, participants, assigned admin user ID, per-user unread flags, last-message preview snippet, message count, status, timestamps; nested messages hold the message body/HTML, author role, and inbound-email routing metadata | Confidential | Until account deletion | Contract, legitimate interest (customer support) | Firebase, SendGrid/Gmail for support email routing |
users/{uid}/coachMessageDrafts | unsent inbox message drafts: target (relationship or support thread), subject, sanitized body HTML, preview snippet, timestamps | Confidential | Until account deletion | Contract | Firebase |
users/{uid}/messageDrafts | user-authored communication drafts, including subject and body; message type, status, label, and timestamps; recipient, contact, job, application, and task context when the user links it; generated or edited content when the user invokes an AI writing feature | Confidential | Until the user deletes the draft or account | Contract | Firebase; OpenAI only when the user invokes AI generation or revision |
users/{uid}/messageDrafts/{draftId}/versions | user-saved communication snapshots containing subject, body, optional version label, and creation timestamp | Confidential | With the parent draft; deleted when the user deletes the draft or account | Contract | Firebase |
users/{uid}/messageTemplates | coach-authored reusable message templates: name, subject, sanitized body HTML with {{wildcards}}, timestamps | Confidential | Until account deletion | Contract, legitimate interest (coach productivity) | Firebase |
users/{uid}/messageLabels | user-created inbox labels: name, color, parent label ID, timestamps | Internal / Confidential | Until account deletion | Contract | Firebase |
users/{uid}/messagingPrefs | per-user inbox UI settings (reading-pane position, density, keyboard shortcuts, undo-send window, default reply); no message content | Internal | Until account deletion | Legitimate interest (product configuration) | Firebase |
coachChatConversations | coach/client user IDs, participants, denormalized relationship status, last-message preview, message-count counter, per-user unread counts/read receipts/typing heartbeat/mute/star/pin state, seeded display names/photos | Confidential | Until both accounts are deleted; redacted on user deletion/redaction request | Contract, legitimate interest (coach-client access control) | Firebase |
coachChatConversations/{conversationId}/messages | realtime chat message text, sender user ID, kind, status (active/deleted tombstone), reactions, attachment metadata (file name/content type/size, no URLs), link-preview metadata, client idempotency key, timestamps | Confidential | Until both accounts are deleted; redacted on user deletion/redaction request | Contract | Firebase, GCS for attachment storage |
coachChatPresence | per-user online/away state and last-active timestamp; no other PII | Internal | Until account deletion | Legitimate interest (presence indicator) | Firebase |
coachMaterials | owner user ID/name, folder hierarchy, file name/type/size/hash and storage object reference, HiringCoach Doc content/revision, sharing count, per-user stars, trash and created/updated timestamps; client-owned onboarding copies also retain source coach/material, relationship, run, block, and root-source IDs as provenance for deterministic replay and support | Confidential | Until owner account deletion or permanent deletion by the owner | Contract | Firebase, GCS for uploaded file bodies |
coachMaterials/{materialId}/materialCollaboration | canonical Yjs document state and state vector, schema version, collaboration epoch/clock, stored-byte count, updated timestamp | Confidential | Until owner account deletion or permanent deletion of the material; one current state row per collaborative document | Contract | Firebase |
coachMaterials/{materialId}/materialRevisions | immutable document HTML/plain text snapshots, revision and operation metadata, contributor display names/user IDs and count, checkpoint creator identity, restored-from revision, stored-byte count, created timestamp | Confidential | Up to the latest 100 revisions, then pruned; also removed on owner account deletion or permanent deletion of the material | Contract, legitimate interest (version recovery and edit audit) | Firebase |
coachMaterials/{materialId}/materialOperations | hashed idempotency record, actor user ID, operation type/request hash, base/result revision, collaboration epoch, created timestamp | Internal / Confidential | Up to the latest 200 revision-linked operations, then pruned; also removed on account or material deletion | Legitimate interest (write deduplication and integrity) | Firebase |
coachMaterials/{materialId}/materialPresence | opaque participant/session IDs, actor user ID/display name, owner/permission flags, cursor anchor, last-seen and expiry timestamps | Confidential | Ephemeral; 45-second application expiry, capped at eight active browser sessions per collaborator; access is denied immediately after revocation and stale rows expire within 45 seconds; rows are removed on leave, account deletion, or material deletion | Contract, legitimate interest (realtime collaboration presence) | Firebase |
coachMaterialShares | material/owner/recipient user IDs, coach-relationship ID, recipient name/email, viewer/commenter/editor permission, grant/revocation timestamps; purchase-scoped public-offer access grants containing intent/purchase/offer/snapshot provenance, sealed material artifact binding, status, grant type, and optional accessExpiresAt | Confidential | Until owner or recipient account deletion, or permanent deletion of the material; revoked or expired grants remain until one of those events for access and commercial audit integrity | Contract, legitimate interest (relationship-scoped access control, commercial artifact integrity, and revocation audit) | Firebase |
coachMaterialRecents | actor user ID, material ID, last-opened timestamp | Internal / Confidential | Until actor account deletion or permanent deletion of the material | Legitimate interest (recent-material navigation) | Firebase |
coachMaterialStorageUsage | owner user ID, aggregate bytes used, storage limit, updated timestamp | Internal | Until owner account deletion | Legitimate interest (quota enforcement) | Firebase |
coachMaterialRealtimeLeases | actor user ID, material ID, opaque lease-document ID, expiry and updated timestamps | Internal / Confidential | Firestore TTL after the 50-second lease window; eagerly removed on access revocation, account deletion, trash, move, or material deletion | Contract, legitimate interest (authorized realtime delivery) | Firebase |
coachMaterialRealtimeSignals | opaque per-material collaborator lease-document ID, monotonic document generation and targeted commentGeneration, expiry and updated timestamps; no document content or participant identity fields | Internal | Firestore TTL after the paired 50-second lease window; eagerly removed with the paired lease | Legitimate interest (metadata-only realtime invalidation) | Firebase |
coachAssignmentResponseTokens | hashed one-tap homework response token as document ID, relationship ID, coach and client user IDs, session workspace ID, the taskIds array the token may answer, the respondedTaskIds array already answered through it, created and expiry timestamps; no assignment content, no response value, and no plaintext token | Confidential | Firestore TTL on expiresAt (session start + 24h); the token stays usable for every task it names until then, so a client can revise an answer — it is not single-use | Contract, legitimate interest (login-free client responses) | Firebase |
coachAlumniStubs | coach-opt-in minimal alumni record created at close-out: client name and email, relationship ID, coach user ID, engagement completion date, employer/outcome tags, and a single goal line | Confidential | Until the coach deletes the stub or either participant account is deleted; created only by explicit coach opt-in at close-out | Consent (coach opt-in), contract, legitimate interest (coach recordkeeping) | Firebase |
coachClientPurgeSchedules | relationship and coach IDs, scheduled purge date for qualitative client content, retention-window setting, last-run and outcome metadata; no client content | Internal / Confidential | Until the scheduled purge completes, the relationship is deleted, or either participant account is deleted | Legitimate interest (retention enforcement), legal obligation where applicable | Firebase |
coachGeneratedInvoices | coach-generated reimbursement invoice metadata: invoice number, coach/relationship/engagement IDs, client name and billing address as entered by the coach, line items, amount and currency, issue/due dates, and document storage reference. No card or bank details. | Confidential | Seven years where applicable for financial recordkeeping; holds extend retention | Contract, legal obligation (tax and financial recordkeeping) | Firebase |
coachCircles | coach peer-circle membership: circle name and description, owner and member coach user IDs, member roles and join/leave timestamps. Client content shared into a circle is de-identified by convention. | Confidential | Until the circle is deleted or the coach account is deleted | Contract, legitimate interest (coach peer community) | Firebase |
coachCircleInvites | circle ID, inviting coach user ID, invited coach user ID or hashed invited email, invite state and expiry, response timestamps | Confidential | Until the invite is accepted, declined, or expires; removed with the circle | Contract, legitimate interest (coach peer community) | Firebase |
coachCircleRequests | circle and requesting coach user IDs, request kind (resource or peer consult), de-identified request body, status, responder coach user ID, timestamps | Confidential | Until the request is closed or the circle is deleted | Contract, legitimate interest (coach peer community) | Firebase |
coachIcfHourStubs | identity-light coaching-hour entry surviving client deletion: coach user ID, session date, minutes, and ICF category. No client name, email, or content. | Internal | Retained for the coach's credentialing evidence until the coach account is deleted; deliberately survives client deletion | Legitimate interest (coach credentialing evidence) | Firebase |
coachRelationships/{relationshipId}/privateContext | coach-only per-client context: values/motivators tags and the client's LinkedIn URL, coach user ID, timestamps. Never visible to the client. | Confidential | Until the coach hard-deletes the entry, the coach account is deleted, or the relationship is deleted | Contract, legitimate interest (coach recordkeeping) | Firebase |
coachRelationships/{relationshipId}/sharedLog | coach+client shared log entries: entry body, author role and user ID, timestamps. Separate from the coach-only private notes. | Confidential | Until the entry is hard-deleted or either participant account is deleted | Contract | Firebase |
Client onboarding
Server-only collections behind the CLIENT_ONBOARDING_RECIPES_ENABLED flag: a coach-authored recipe of onboarding steps (asset intake, agreement, payment, survey, homework, scheduling, and material delivery) assigned to an invited client and driven through a token-gated public wizard. All writes go through Admin-SDK server code (the coach recipe-builder API and the token-verified client wizard API); see firestore.rules.
| Collection | Fields | Classification | Retention | Lawful basis (GDPR) | Processors |
|---|---|---|---|---|---|
coachOnboardingRecipes | coach user ID, recipe name/description, the recipe archetype (V3 Workstream F — new_client or portal_intro; a coach-chosen audience label only, no client data, and a portal_intro recipe may not contain payment or agreement blocks), the recipe-level automated-reminder policy switch (reminders.enabled), ordered onboarding block configuration (asset, agreement, payment, survey, homework, scheduling, and material-delivery settings, each referencing a coach-owned contract template, public offer, intake-template version, or active coach-owned material; material delivery pins at most 50 source material IDs, bounded names and kinds, copy/shared mode, and any required cross-client editor-share warning acknowledgment, without storing the other client's identity; the survey block's mappings (Workstream E) additionally references up to 7 pinned survey field IDs used to auto-seed the client's career-plan narrative, north-star goal, and target-role entries during provisioning; field IDs only, never response content; plus Workstream D's coach-authored welcome_message rich-text body — HTML sanitized server-side at save, raw input/plaintext length-capped — and video block references, stored only as an allowlisted provider (YouTube/Vimeo/Loom) and video ID plus an optional title, never a raw URL or embed markup), plus the optional post-onboarding journey section (V3 Workstream B — a coach-owned program-template reference, up to 5 coach-owned course references, and up to 5 coach-authored follow-up message subject/body pairs with day offsets, fired when a run completes), recipe family/revision references, status, content hash, current published-version reference, version and operation metadata, and timestamps; the family-root entry additionally carries the family's live published recipe/version pointers and (V3) an optional experiment record for a revision A/B test — status, the two compared coach-owned recipe/version IDs, the start timestamp and the coach user ID who started it, never any client data; nested versions hold immutable published snapshots, and nested activity/operations record actor/action/replay metadata | Confidential | Until coach account deletion, or earlier when the coach archives/deletes the recipe; archived recipes remain until deletion so past assigned-run snapshots stay resolvable | Contract | Firebase |
clientOnboardingRuns/{runId} | coach and relationship IDs, client email and (once bound) client user ID, the assigned recipe's frozen name/description/block snapshot and content hash, ordered onboarding step statuses with per-step engine references (asset, agreement, payment-intent, intake-form, homework, scheduling-link, and material-delivery pointers); material-delivery refs retain bounded per-source copy/shared outcomes, delivered material IDs, non-sensitive failure reasons, and completion time for replay and support, provisioning results (per-item outcomes; Workstream E adds the survey-mapping outcomes — career-plan-narrative/goal/target-role-entry success, skip-with-reason, or error records referencing the created goal/target-entry ids only, never response content or field labels), the current active link's token hash and its expiry mirror (linkExpiresAt), a last-client-activity timestamp, the automated reminder-engine state (policy snapshot, invite cycle, per-send records with claim/send timestamps and outcome, next-due/stall-alert timestamps, pause/opt-out/exhaustion markers, and the self-service link-recovery cooldown timestamp; Workstream F adds a handoffInvite one-time delivery record — due/attempt/backoff state, sent timestamp, and last-error reason only, no send content; V3 Workstream D adds a smsSends claim ledger for the optional text-nudge channel — per-nudge invite cycle, reminder index, claim/send timestamps, and a sent/deferred/failed outcome with an error reason, capped at two records per run, holding no phone number and no message content), the post-onboarding journey outcome record (V3 Workstream B — a completion timestamp plus per-item results for the applied program template, granted course enrollments, scheduled follow-up messages, and the fired onboarding_completed form-automation trigger: referenced program-template/course/enrollment/send-timer IDs, planned send timestamps, and skip-reason or error strings only, never message or response content), version and operation metadata, and timestamps; nested operations record replay metadata, and nested legalAcceptances hold sealed click-accept clickwrap evidence (accepted contract-template/version, content hash, acknowledgment labels, hashed IP and user agent, acceptance operation ID, and platform seal) | Confidential; Restricted for the legalAcceptances sealed clickwrap evidence, matching sibling legal-acceptance records | Retained for the life of the coach-client relationship; sealed legalAcceptances evidence follows the applicable contract, limitations, or claims period plus holds like sibling legal-acceptance rows | Contract | Firebase |
clientOnboardingRuns/{runId}/legalAcceptances | sealed click-accept clickwrap evidence: accepted contract-template/version references, content hash, acknowledgment keys and labels, accepting client's user ID and email, hashed IP and user agent (never raw), acceptance operation ID, immutable evidence record with its hash and platform seal, and timestamps | Restricted | Follows the applicable contract, limitations, or claims period plus holds, like sibling legal-acceptance rows | Contract | Firebase |
clientOnboardingLinks | SHA-256 hash of the onboarding magic-link token as the document ID (the raw token is never stored or logged), scope, run/relationship/coach IDs, status, expiry, and revoke/create/update timestamps | Confidential | 14-day expiry + Firestore TTL policy on expiresAt | Contract | Firebase |
coachOnboardingRecipeStats/{recipeFamilyId} | Coach user ID, recipe family ID, and aggregate funnel counters only: invited/started/accepted/finished/abandoned counts, per-block-type completion counts, a per-step abandonment-count breakdown, an approximate completion-time duration histogram plus its sum/count, a parallel revisions.<recipeVersionId> map repeating that same counter set per published recipe revision (V3 per-revision funnels, keyed by the immutable version ID each run was assigned), and timestamps. No client identifiers, emails, names, run IDs, or other per-client detail — every counter is a coach/family-level rollup written by FieldValue.increment inside the same transaction that mutates the underlying run. | Confidential | Until coach account deletion | Legitimate interest (coach onboarding funnel/practice reporting, aggregate-only) | Firebase |
Contacts and follow-ups
| Collection | Fields | Classification | Retention | Lawful basis (GDPR) | Processors |
|---|---|---|---|---|---|
users/{uid}/contacts | name, email, phone, LinkedIn URL, notes, lastContacted | Confidential | Until account deletion | Contract | Firebase |
users/{uid}/coffeeChats | saved networking-preparation session name and goals; linked contact ID/name; invitation, questions, introductions, insights, and follow-up drafts; role, industry, location, experience, search inputs, editable outreach copy, and timestamps | Confidential | Until the user deletes the saved session or the account is deleted; legal holds may extend retention where applicable | Contract; legitimate interest in delivering and recovering the user's saved coaching workspace | Firebase |
users/{uid}/contactLinks | per-contact relationship metadata | Confidential | Until account deletion | Contract | Firebase |
users/{uid}/followUps | scheduled follow-ups per contact | Confidential | Until account deletion | Contract | Firebase |
users/{uid}/coffeeChats | coffee-chat preparation sessions: person/company, discussion goals, research inputs, invitation and follow-up drafts, questions per goal, linked contact, timestamps | Confidential | Until account deletion | Contract | Firebase, OpenAI (question/invitation generation) |
users/{uid}/followUpReminders | reminder records for follow-ups | Confidential | Until account deletion | Contract | Firebase |
Integrations (LinkedIn, OAuth-based imports)
| Collection | Fields | Classification | Retention | Lawful basis (GDPR) | Processors |
|---|---|---|---|---|---|
users/{uid}/integrations | per-integration tokens / configuration | Restricted | Until account deletion or revocation | Consent | Firebase |
users/{uid}/linkedIn | LinkedIn profile snapshot, last sync, scope | Confidential | Until account deletion | Consent | Firebase, LinkedIn |
users/{uid}/linkedinJobExports | LinkedIn job-search exports | Confidential | Until account deletion | Consent | Firebase, LinkedIn |
users/{uid}/linkedinProfileExports | LinkedIn profile exports | Confidential | Until account deletion | Consent | Firebase, LinkedIn |
linkedinCookies | uid, liAt (AES-256-GCM encrypted), createdAt, expiresAt | Restricted | TTL 1 h (configurable), or until revoke | Consent | Firebase |
Subscriptions and feedback
| Collection | Fields | Classification | Retention | Lawful basis (GDPR) | Processors |
|---|---|---|---|---|---|
subscriptions | userId, stripeCustomerId, stripeSubscriptionId, status, created, updated | Confidential | Until account deletion + 7 y for tax records | Contract, legal obligation | Firebase, Stripe |
subscriptionHistory | per-user subscription lifecycle events | Confidential | 7 y (tax / billing audit) | Legal obligation | Firebase, Stripe |
heldConsumerSubscriptions | one active hold per user: hold status, source relationship ID, held-plan snapshot (price/plan/product IDs, tier, gift/premium-until fields), paid-through timestamp, hold kind, Stripe subscription/customer IDs of the canceled subscription, resume outcome, consent timestamp/hashed user-agent | Confidential | Until account deletion + 7 y for tax records | Contract, legal obligation | Firebase, Stripe |
subscriptionTransitionOps | server-only exactly-once operation locks for the coach-access subscription hold/resume engine: lock key, operation type/status, lease metadata, retry count, redacted error fields | Internal / Confidential | Until account deletion | Legitimate interest (idempotent billing operations) | Firebase |
coachBillingGraceEvents | one open grace record per coach whose own HiringCoach Plan billing lapsed while they have active clients: status, opened/grace-end timestamps, billing-lapse cause, last daily-email date key, resolution | Confidential | Until account deletion | Contract, legitimate interest (coach billing-lapse client-access grace window) | Firebase, SendGrid/Gmail for the daily coach email |
adminBillingActionAudit | adminEmail, userId, userEmail, refund request details, Stripe refund/subscription references, cancellation and migration results, currentPriceId, createdAt | Confidential | 7 y (billing audit / tax support) | Legal obligation, legitimate interest (billing support and fraud prevention) | Firebase, Stripe |
feedback | user-submitted product feedback (often includes free-text) | Confidential | Until account deletion | Legitimate interest | Firebase |
aiOutputFeedback | thumbs up/down on AI outputs, optional comment | Confidential | Until account deletion | Legitimate interest | Firebase |
coachLeadSubmissions | name, email, phone, website, plan interest, cohort rationale free-text answer, source/UTM metadata, referrer/user-agent, Sheet sync status, owner notification status | Confidential | 2 years, or until deletion request | Consent, legitimate interest (coach partner intake and sales follow-up) | Firebase, Google Workspace / Sheets, SendGrid or Gmail |
renewalReminders | one idempotency record per Stripe subscription per renewal period, keyed by stripeSubscriptionId (or uid) and currentPeriodEnd: uid, email, priceId, planPeriod (annual/quarterly), currentPeriodEnd, status (queued/sent/skipped_unsubscribed/skipped_no_email/failed), campaignId, error, createdAt, updatedAt | Confidential | Until account deletion + 7 y for tax records (mirrors subscriptions) | Contract, legitimate interest (renewal communications) | Firebase, Mailchimp for the reminder campaign |
adminMarketingEmailTemplates | one fixed override document (id renewalReminder) holding the marketing-admin-edited renewal-reminder campaign content: subjectLine, previewText, html, updatedAt, updatedBy (admin uid). No customer personal data; the effective template it produces is what the renewalReminders cron sends via Mailchimp | Internal | Until an admin clears the override | Legitimate interest (marketing-admin management of the renewal-reminder email template) | Firebase |
Referral program
Server-only collections behind the REFERRALS_ENABLED flag (docs/referral-program.md). All writes go through Admin-SDK server code (the claim endpoint, the Stripe webhook reward engine, and /api/admin/referrals); see firestore.rules and __tests__/rules/referralRules.rules.test.js for the enforced access model.
| Collection | Fields | Classification | Retention | Lawful basis (GDPR) | Processors |
|---|---|---|---|---|---|
referralCodes | code, ownerUserId, active, createdAt | Confidential | Until account deletion | Contract, legitimate interest (program operation) | Firebase/GCP |
referrals | referredUserId, referrerUserId, code, status, attributedAt; salted claim.ipHash/claim.userAgentHash (raw IP/user-agent never stored) and claim.signupAgeMs; conversion Stripe references (subscription/customer/invoice/payment-intent/charge IDs, amount paid, currency, billing reason, event ID, paid-at timestamp, card fingerprint); abuse flags and evaluation detail; clawback and adminAction records; createdAt, updatedAt | Confidential | Until account deletion + audit retention | Contract, legitimate interest (fraud prevention) | Firebase/GCP; Stripe for conversion references |
referralStats | referrerUserId, code, counters (totalAttributed, totalConverted, totalRewarded, totalHeld, totalDenied, totalClawedBack), rewardGrantTimestamps (rolling annual cap math), createdAt, updatedAt | Confidential | Until account deletion | Contract | Firebase/GCP |
Affiliate program (cash channel)
Server-only collections. Acquisition, admin, Connect, and payout surfaces are behind AFFILIATES_ENABLED; connected-account provisioning is separately behind AFFILIATES_CONNECT_ENABLED, and cash execution requires both AFFILIATES_PAYOUTS_ENABLED and the approved/versioned/current-year server tax-configuration attestation (lib/affiliates). Signed Stripe refund/dispute processing deliberately remains active for existing commissions when acquisition is disabled. All writes go through Admin-SDK server code (the apply/claim/residence endpoints, the Stripe webhook commission engine, /api/admin/affiliates/*, and the payout engine); every collection is deny-all to clients in firestore.rules and is read only through sanitized server APIs.
| Collection | Fields | Classification | Retention | Lawful basis (GDPR) | Processors |
|---|---|---|---|---|---|
affiliateCodes | code, active owner binding, active, createdAt, account-deletion deactivation metadata | Confidential | Deactivated before account access is removed. The direct owner identifier is removed on deletion, while an inactive code tombstone remains reserved with the affiliate financial record for tax/audit reconciliation. | Contract, legitimate interest (program operation and payout reconciliation) | Firebase/GCP |
affiliateProfiles | affiliateUserId, status; application text (website, audienceDescription, promotionPlan, US-residency attestation, application-time usState); current residence declaration (residencyStatus, nullable stateCode, monotonic declarationVersion, declaredAt); terms acceptance (timestamp, document id, document version, salted ipHash; raw IP never stored); code; earnings counters (totalAttributed, totalConverted, totalHeld, totalEarnedCents, totalReversedCents, totalPaidCents); stripeConnectedAccountId and Connect readiness state; bounded payoutCompliance review and history (schema/policy/review IDs, opaque configuration version, tax year, connected-account binding, reviewed state, residence-declaration version, enumerated identity/withholding/state statuses, recorded admin authority policy, admin user ID, review timestamps, and residence-change invalidation metadata); adminDecision; bounded for-cause suspension state (accountNotice: kind, cause, active/resolved state, the admin's bounded 10-2000 character notice text shown to the affiliate, issuing admin user ID and authority policy, issued/response-due/responded/resolved timestamps, response status; suspensionResponse: the affiliate's own bounded 10-4000 character text, submission timestamp, status) issued by /api/admin/affiliates/applications (action issue_notice; resolved when the affiliate is reinstated) and answered once through /api/affiliates/notice-response; payoutRecovery (status, outstandingCents, affected commission IDs, reason, timestamps) when a completed transfer's underlying charge is later refunded or disputed; account-deletion privacyLifecycle, including bounded Stripe Connect cleanup status when a concurrent unused account requires assisted deletion and a bounded assistedSettlement inventory (status, aggregate unresolved earned/held/processing counts and cents, truncation flag, retention policy, timestamps, and the account's normalized retainedContactEmail only while an unpaid obligation remains); createdAt, updatedAt. Names, tax identifiers, tax-form content, bank details, identity documents, withholding amounts/rates, and free-text tax notes are not stored; Stripe holds onboarding identity/tax/bank data. | Confidential | Deletion first marks and transactionally fences the affiliate, disables public codes, converts approved standing to closed while preserving other standing, redacts application and non-retained reviewer identity, revokes ordinary access, and continues deleting ordinary product/authentication data even when an EARNED, HELD, or processing obligation remains — those are amounts owed TO the affiliate, retained via the bounded assisted-settlement inventory below. Account deletion is instead BLOCKED (fails closed, no product/authentication data removed) while payoutRecovery.status is outstanding: that liability is money already transferred to the affiliate for a charge later refunded or disputed, owed BACK to HiringCoach, and it must be reconciled (an admin resolve_recovery action) before deletion can proceed. Only bounded financial evidence and the restricted pending assisted-settlement inventory and minimum contact remain until resolution. Self-service Connect and ordinary compliance mutation stay fenced. For that exact pending closed or suspended case, a trusted-origin fresh interactive admin may create or resume live Stripe onboarding and record bounded payout compliance; the strict route returns a hosted Account Link and retainedContactEmail only after its final access recheck and does not send a message or move cash. A fresh interactive admin may adjudicate HELD for either supported standing; closed approval leaves the case pending as EARNED, while suspended approval or explicit authorization stamps only the reviewed EARNED commission with an immutable version-1 pay disposition. Ordinary suspended balances remain ineligible. A bounded refresh deletes retained contact and purpose when all obligations resolve. Terms, counters, residence, Connect binding, payout-compliance review/history, suspension-notice/response evidence, and accountable reviewer evidence remain only for settlement, tax reporting, reconciliation, fraud review, and audit retention. | Contract, legal obligation (tax reporting), legitimate interest (fraud prevention and payout-integrity evidence) | Firebase/GCP; Stripe for payout accounts, hosted identity/tax/bank collection, and tax-reporting capability |
affiliateReferrals | While the referred account is active: referredUserId, affiliateUserId, code, status, attributedAt, convertedAt; salted claim.ipHash/claim.userAgentHash (raw IP/user-agent never stored) and claim.signupAgeMs; bounded terminal outcome reason/event/timestamp only when beneficiary-account deletion consumes an old non-redacted attribution; createdAt, updatedAt. Referred-customer deletion removes referredUserId, code, and claim while retaining the immutable document key, affiliateUserId, status/timestamps, and exact privacyLifecycle (referredAccountDeleted, first referredAccountDeletedAt, equal inclusive paymentCutoffAt, claimRedacted, and affiliate-financial-record-retention-v1). Post-cutoff invoice evaluation is a deterministic no-write skip, so the attributed tombstone remains available for a delayed at-or-before-cutoff Stripe payment. | Confidential | Active attribution until conversion or deletion; a referred-customer tombstone and any resulting financial trace follow the affiliate financial-record period, up to seven years where applicable plus legal holds. | Contract, legitimate interest (fraud prevention and financial idempotency), legal obligation or claims for retained financial evidence | Firebase/GCP |
affiliateCommissions | Ordinary records: referredUserId, affiliateUserId, code, status, commission amounts (amountCents, rateBps, USD-only currency), conversion Stripe references (subscription/customer/invoice/payment-intent/charge/price IDs, amount paid, currency, billing reason, event ID, live/test mode, paid-at timestamp, card fingerprint) and authoritative chargeVerification; earnedAt; bounded abuse, partial-refund, paid-reversal, pending-reversal/manual-reconciliation, payout, reversal, and admin-action evidence; a paid commission whose qualifying charge is later refunded or disputed also carries paidReversalRecovery (schema version, outstanding/resolved status, recordedCents, reason, event ID, timestamp) mirroring the affiliate-profile-level payoutRecovery liability it opens; optional immutable assistedSettlementDisposition; timestamps. For a deleted referred account, the commission omits referredUserId and code, clears abuse detail, copies the exact five-field referral privacyLifecycle, and limits conversion to invoiceId, paymentIntentId, chargeId, priceId, amountPaidCents, currency, billingReason, eventId, livemode, paidAt, and bounded chargeVerification. Both EARNED/HELD creation and a pre-accrual terminal REVERSED record use this sanitizer. A non-USD Stripe invoice returns currency_mismatch and creates no commission or payable state. | Confidential | Affiliate financial-record period, up to seven years where applicable plus legal holds; direct referred-customer fields are removed during deletion while the minimum reversible financial trace remains. | Contract, legal obligation (tax reporting), legitimate interest (fraud prevention, reversal integrity, and financial idempotency), establishment or defense of claims | Firebase/GCP; Stripe for conversion and transfer references |
affiliateChargeReversalMarkers | Server-only schema-versioned record keyed by canonical Stripe chargeId: livemode; terminal flag/reason and bounded terminalEvidence; bounded latestPartialRefundEvidence; rolling last-20 eventEvidence entries containing event ID/type, enumerated reason, charge/refund amounts, Stripe-created time, and recorded time; eventEvidenceCount, chained SHA-256 eventEvidenceDigest, eventEvidenceOverflowed, evidenceCapacity, candidateCoverageOverflow, manualReconciliationRequired, createdAt, updatedAt. It contains no user ID, email, raw IP, tax data, or bank data. candidateCoverageOverflow is a server-only global cash block: preview, claim, resume, and final transfer fences fail closed until manual reconciliation clears the marker. | Restricted financial-integrity evidence | Retained with the related commission/refund/dispute record for the affiliate financial-record period, up to seven years where applicable plus legal holds. It is excluded from the self-service affiliate export because it is charge-keyed and has no safe user binding; a requester may match it only by a verified Stripe charge reference through the assisted DSR process. | Contract, legal obligation where applicable, legitimate interest (out-of-order reversal integrity, replay prevention, and reconciliation), establishment or defense of claims | Firebase/GCP; Stripe identifiers only |
affiliatePayouts | payoutId, affiliateUserId, payoutMode (normal or scoped settlement), nullable settlementProfileStatus, status, amountCents, USD-only currency, commissionIds, bounded per-commission assistedSettlementDispositions snapshots for a suspended settlement, Stripe destination account and transferId, createdBy admin ID; expectedPreviewToken; bounded hashed stripeIdempotencyKey; executionControlVersion and bounded executionAttempt (token, acquiredByAdminUserId, acquiredAt, expiresAt); transferFenceVersion, transferStartedAt, and transferLastAuthorizedAt; immutable bounded payoutCompliance snapshot; reconciliation records (flippedCents, skippedCommissionIds, paidDespiteReversalIds, reversedOnReleaseIds, error); created/updated/paid/failed timestamps. No tax identifier, form, bank detail, identity document, withholding amount/rate, or free-text tax note is copied into a payout. The preview token binds mode, target, reviewing admin, exact sorted eligible and same-mode processing commission sets, currency, destination, compliance, settlement standing, and disposition snapshots. Processing remains exact-mode and settlement exact-target. A suspended settlement must remain deletion-fenced and pending, and every selected EARNED commission must retain its exact valid version-1 pay disposition; ordinary suspended balances are not eligible. Currency/status/disposition/config fences are rechecked at preview, claim, lease/resume, and immediately before transfer. After the transfer fence, network/5xx uncertainty keeps claims held and, after the execution lease expires, requires manual Stripe reconciliation; it is not automatically replayed or released. | Confidential | Tax/audit retention (financial record) | Contract, legal obligation (tax and financial records), legitimate interest (payout integrity, replay prevention, and reconciliation) | Firebase/GCP; Stripe for transfers |
affiliateConnectAccounts | Server-only registry keyed by Stripe connected-account ID, binding it to exactly one affiliateUserId: registryVersion, accountId, affiliateUserId, kind, a bindingFingerprint derived from the account/affiliate pair (ownership-collision detection only, not independently meaningful), createdAt, lastConfirmedAt. No identity, tax, or bank data; Stripe holds that. | Confidential | Same lifecycle as the owning affiliateProfiles document; retained alongside it for Connect-account reconciliation. | Contract, legitimate interest (preventing one Stripe account from being claimed by more than one affiliate) | Firebase/GCP; Stripe for the connected account itself |
affiliatePayoutAuditEvents | Server-only, append-only evidence for admin-initiated payout reconciliation (lib/affiliates/payoutEngine.js reconciliation surface): schemaVersion, payoutId, affiliateUserId, payoutMode, amountCents, currency, enumerated action (complete_existing, release_no_transfer, retry_same_request, hold_returned_liability), admin actorUserId, optional admin note, evidence (live Stripe transfer evidence gathered before the decision), createdAt. The self-service affiliate export includes only action and createdAt per event; admin identity, notes, and evidence are excluded. | Restricted financial-integrity evidence | Retained with the related payout for the affiliate financial-record period, up to seven years where applicable plus legal holds. | Contract, legal obligation where applicable, legitimate interest (payout reconciliation integrity and audit evidence) | Firebase/GCP; Stripe for transfer evidence |
affiliateBankPayouts | Reserved: no writer exists on this branch yet (Stripe's transfer-to-bank tracking is unbuilt). Once a writer ships, the documented shape is a Stripe-payout-keyed record with affiliateUserId, status, amountCents, USD-only currency, providerCreatedAt/arrivalAt/paidAt/failedAt/canceledAt, and matched-transfer references — no bank account number or routing detail (Stripe holds that). lib/affiliates/paymentStatement.js and lib/affiliates/privacyLifecycle.js already read this collection tolerantly (an absent/empty collection simply contributes no rows) so both the Payments-tab ledger and the self-service export activate automatically the day a writer ships. | Confidential | Same retention as affiliatePayouts once populated. | Contract, legal obligation (tax and financial records) | Firebase/GCP; Stripe for the underlying bank payout |
Pilot / group programs (per-user data within a sponsor program)
| Collection | Fields | Classification | Retention | Lawful basis (GDPR) | Processors |
|---|---|---|---|---|---|
pilotMemberships | userId, pilotId, email, display name, role/status, cohort tags/subgroups, invitation/activation/removal timestamps | Confidential | Identifying fields until account deletion; anonymized program participation retained until program end | Contract, legitimate interest | Firebase |
pilotAdmins | userId, pilotId, role, permission overrides, status, invite/grant/revocation timestamps | Confidential | Until program end or access revocation + audit retention | Contract, legitimate interest | Firebase |
pilotSessions | userId, membershipId, sessionId, start/end/heartbeat timestamps, active/idle/engaged duration, page-view and action counters, features/page groups used, entry/exit paths, device/browser metadata | Confidential | Identifying fields until account deletion; anonymized usage retained until program end | Contract, legitimate interest | Firebase |
pilotEvents | userId, membershipId, sessionId, event name/category/feature, page path/route/referrer, timestamp, duration/count values, platform/device/browser/user-agent, event properties | Confidential | Identifying fields until account deletion; anonymized usage retained until program end | Contract, legitimate interest | Firebase |
pilotUserDailyRollups | userId, membershipId, date, session count, active duration, meaningful-action count, feature-usage counts, page views, last-active timestamp | Confidential | Identifying fields until account deletion; anonymized usage retained until program end | Contract, legitimate interest | Firebase |
pilotGoals | program-level goals and targets | Internal / Confidential | Until program end | Contract | Firebase |
pilotInterventions | coach interventions logged per user | Confidential | Until program end | Contract | Firebase |
therapistSessions | session metadata for coaching engagements | Confidential | 7 y (record retention) | Legitimate interest | Firebase |
Account-deletion ledgers
| Collection | Fields | Classification | Retention | Lawful basis (GDPR) | Processors |
|---|---|---|---|---|---|
deleted_users | deletedUid, normalizedEmail, displayEmail, userName, status, deletionReason, content-count summary, billingCleanupStatus | Confidential | Name/email up to 30 d after deletion; remaining audit metadata 365 d | Legitimate interest (responding to deletion feedback, deletion confirmation, security, billing reconciliation, legal claims) | Firebase |
deleted_account_snapshots | full user doc + subscription snapshot + content inventory | Restricted | 30 d recovery window | Legitimate interest | Firebase |
deleted_account_feedback | userId, feedbackReason, feedbackNotes | Internal | 365 d | Legitimate interest (product improvement) | Firebase |
Audit and security ledgers
| Collection | Fields | Classification | Retention | Lawful basis (GDPR) | Processors |
|---|---|---|---|---|---|
auditLog | ts, actorUid, actorRole, ip, userAgent, action, resourceType, resourceId, delta, tenantId, requestId | Confidential | 2 years | Legal obligation (security), legitimate interest (forensics) | Firebase |
adminBillingActionAudit | admin email, target user ID/email, refund mode, requested charge/amount, refund IDs/status, Stripe charge/payment intent/subscription IDs, migration/archive flags, price ID, createdAt | Confidential | 7 y (billing audit / tax support) | Legal obligation, legitimate interest (billing integrity and forensics) | Firebase, Stripe |
adminPaidPlanAdjustmentAudit | admin user ID/email, target user email or plan cohort, plan ID, requested end timestamp, updated/skipped/error counts, createdAt | Confidential | 7 y (billing audit / tax support) | Legal obligation, legitimate interest (billing integrity and forensics) | Firebase |
adminPlanCatalogImportAudit | admin user ID/email, imported-plan count, error count, createdAt | Confidential | 2 years | Legitimate interest (administrative change control and forensics) | Firebase |
adminPlanMutationAudit | operation ID/fingerprint, action/method, target plan document and price ID, admin actor user ID/email and assurance evidence, before/after plan values, createdAt | Confidential | 7 y (billing audit / tax support) | Legal obligation, legitimate interest (billing integrity, change control, and forensics) | Firebase |
adminPlanConflictRepairAudit | admin user ID/email, repair mode, updated/skipped/error counts, createdAt | Confidential | 7 y (billing audit / tax support) | Legal obligation, legitimate interest (billing integrity and forensics) | Firebase |
adminSubscriptionFieldMigrationAudit | admin user ID/email, total/updated/skipped/error counts, createdAt | Confidential | 7 y (billing audit / tax support) | Legal obligation, legitimate interest (subscription integrity and forensics) | Firebase |
adminSubscriptionMigrationAudit | admin user ID/email, old and new user IDs/emails, Stripe subscription/customer IDs, prior-subscription indicator, createdAt | Confidential | 7 y (billing audit / tax support) | Legal obligation, legitimate interest (billing integrity and forensics) | Firebase, Stripe |
adminSubscriptionOverwriteAudit | admin user ID/email, target user ID/email, replacement plan ID, createdAt | Confidential | 7 y (billing audit / tax support) | Legal obligation, legitimate interest (billing integrity and forensics) | Firebase |
adminCoachActions | action type, admin actor user ID/email, coach user ID, relationship ID, target client user ID, summary, reason/metadata, timestamp | Confidential | 2 years | Legitimate interest (coach access administration, security, and billing audit) | Firebase |
adminInvoices | admin-created invoice records: invoice number, status, issue/due dates, bill-to name/company/email/address, from (business) name/address/email/phone/website snapshot, line items (description, quantity, unit amount), tax rate, discount, computed totals, currency, notes, payment instructions, and creator admin email. No card or bank details. | Confidential | Seven years for financial recordkeeping | Contract, legal obligation (tax and financial recordkeeping) | Firebase |
adminInvoicePayees | saved invoice recipients reused across invoices: name, company, email, billing address, and creator admin email. No card or bank details. | Confidential | Seven years for financial recordkeeping | Contract, legal obligation (tax and financial recordkeeping) | Firebase |
securityAuditMonitorRuns | runId, timestamps, lookback window, reviewed-event count, finding type/severity/count, hashed actor/IP/resource identifiers, retention expiry | Confidential | 365 days | Legitimate interest (security monitoring, compliance evidence) | Firebase, Sentry for finding notifications |
aiCallAudit | uid, endpoint, model, promptHash, tokensIn, tokensOut, requestedAt, durationMs, piiDetected | Confidential | 1 year | Legitimate interest (AI governance) | Firebase |
complianceTrainingLog | signerUid, signerEmail, signerName, document title/path/hash/version, signed statement, acknowledgment method, IP, user-agent, timestamp | Confidential | 7 years after access relationship ends | Legal obligation (compliance evidence), legitimate interest (security governance) | Firebase |
users/{uid}/complianceAcknowledgments | latest per-person/per-document onboarding acknowledgment rollup, latest log ID, document metadata, signer identity, timestamp | Confidential | 7 years after access relationship ends | Legal obligation (compliance evidence), legitimate interest (security governance) | Firebase |
complianceDocumentReviewLog | reviewer UID/email/name, document title/path/hash/version, review cadence, scheduled window, notes, timestamp | Confidential | 7 years | Legal obligation (compliance evidence), legitimate interest (security governance) | Firebase |
complianceDocumentReviews | latest per-document review rollup, latest log ID, reviewer identity, document metadata, cadence, scheduled window, notes | Confidential | Superseded by latest review; retained in complianceDocumentReviewLog for 7 years | Legal obligation (compliance evidence), legitimate interest (security governance) | Firebase |
compliancePatchVerificationRuns | reviewer UID/email/name, repository, check status, Dependabot PR/alert summaries, SBOM status, notes, timestamp | Confidential | 7 years | Legal obligation (compliance evidence), legitimate interest (security governance) | Firebase |
compliancePatchVerification | latest monthly patch-verification rollup, latest passing run timestamp, latest check status, reviewer identity | Confidential | Superseded by latest run; retained in compliancePatchVerificationRuns for 7 years | Legal obligation (compliance evidence), legitimate interest (security governance) | Firebase |
Hiring pipeline (careers job postings and applicants)
| Collection | Fields | Classification | Retention | Lawful basis (GDPR) | Processors |
|---|---|---|---|---|---|
hiringJobs | job posting metadata: slug, title, workflow state, employment type, location, authoring/last-editing admin email, HR/Legal sign-off stamps (admin email, timestamp, revision), latest AI-review revision markers, state-transition ledger (admin email, timestamp, note, review-gate override flag), lifecycle timestamps | Internal / Confidential (admin identities) | Until admin deletion; Archived is the normal terminal state; hard delete is refused while applications exist | Legitimate interest (recruiting operations) | Firebase |
hiringJobs/{jobId}/versions | versioned job-description content (section HTML, compensation disclosure, location, employment type), authoring admin email, change summaries, submission timestamps | Internal / Confidential (admin identities) | With the parent job | Legitimate interest (recruiting operations) | Firebase, OpenAI (JD generation and revision; per-request store: false) |
hiringJobs/{jobId}/reviews | AI HR/Legal review findings against a JD version (summary, issues, severity), model name, creator admin ID | Internal | With the parent job | Legitimate interest (recruiting operations) | Firebase, OpenAI (review generation; per-request store: false) |
hiringJobs/{jobId}/applications | careers-site applicant records: name, email, phone, LinkedIn URL, resume link or stored-file reference, cover note, triage status, status-change history (acting admin email, timestamps), admin-only screening notes with attribution, latest candidate decision-email record (subject, full reviewed body, sending admin, status, timestamp) | Confidential (applicant PII) | Minimum 4 years from application date or related personnel action; litigation holds retained until lifted (mirrors the applicant-records retention row). Individual applications (doc + stored resume) are deletable via the admin inbox to service privacy requests. | Legitimate interest (recruiting), legal obligation (recruiting record-keeping) | Firebase, Google Workspace / Gmail (careers@ team notice and candidate emails), OpenAI (candidate status-email drafting and HR/Legal review; per-request store: false) |
Non-Firestore data (sub-processors and external systems)
This section is the data-map projection of the sub-processors; both are kept in sync by the automated data-map audit.
Core infrastructure
| System | Data | Classification | Retention | |
|---|---|---|---|---|
| Google Cloud Platform / Firebase | Authentication, Firestore database content (all rows above), Cloud Storage objects for account documents, resume binaries, coach/client materials, chat attachments, coach profile images, and private coach credential-evidence images, Cloud Tasks payloads, Cloud Text-to-Speech inputs, backup/export buckets, and Cloud Functions source buckets. | Confidential (inherits source) | Until account deletion or owner deletion (live user content); Firestore PITR retains 7 days; managed Firestore backups retain 98 days | |
| Vercel | Application hosting, Edge Middleware, Serverless Function inputs, AI Gateway routing, platform logs, and consented site analytics with pageview query strings/fragments removed before send. New public booking and booking-management URLs expose only a non-authorizing link ID in the request path; the raw credential is exchanged through a private, no-store same-origin request body and is not placed in the path or query. | Internal / Restricted where a function input carries a short-lived credential | Vendor retention for runtime/platform logs; enabled log drain sends selected production/preview log sources to Sentry | |
| Cloudflare | Public DNS, reverse proxy, CDN/security edge for hiringcoach.ai | Internal / Confidential if request metadata includes user identifiers | Per Cloudflare defaults | |
| Firestore backups | Firestore PITR, managed daily Firestore backups, manual local Firestore JSON export tooling, and the US multi-region backup/export bucket | Confidential (inherits source) | PITR: 7 days; managed daily Firestore backups: 98 days; primary export bucket: 90-day soft delete; local exports: 30 days target | |
| Domain registrar / DNS | Domain registration metadata, DNS records | Internal | Until domain transfer or expiry | |
| GitHub | Source-code hosting, CI runs, deploy artifacts | Internal | Per repository policy | |
| Browser IndexedDB (user device) | user- and material-namespaced canonical Yjs document cache plus an unsynced recovery update used for offline editing and version-reset recovery | Confidential (inherits document content) | Canonical cache remains on that browser until access loss, material deletion, browser-site-data clearing, or storage eviction; recovery state is cleared after successful synchronization or explicit dismissal and is isolated by authenticated user ID | Contract, legitimate interest (offline editing and recovery) |
| Browser booking-capability cookie (user device) | Signed version, non-authorizing link ID, booking or management scope, issued/expiry times, and optional hashed email-verification reference. The cookie is HttpOnly and contains no raw booking bearer, client details, or calendar data. | Restricted | Up to 4 hours or the underlying link's earlier expiry; browsers may clear it sooner. The server rechecks the underlying link's current expiry, use, and revocation state on every operation. |
Payments and email
| System | Data | Classification | Retention |
|---|---|---|---|
| Stripe | Card tokens, customer IDs, payment intents, invoices, subscription events | Restricted (tokens); Confidential (customer IDs) | Per Stripe's policy; we hold only identifiers |
| SendGrid (Twilio) | Transactional email recipient/sender addresses, subject and message body (including user communication content or a profile-review snapshot included in an email), and send, event, bounce, and complaint records | Confidential | Message bodies are processed transiently for delivery; most event data expires within 37 days and some pseudonymized event data may be retained by the provider for up to 1 year for security, fraud, anti-abuse, and network protection |
| Mailchimp (Intuit) | Email, name, account/customer communication status, marketing-email preferences where applicable | Confidential | Until unsubscribe or suppression |
| Google Workspace / Gmail (transactional and support communications) | Sender/recipient addresses, subject, message body, reply and routing metadata, and profile-review content sent to the administrative mailbox | Confidential | Per applicable mailbox and legal-record retention settings |
| Google Workspace / Sheets (coach lead intake) | Career coach lead submissions from /coach, including contact details, practice details, client-count range, coaching focus, plan interest, free-text message, and source/UTM metadata. | Confidential | 2 years, or until deletion request |
| Google Workspace / Sheets (testimonials) | Submission timestamp, name, email, testimonial text, name/LinkedIn publication permissions, and case-study interest | Confidential until published with permission | Until deletion request or manual removal; no automated retention schedule is currently configured |
Applicant and intern records
| System | Data | Classification | Retention |
|---|---|---|---|
| Google Workspace / Gmail (hiring and accommodations mailboxes) | Resume, work samples, written application materials, hiring-contact correspondence, scheduling details, interview notes, and accommodation requests submitted to [email protected]. Accommodation requests are stored separately from hiring decision records and are not used in hiring decisions. | Confidential; Restricted where accommodation requests include disability, health, or other sensitive information | Minimum 4 years from application date or related personnel action; litigation holds retained until lifted |
| Google Cloud Storage (private hiring-resumes bucket) | Applicant resume files uploaded from /careers (PDF/DOC/DOCX, magic-byte validated) stored under hiring/{jobId}/applications/{applicationId}/ in a dedicated private bucket (public access prevention enforced); served only through the admin-gated streaming endpoint — no public URLs | Confidential (applicant PII) | Deleted with the parent application/job; the 4-year applicant-record retention above applies while the role's records are retained |
AI / generation providers
| System | Data | Classification | Retention |
|---|---|---|---|
| OpenAI (called both directly and via Vercel AI Gateway) | Generative-AI prompts and completions; coach profile text, link fields, and profile photos submitted for moderation; ephemeral Journey Narrative generation from bounded shared relationship evidence; Coach Thought Partner prompts may include assessment and private relationship evidence only when the coach explicitly enables that context; Assignment Ideation prompts may include active technique/template content and safe session content | Confidential (input); generated output is HiringCoachAI-owned | Covered calls use per-request store: false; this does not claim zero retention. No Zero Data Retention (ZDR) amendment: OpenAI's then-current standard API retention windows apply. |
| Perplexity AI | Research-backed search prompts | Confidential | Standard API terms; provider default retention applies. |
| ElevenLabs | Text-to-speech audio output | Confidential | Standard API terms; provider default retention applies. |
| Deepgram | Audio-to-text transcripts | Confidential | Per-request redact=true to redact sensitive number-like entities from transcripts, such as payment cards and Social Security numbers; provider default audio retention otherwise applies. |
| Google Cloud Text-to-Speech | Alternate TTS pipeline | Confidential | Standard API terms; provider default retention applies. |
OAuth, calendar, and import providers
User-connected calendar and meeting integrations are credential-gated and process data only after a coach authorizes or supplies access to their own provider account. Microsoft Graph / Outlook Calendar is classified as a user-authorized connected provider under the applicable developer terms, with no HiringCoachAI-Microsoft processor DPA or SCC coverage claimed for that API relationship. Zoom and Apple remain pending legal and Privacy Officer classification.
| System | Data | Classification | Retention |
|---|---|---|---|
| Google OAuth / Drive | Profile and email; a per-file drive.file user grant; file/folder names, metadata, and user-directed uploads beneath the marked HiringCoachAI folder; a dedicated service-account folder ACL used only for that subtree; Google Calendar event and free/busy scopes only when a coach connects scheduling | Confidential / Restricted for field-encrypted OAuth credentials and Drive content metadata | Dedicated field-encrypted OAuth credentials are stored until account deletion; revoking the provider grant makes them unusable but does not currently delete the record. Ordinary NextAuth provider rows retain identity metadata only. Provider-side Drive files remain in the user's account. While Drive OAuth remains connected, Materials re-establishes a manually removed folder share on the next sync. To stop that access under the current implementation, the user must revoke the OAuth grant and remove the folder share in Google Drive. |
| Microsoft Graph / Outlook Calendar | OAuth authorization context; calendar IDs, names, and editability; event start/end and showAs availability status for conflict checks; coach-authorized booking-event title, start/end, optional location, and attendee email only when invitations are enabled | Confidential / Restricted for OAuth credentials | Field-encrypted credentials, pending authorization state, granted scopes, calendar selections, and Outlook sync preferences are cleared on disconnect or permanent authorization failure. A minimal revoked status/error record may remain until account deletion, which removes the connection record. Events already written to Outlook remain in the connected account until deleted in Outlook or through an active HiringCoachAI connection. |
| Zoom | Connected coach account identity; meeting topic, start time, duration, provider meeting ID, attendee join URL, and OAuth request metadata | Confidential / Restricted for OAuth credentials and join links | Stored OAuth credentials and pending authorization state are cleared on disconnect; the revoked connection record is retained until account deletion. Provider-side meeting and operational records follow the connected account and Zoom's terms |
| Apple iCloud CalDAV | Coach Apple Account email, app-specific password, CalDAV server/calendar paths, free/busy event intervals, and booking-event start/end, title, and description | Confidential / Restricted for the app-specific password | Stored endpoint, username, and app-specific password are cleared on disconnect; the revoked connection record is retained until account deletion. Provider-side calendar data follows the connected Apple account and iCloud terms |
| OAuth sign-in; profile import (with user consent) | Confidential | Until user revokes | |
| Facebook OAuth | Profile, email | Confidential | Until user revokes |
| Canva | Design asset import metadata | Internal | Until user revokes |
| Mapbox | Geocoding and location display (approximate location strings) | Internal | Per Mapbox defaults |
| OpenWeb Ninja (Whats Next Labs LLC; candidate, production-disabled pending DPA/SCC posture) | Authenticated JSearch role/keyword, optional location, country/language and filters; normalized public job-listing fields returned to the browser. Only a user-selected listing enters the existing Firebase application record and AI job-description pipeline. | Internal search criteria; public listing data; Confidential after a listing is saved into the user's application workflow | Search responses: 10 minutes per warm server instance and 15 minutes in browser session storage. Selected listings: until user/account deletion under the existing application retention. |
Monitoring and analytics (consent-gated for non-essential)
| System | Data | Classification | Retention |
|---|---|---|---|
| Sentry | Error payloads, stack traces, Vercel drained logs, user IDs only where needed for debugging after recursive event, log, transaction, and span URL scrubbing; Session Replay and automatic DOM screenshots disabled | Confidential | 90 d |
| Amplitude | Product analytics events (anonymous or identified) | Internal / Confidential (if identified) | Per vendor defaults; revocable via analytics consent |
| Mixpanel | Product analytics events | Internal / Confidential (if identified) | Per vendor defaults; revocable via analytics consent |
| Meta (Facebook) Conversions API | Server-side gift-flow conversion events and hashed identifiers; client Meta Pixel disabled | Internal | Per vendor defaults; gated by marketing consent |
| PostHog (PostHog Inc., US) — client-side | Product-analytics event names and properties (e.g. login_attempted, email_magic_link_sent, registration_form_opened, upgrade_page_viewed, checkout_initiated, resume_optimization_started, job_search_submitted, job_board_link_clicked); stable user identifier (Firebase UID) and email attached only after analytics consent | Internal / Confidential (when identified) | Per vendor defaults; gated by analytics consent. SDK is opted-out by default in instrumentation-client.ts; capture begins only after the analytics consent category is granted and ceases immediately on revocation (distinct ID is reset). Lawful basis: consent. |
| PostHog (PostHog Inc., US) — server-side transactional | Operational events tied to contract performance: subscription_purchased, payment_failed (from Stripe webhook), account_deletion_confirmed (from the account-deletion confirmation handler), and affiliate-program events affiliate_attributed, affiliate_commission_earned, affiliate_commission_held, affiliate_commission_reversed, and affiliate_payout_paid. Affiliate events use the affiliate Firebase UID as distinct ID and may include the referred-user UID, affiliate code, integer commission/payment amounts, enumerated fraud flags or reversal reason, Stripe live/test mode, commission count, and internal payout ID. affiliate_commission_reversed is emitted only when an existing commission transitions to REVERSED; partial-refund and paid-after-reversal evidence have no separate PostHog event. | Confidential | Per vendor defaults. Lawful basis: contract performance for subscriptions and affiliate attribution, commission, and payout records; legitimate interest for account-deletion churn analysis, payment-failure signals, fraud review, and reconciliation. These events are operational telemetry, not marketing or behavioral analytics, and are not gated by cookie consent. Vendor-side access, export, or deletion is handled through the assisted DSR process when the identifiers link to a requesting data subject. |
Hotjar runtime initialization, Google Analytics / Google Tag Manager (GTM) and container-loaded LinkedIn Insight tags, and the client Meta Pixel were disabled on 2026-07-29 because those browser integrations could collect full query-backed product URLs. Cloudflare Google Tag Gateway was found re-enabled and injecting GTM before consent on 2026-08-06; it was disabled again that day and a fresh no-consent browser check confirmed no GA4, Google Ads, or LinkedIn requests or cookies. Dormant package or vendor-account records are retained for software inventory and audit history but do not represent active browser data transfers.
PII fields (consolidated)
For DSR purposes, a user's personal data is distributed across:
users/{uid}and every user-scoped subcollection above (resumes, files, coverLetters, contacts, applications, integrations, etc.)subscriptionsandsubscriptionHistory(rows whereuserId == uid)affiliateProfiles,affiliateReferrals,affiliateCommissions, andaffiliatePayoutswhere affiliate or referred-user identifiers link to the data subject; financial and bounded operating-decision evidence follows the tax/audit retention stated above rather than unconditional deletion. Charge-keyedaffiliateChargeReversalMarkersare excluded from the self-service affiliate export and are searched only from a verified Stripe charge reference through the assisted DSR process.linkedinCookies(rows whereuid == uid)accounts,sessions,authTokens,verificationTokens(rows whereuserId == uid)auditLog,aiCallAudit,adminCoachActions,coachClientPaymentAuditEvents, andcoachLeadSubmissions(rows whereactorUid, actor/coach/relationship/engagement identifiers, admin actor, coach user, target client identifiers, or lead contact details link to the data subject)coachRelationshipsand nested coach comments, replies, messages, conversation threads, private notes, activity, coach task linkage, notifications, and notification throttle records where the user is the coach, client, author, or recipient- relationship-scoped coaching sessions, goals, milestones, goal check-ins, engagement and agreement-version records, signature evidence, operation records, and
engagementIntakeForms, pluscoachIntakeTemplatesowned by a coach coachMaterials, collaborative state/revisions/operations/presence, realtime leases, material share grants, recent-item records, storage-usage records, browser IndexedDB document caches/recovery state, and uploaded GCS objects where the user is the owner, recipient, collaborator, or recent-item actor- relationship-scoped coaching sessions, goals, milestones, goal check-ins, engagement, payment-obligation, subscription-binding, agreement-version and signature records; top-level contract-notification and payment-reminder evidence; operation records and
engagementIntakeForms; pluscoachIntakeTemplatesowned by a coach coachMaterials, material share grants, recent-item records, storage-usage records, and uploaded GCS objects where the user is the owner, recipient, or recent-item actorsupportThreads(and nested support messages) where the user is the thread owner, and the user-scoped communication toolsusers/{uid}/coachMessageDrafts,messageDraftsand its saved versions,messageTemplates,messageLabels, andmessagingPrefscoachProfileDrafts,coachPublicProfiles,coachPublicProfileSlugs, andcoachProfileReviewNotificationswhere the user owns the profile or review requestpilotMemberships,pilotAdmins,pilotSessions,pilotEvents,pilotUserDailyRollups,pilotGoals,pilotInterventions,therapistSessions(rows whereuid,userId, ormembershipIdlinks to the data subject)- Stripe (customer object keyed by
stripeCustomerId) - SendGrid and Google Workspace / Gmail (email addresses, transactional/support message content, and delivery or routing metadata)
- Google Workspace / Sheets (testimonial submissions and permissions)
- Google Workspace / Gmail hiring and accommodations mailboxes (applicant and intern records, including accommodation requests)
hiringJobs/{jobId}/applicationsand the private GCS hiring-resumes bucket (careers-site applicant records, where the data subject is a job applicant rather than a product user)- LinkedIn, Google, Microsoft, Zoom, Facebook, and Apple iCloud (provider-side records under the user's revocable OAuth grant or user-supplied app-specific credential)
The account-deletion flow cascades across user-scoped Firebase collections, linked authentication and session records, coach profile drafts and public profiles, owned coach/client materials and their storage objects, material grants/recents/stars tied to the user, onboarding-copy coach/source/relationship/run attribution on material copies owned by another user, coach relationship access and authored coach communications, user-linked pilot administrator assignments, pilot-program direct identifiers, email-matched public-booking verification records, and Stripe subscription cancellation/verification before active account data removal. Before any of that begins, account deletion is BLOCKED (fails closed, no product/authentication data removed) while payoutRecovery.status is outstanding — a completed transfer whose underlying charge was later refunded or disputed, owed back to HiringCoach, must be reconciled through an admin resolve_recovery action first. Once clear, affiliate deletion marks the user as processing, transactionally fences standing before access revocation, disables owned codes, redacts the application and non-retained standing reviewer, and continues deleting ordinary product/authentication data even when EARNED, HELD, or processing obligations remain. Approved standing becomes closed; suspended and other nonapproved standing is preserved. Only bounded financial evidence and, while needed, the restricted pending assisted-settlement inventory and minimum retained contact survive. Self-service Connect is blocked after the fence. A trusted-origin fresh interactive admin may use the exact pending closed or suspended settlement route to create or resume live Stripe onboarding and receive an Account Link plus the retained delivery contact after a final race-safe recheck; the application sends no message. The same exact case permits bounded payout-compliance review and HELD adjudication. closed approval may make the reviewed amount EARNED; suspended approval or explicit authorization stamps an immutable version-1 pay disposition on only the reviewed commission, and settlement may select only those exact disposition-bound EARNED commissions while the profile remains suspended, deletion-fenced, and pending. Ordinary suspended balances remain ineligible. Terminal commission and payout paths refresh the inventory and remove retained contact when obligations resolve without unsafely retrying money movement after a refresh failure. Referred-customer deletion separately replaces any attribution with the minimal beneficiary/status/timestamp/five-field lifecycle tombstone and any pre-cutoff commission with a sanitized reversible financial record; post-cutoff invoice delivery does not mutate the tombstone or counters. The same idempotent fences run inside abandoned-account removal. Affiliate commissions, payouts, terms, counters, residence, connected-account binding, payout-compliance decisions, marker evidence, and accountable reviewer evidence remain only under the documented settlement, tax, fraud, claims, and audit posture. Coach profile slugs are tombstoned and retain only a pseudonymous owner hash where needed for link integrity and anti-impersonation. Coach relationship records are ended and direct identifiers for the deleting user are redacted; authored coach comments, replies, messages, private notes, notification throttle rows, and queued payment/contract notifications are redacted, canceled, or removed. Signed contract, verified booking assent, automatic-renewal consent, payment-obligation, subscription-binding, delivery-outcome, and related audit evidence is retained only for its applicable minimum period or legal hold, with direct identifiers redacted only where compatible with evidence integrity. Exact sealed legal-acceptance records are not mutated by account deletion. Pilot usage records are retained only after direct user identifiers are replaced with non-reversible deleted-participant identifiers and direct contact, name, and free-text fields are removed. SendGrid, Google Workspace, and other vendor-side records outside Stripe are handled through the DSR process rather than automatic API deletion.
The self-service account export requires fresh authoritative authentication and a current MFA verification bound to the requesting app session. It currently includes the user's profile, recursive user subcollections, subscription record, safe linked-authentication and session metadata with raw MFA credentials, recovery material, tokens, and security subcollections excluded or redacted, metadata-only audit rows from the application audit log and AI call audit, coach relationship records and nested engagement/agreement/payment-obligation records tied to the user, coach notification, contract-delivery, payment-reminder, and still-present public-booking verification records tied to the user or a client relationship, owned material metadata and HiringCoach Doc content, material grants received or issued by the user, material quota data, metadata-only references for client-owned onboarding copies attributed to the exporting coach's source materials, pilot membership, pilot-admin assignment, pilot-session, pilot-event, and pilot user-daily-rollup rows tied to the user, and a bounded affiliate section containing the user's own application, residence, terms, standing, counters, coarse Connect and payout-compliance states, owned codes, anonymous commission rows, and payout summaries. The affiliate projection omits referred-user and document identifiers, raw Stripe account/customer/payment/transfer references, commission ID lists, IP hashes, and administrator or reviewer user IDs. affiliateChargeReversalMarkers are excluded from the self-service affiliate export because the charge-keyed records do not carry a safe user binding; disclosure requires a verified Stripe charge reference through the assisted DSR process. The archive separately includes an affiliateProgramData self-service DSR section (lib/affiliates/privacyLifecycle.js) covering the same profile/commission/payout/code ground plus payout audit events (action and timestamp only) and Connect registration state (registered flag and confirmation timestamps only, never the Stripe account ID); its affiliateBankPayouts/affiliatePayoutPlans sections stay empty until those collections have writers. coachClientPaymentAuditEvents, email-matched anonymousPurchaseLegalAcceptances, and email-matched anonymousBookingLegalAcceptances are handled through the assisted DSR workflow rather than the current self-service JSON export; an anonymous purchaser or booking visitor must verify control of the matching email before disclosure. Fulfillment-exception records are reconciled by provider reference and disclosed when they can be reliably linked to a verified requester. Uploaded material file bodies remain downloadable through the authenticated materials workspace rather than being embedded as base64 in the self-service JSON archive. Vendor-side Stripe, SendGrid, analytics, or OAuth-provider records are handled through the DSR workflow with the applicable provider rather than the self-service JSON export.
Maintenance
- An automated data-map audit runs during local compliance checks and the manual security workflow. It scans every Firestore collection reference in the application code and compares it to this document, fails if a collection is referenced in code but not represented here, and maintains an explicit allowlist for operational and admin-internal collections that hold no personal data.
- The same audit surfaces drift between this document and the sub-processors when local compliance checks or the manual security workflow are run.
Change history
| Date | Change | Author |
|---|---|---|
| 2026-08-14 | Registered adminMarketingEmailTemplates, a single fixed-document Firestore override store letting a marketing admin edit the renewal-reminder Mailchimp campaign's subject line, preview text, and HTML (title and from-name stay code-controlled). The cron now renders the effective (override-or-default) template via resolveEffectiveRenewalReminderEmail, and a new admin-only test-send flow (behind the existing marketing-admin auth or a cron bearer token) sends a [TEST]-prefixed preview through a dedicated renewal-reminder-test Mailchimp segment - never the live renewal-reminder-pending segment, never the renewalReminders idempotency store. No customer personal data; server-only Admin SDK writes. | Security Officer |
| 2026-08-14 | Registered renewalReminders, the idempotency store for the dark-launched (RENEWAL_REMINDER_EMAILS_ENABLED, default off) daily renewal-reminder cron: one record per Stripe subscription per renewal period, guaranteeing at most one reminder email per period. Server-only Admin SDK writes. No client Firestore access; not covered by firestore.rules. | Security Officer |
| 2026-08-14 | Registered affiliateConnectAccounts (Connect-account-to-affiliate binding registry) and affiliatePayoutAuditEvents (restricted, append-only reconciliation evidence) as their own rows; reserved a row for the not-yet-written affiliateBankPayouts. Documented the payoutRecovery (affiliate profile) and paidReversalRecovery (commission) returned-transfer-liability fields, and the new deletion behavior they drive: account deletion now BLOCKS (fails closed) while a payoutRecovery liability is outstanding, distinct from the existing EARNED/HELD assisted-settlement posture, which still does not block. Documented the new accountNotice/suspensionResponse for-cause suspension-notice fields on affiliateProfiles (/api/affiliates/notice-response). Added the affiliateProgramData self-service DSR export section (payout audit action/timestamp only, Connect registration state without the raw account ID) alongside the existing affiliate export section. | Security Officer |
| 2026-08-14 | Added bounded, self-only affiliate records to account export and documented their identity-minimized projection. Added the pre-revocation affiliate deletion fence: close eligible standing, disable and pseudonymize owned-code tombstones, remove application and non-retained standing reviewer data, and preserve settlement/tax/audit records under the affiliate financial retention posture. Registered bounded concurrent Stripe-account cleanup evidence, restricted unpaid-obligation assisted-settlement cases with contact deletion on resolution, and the affiliate attribution, commission, reversal, and payout PostHog event inventory with assisted-DSR handling. | Security Officer |
| 2026-08-13 | Recorded affiliate current-residence declarations, bounded account/state/year/procedure payout-compliance reviews and immutable payout snapshots; confirmed that identity, tax-form, tax-identifier, bank, withholding amount/rate, and free-text tax data stay in Stripe or outside the application; and documented fail-closed annual cash gates plus manual reconciliation for ambiguous processing payouts. No new collection or direct Firestore client access. | Security Officer |
| 2026-08-13 | Registered the explicit append-only users/{uid}/applications/{applicationId}/statusTransitions ledger, its server-timestamped schema-v2 fields, and locked, paged server-mediated lifecycle deletion; documented the protected parent recordedStageFirstReachedAt projection and server-maintained compatibility caches used by /jobs to consume first real stage-commit times without loading the ledger; separated the two stores so the automated collection audit recognizes both. | Security Officer |
| 2026-08-12 | Replaced recipe-level scoped consent for new onboarding runs with client-owned Account controls that default every content category on. Recorded the bounded per-scope request state on coachRelationships, the deterministic Mission Control review task in users/{uid}/tasks, coach-visible pending/denied status and denial date, seven-day resend metadata, client approve/deny handling, and permissions-only workspace restriction when coaching workspace access is off. Existing in-flight runs retain their frozen legacy snapshot; saved legacy recipe fields remain readable for compatibility but no longer narrow new acceptances. | Security Officer |
| 2026-08-12 | Recorded onboarding material delivery through existing coachMaterials, coachMaterialShares, coachOnboardingRecipes, and clientOnboardingRuns: bounded client-owned copies retain deterministic source/run provenance and charge the client's storage quota; shared delivery uses relationship-scoped editor grants only after acceptance; run refs retain bounded per-item outcomes; coach deletion redacts coach/source/relationship/run attribution from surviving client-owned copies; coach exports include only metadata references to those external copies. No new collection or direct Firestore client access. | Security Officer |
| 2026-08-12 | Recorded immutable public-offer package duration and purchase-level access expiry across public snapshots, purchase intents, purchases, primary/shared engagements, course enrollments, and material shares. The new purchase-scoped grant map preserves independent manual or later-offer access while enforcing expiry at booking and content boundaries. No new collection or client-side Firestore access was added; existing server-only rules remain unchanged. | Security Officer |
| 2026-08-12 | Recorded the fragment-to-HttpOnly-cookie exchange for public booking and management capabilities, the non-authorizing scheduling-link path handle, OAuth-state export redaction, and removal of booking and cancellation metadata from server-side PostHog events. | Security Officer |
| 2026-08-10 | Historical Client Onboarding Recipes V3 Workstream E record: introduced recipe-level scoped consent and per-category request timestamps. Superseded on 2026-08-12 by client-owned Account controls and the bounded permission-request workflow above; the legacy recipe field remains read-compatible only for existing data and no longer narrows new acceptances. | Security Officer |
| 2026-08-10 | Client Onboarding Recipes V3 Workstream F (re-onboarding recipes): recorded the new archetype field on coachOnboardingRecipes (new_client, the default for every recipe saved before the field existed, or portal_intro for clients who already work with the coach and are simply being moved onto the portal). It is a coach-chosen audience label — no client data, no new personal data, and no new collection — and it is snapshotted onto clientOnboardingRuns.recipeSnapshot with the rest of the definition. A portal_intro recipe rejects payment and agreement blocks at save time, so a re-onboarded client is never asked to pay or sign again; assignment, runs, links, reminders, journeys, and the aggregate stats counters are otherwise identical for both archetypes. Behind the existing CLIENT_ONBOARDING_RECIPES_ENABLED flag; server-only/deny-all in firestore.rules is unchanged. | Security Officer |
| 2026-08-10 | Client Onboarding Recipes V3 Workstream D (consent-first SMS nudges): added the client onboarding wizard as a second capture surface for the EXISTING coach SMS consent engine — no new consent, opt-out, quiet-hours, or delivery machinery. Recorded the new smsSends claim ledger on clientOnboardingRuns (invite cycle, reminder index, claim/send timestamps, sent/deferred/failed outcome and error reason; max two records per run; no phone number, no message content) and the new client_onboarding_wizard value of coachRelationships.sms.consentMethod / the source field on coachSmsConsentEvents. Consent writes and the evidence doc still go through setRelationshipSmsConsent; outbound texts still go through coachSmsMessages + deliverCoachSms (8pm-8am client-local quiet hours, Twilio STOP handling, and the phone-hash-wide global opt-out all unchanged and now also suppress onboarding nudges). Behind the existing CLIENT_ONBOARDING_RECIPES_ENABLED flag plus a new CLIENT_ONBOARDING_SMS_REMINDERS_ENABLED sub-flag. No new collections; server-only/deny-all in firestore.rules is unchanged. | Security Officer |
| 2026-08-10 | Recorded the Privacy Officer classification of Microsoft Graph / Outlook Calendar as a user-authorized connected provider; corrected the exact Graph read/write fields and documented local disconnect/revocation cleanup plus the provider-side event-retention boundary. | Privacy Officer |
| 2026-08-10 | Client Onboarding Recipes V3 (per-revision funnels + revision experiments): split every coachOnboardingRecipeStats funnel counter into a parallel revisions.<recipeVersionId> map (same aggregate-only counters, keyed by the immutable version ID already snapshotted on each run — no new client-level data), and recorded the optional experiment A/B record on the coachOnboardingRecipes family-root entry (status, the two compared coach-owned recipe/version IDs, start timestamp, starting coach user ID). Assignment-time A/B selection is a deterministic sha256 of the assignment's own idempotency key — no randomness, no profiling of the client. Behind the existing CLIENT_ONBOARDING_RECIPES_ENABLED flag plus a new CLIENT_ONBOARDING_REVISION_EXPERIMENTS_ENABLED sub-flag. No new collections; server-only/deny-all in firestore.rules is unchanged. | Security Officer |
| 2026-08-10 | Client Onboarding Recipes V3 Workstream B (post-onboarding journeys): recorded the optional journey section on coachOnboardingRecipes (a coach-owned program-template reference, up to 5 coach-owned course references, and up to 5 coach-authored follow-up messages with day offsets) and its per-run outcome record on clientOnboardingRuns (completion stamp plus per-item referenced IDs, planned send timestamps, and skip-reason/error strings only — never message content). Journey outcomes are exposed to the coach only, never to the client wizard projection. Execution routes entirely through the existing program-template, course-enrollment, form-automation, and inbox send-timer engines, and adds an onboarding_completed trigger to the existing form-automation rule triggers. No new collections; server-only/deny-all in firestore.rules is unchanged. | Security Officer |
| 2026-08-08 | Client Onboarding Recipes Workstream F (self-serve purchase → recipe handoff): recorded the optional onboardingRecipeId reference on coachServiceCatalog (shape-validated at save, resolved to a published recipe at publish time) and its sealed passthrough onto the published coachPublicOffers version snapshot and publicPurchaseIntents' offer snapshot; recorded publicPurchaseIntents' new fulfillment.onboardingHandoff outcome record (timestamp plus a spawned run ID, skip reason, or error message only — never response content); recorded the new one-time reminders.handoffInvite delivery-state record on clientOnboardingRuns (due/attempt/backoff/sent/last-error only). All spawn/delivery writes are Admin-SDK server code behind the existing CLIENT_ONBOARDING_RECIPES_ENABLED flag plus a new CLIENT_ONBOARDING_OFFER_HANDOFF_ENABLED sub-flag. No new collections; server-only/deny-all in firestore.rules is unchanged. | Security Officer |
| 2026-08-08 | Client Onboarding Recipes Workstream E (intake survey → workspace mapping): recorded the survey block's new mappings config on coachOnboardingRecipes (up to 7 pinned survey field-ID references used to auto-seed the client's career-plan narrative, north-star goal, and target-role entries — field IDs only, never response content) and the workspace-seeding provisioning outcomes on clientOnboardingRuns's provisioning results (career-plan/goal/target-entry success, skip-with-reason, or error records). All writes land through the existing career-plan/goals/target-strategy domain writers. No new collections; server-only/deny-all in firestore.rules is unchanged. | Security Officer |
| 2026-08-08 | Client Onboarding Recipes Workstream D (content blocks): recorded the new coach-authored welcome_message (rich-text HTML, sanitized server-side at save with a dedicated allow-list, never trusted raw) and video (allowlisted provider + video ID only — YouTube/Vimeo/Loom — never a raw URL or embed markup) block types on coachOnboardingRecipes. No new collections; server-only/deny-all in firestore.rules is unchanged. | Security Officer |
| 2026-08-20 | Completed the adults-only removal outside the published policies: the signer representation sealed into new signatures moved to hc-signer-representation-v2 and no longer states an age (verification still recognizes the pinned v1 text so signatures sealed before the change keep validating), and the coach-client SMS consent disclosure moved to coaching-sms-v3-2026-08-20, rewritten to the CTIA and Twilio A2P 10DLC standard opt-in elements. The Terms of Service, Privacy Policy, and community guidelines keep their own age statements. | Engineering; pending Privacy Officer review |
| 2026-08-19 | Removed the adults-only product gate from the coach commercial, learning, lead-capture, and SMS surfaces: coachServiceCatalog entitlement templates, published offer snapshots, publicPurchaseIntents participant records, coachCourses/coachCourseVersions/coachCourseEnrollments, coachLeadOptInVerifications, and coachSmsConsentEvents no longer collect or store an age attestation, and the separate recipient/participant 18+ consent artifacts on signed agreements are no longer produced. The Terms of Service and Privacy Policy continue to state that the service is intended for adult users, and the signature block's legal capacity representation is unchanged. | Engineering; pending Privacy Officer review |
| 2026-08-08 | Client Onboarding Recipes Workstream B (dashboard/stats + PostHog telemetry): registered coachOnboardingRecipeStats (aggregate per-recipe-family funnel counters, coach/family-level only, no client-level data), added to the client-onboarding server-only/deny-all block in firestore.rules. PostHog events (client_onboarding_run_created/step_completed/run_completed/run_abandoned) carry only recipe/run/step identifiers and coarse metadata (distinctId = coach uid) — no new personal-data collection. | Security Officer |
| 2026-08-08 | Client Onboarding Recipes Workstream A (automated reminders/stall/expiry follow-through): recorded the new reminder-engine state and link-expiry mirror on clientOnboardingRuns and the reminder-policy switch on coachOnboardingRecipes. No new collections; server-only/deny-all in firestore.rules is unchanged. | Security Officer |
| 2026-08-08 | Registered the folder-bounded Google Drive Materials mirror, direct user-owned uploads, dedicated no-project-role service account, field-encrypted Drive credential record, legacy credential migration gate, and provider-side retention boundary. | Engineering; pending Privacy Officer review |
| 2026-08-07 | Registered the Client Onboarding Recipes collections (coachOnboardingRecipes, clientOnboardingRuns incl. nested operations/legalAcceptances sealed clickwrap evidence, clientOnboardingLinks) ahead of the coach-authored post-signup onboarding wizard feature; server-only/deny-all in firestore.rules, and clientOnboardingLinks.expiresAt carries a 14-day Firestore TTL fieldOverride. | Security Officer |
| 2026-08-03 | Added redditProspects (internal Reddit community-manager queue: sourced public thread content, triage/draft metadata, human review decisions) to the non-personal operational allowlist, same treatment as seoContentItems — no customer personal data, server-only via Admin SDK. | Security Officer |
| 2026-07-29 | Updated the OpenWeb Ninja JSearch candidate record after Rishan confirmed the scoped commercial permission; recorded the free hard-limit plan, server key configuration, short-lived caches, and locally verified search/import/deduplication flow. Production remains fail-closed pending the DPA and SCC/transfer posture required by the published privacy commitments. | Privacy Officer |
| 2026-07-29 | Registered coach-owned imported CRM field definitions and arbitrary coach-only per-client custom values; documented deletion of all imported practice metadata when either participant deletes their account. | Security Officer |
| 2026-07-27 | Added conservative external-system coverage for coach-connected Microsoft Graph / Outlook Calendar, Zoom, and Apple iCloud CalDAV; final controller/processor and DPA classification remains pending counsel and Privacy Officer confirmation. | Engineering; pending Privacy Officer review |
| 2026-07-26 | Registered the editable coach service catalog, encrypted coupon configuration, adult-only entitlement templates, and testimonial permission, truth, substantiation, results, and material-connection disclosure fields. | Privacy Officer |
| 2026-07-20 | Corrected high-assurance operation inventory and retention: signed pending projections can retain raw signature/evidence payloads, and recognized v1/v2/v3 operations are preserved exactly while legacy versions remain manual-review only. | Privacy Officer |
| 2026-07-20 | Registered saved coffee-chat preparation sessions and their linked-contact, networking-draft, and timestamp fields. | Privacy Officer |
| 2026-07-20 | Registered authenticated client refund-case evidence, exact provider attribution, restricted assisted DSR handling, and the legacy conservative v1 retention schedule. | Privacy Officer |
| 2026-07-16 | Registered the hiring pipeline: hiringJobs and its versions/reviews/applications subcollections (careers-site applicant PII incl. status history, admin screening notes, and sent decision-email records) plus the private GCS hiring-resumes bucket; aligned Firestore/GCS applicant records with the existing 4-year Gmail applicant-records retention. | Privacy Officer |
| 2026-07-16 | Registered verified public-booking clickwrap evidence; separated the eight-minute verification window from asynchronous TTL deletion; documented exact-evidence preservation, assisted DSR matching, and account export/deletion handling for claimed-email records. | Privacy Officer |
| 2026-07-16 | Registered anonymous purchase clickwrap evidence and fail-closed gift-fulfillment refund exceptions; documented plaintext-email attribution, assisted DSR matching, and financial retention. | Privacy Officer |
| 2026-07-16 | Registered admin plan-adjustment, plan-import, plan-conflict, subscription-field, subscription-migration, and subscription-overwrite audit ledgers. | Security Officer |
| 2026-07-16 | Registered coach engagement, payment-obligation, subscription-binding, renewal-reminder and client-payment audit records; established the conservative automatic-renewal evidence floor and clarified notification, legal-hold and deletion-lock retention. | Security Officer |
| 2026-07-16 | Registered the durable contract-delivery outbox, provider-outcome resolution evidence, legal-hold registry, and deletion-serialization locks; clarified fail-closed account-deletion retention. | Security Officer |
| 2026-07-16 | Registered coach profile and moderation records, coaching-session notes and operation records, booking email verifications, testimonial submissions, user communication drafts and versions, and the communication content processed by email providers; documented coach-profile OpenAI moderation and deletion behavior. | Privacy Officer |
| 2026-07-16 | Registered client-content artifact collections plus coaching sessions, goals, milestones, check-ins, intake templates/forms, coaching contract templates, agreement versions and signature evidence, immutable versions, and idempotency-operation records. | Security Officer |
| 2026-07-16 | Registered HiringCoach Doc canonical collaboration state, bounded revisions/operations, ephemeral presence, 50-second realtime lease/signal collections, and user-namespaced browser IndexedDB cache/recovery state; clarified access-revocation retention. | Security Officer |
| 2026-07-14 | Registered the coach/client materials workspace collections and GCS objects, plus account-export and deletion handling for owned and shared materials. | Security Officer |
| 2026-07-13 | Registered coachProspects (coach CRM/prospect pipeline, part of the Client Payments commerce domain — already server-only/deny-all in firestore.rules) after audit-data-map caught it as an undocumented code reference. | Security Officer |
| 2026-07-10 | Registered the subscription transition engine collections (heldConsumerSubscriptions, subscriptionTransitionOps, coachBillingGraceEvents) ahead of the coach-invite subscription-hold/resume and coach-billing-lapse grace features (docs/coach-client-subscription-transitions.md). | Security Officer |
| 2026-07-09 | Registered the coach<->client realtime chat collections (coachChatConversations, coachChatConversations/{conversationId}/messages, coachChatPresence) and their GCS attachment storage note ahead of the coach-chat feature (docs/coach-chat.md). | Security Officer |
| 2026-07-08 | Registered the coach internal-inbox messaging collections after the coach messaging/inbox feature shipped: coachRelationships/{relationshipId}/threads, top-level supportThreads, and the user-scoped inbox tools users/{uid}/coachMessageDrafts, messageTemplates, messageLabels, and messagingPrefs. | Security Officer |
| 2026-06-25 | Added coachLeadSubmissions and the Google Sheets coach lead intake spreadsheet for the public coach landing page | Security Officer |
| 2026-06-25 | Added adminCoachActions for career coach access administration and relationship revocation audit records | Security Officer |
| 2026-07-24 | Registered server-only coach reporting preferences, weekly delivery leases, and pseudonymous offer analytics. Offer events contain an HMAC session hash and allowlisted event/source only; no raw IP, user agent, referrer, or participant PII is stored. | Privacy Officer |
| 2026-04-24 | Initial map | Security Officer |
| 2026-05-06 | Comprehensive rewrite: added user-scoped subcollections (applications, drafts, fitAnalysis, candidateAnalysis, intelBriefings, interviewQuestions, interviewResearchCases, pepTalks, onboarding, contactLinks, followUps, followUpReminders, integrations, linkedIn / linkedinJobExports / linkedinProfileExports, shortAnswers, resumeMetadata, userDetails, explore, feedback, aiOutputFeedback, subscriptionHistory, verificationTokens, therapistSessions, pilotMemberships, pilotGoals, pilotInterventions); split compound vendor cells in non-Firestore section so each sub-processor has its own row; added drift gate via the automated data-map audit. | Security Officer |
| 2026-05-07 | Clarified self-service export coverage and vendor-side deletion status after code review and export expansion. | Security Officer |
| 2026-05-07 | Added compliance onboarding acknowledgments, training log, scheduled document review log, and latest document review rollups after onboarding/review portal implementation. | Security Officer |
| 2026-05-08 | Added monthly patch-verification run and rollup collections; corrected data-map audit workflow description to local/manual checks. | Security Officer |
| 2026-05-12 | Clarified that the cookie marketing-consent field governs marketing/attribution tracking and is not itself a marketing-email subscription. Mailchimp processing is listed for account/customer communications and communication-list management; marketing-email preference handling remains separate from cookie tracking consent. | Security Officer |
| 2026-05-12 | Added user-linked pilot engagement collections (pilotAdmins, pilotSessions, pilotEvents, pilotUserDailyRollups) to the personal-data inventory and account-export coverage notes. | Privacy Officer |
| 2026-05-12 | Clarified account-deletion handling for pilot programs: direct user identifiers are removed from pilot membership and usage records while anonymized usage is retained for program reporting. | Privacy Officer |
| 2026-05-14 | Added securityAuditMonitorRuns after implementing the hourly audit-log anomaly monitor and retention target. | Security Officer |
| 2026-05-17 | Added PostHog (PostHog Inc., US) as a product-analytics sub-processor. Client-side capture is opted-out by default and gated through the analytics consent category. Server-side transactional events (subscription, payment-failure, account-deletion confirmation) are listed separately under contract performance / legitimate interest. | Privacy Officer |
| 2026-05-17 | Added users/{uid}/files metadata for server-mediated account document uploads; aligned GCP/Firebase row with account document storage now that the upload feature is live. | Security Officer |
| 2026-05-20 | Added resume parser benchmark fixture, run, and attempt collections after introducing the admin benchmark harness. | Security Officer |
| 2026-06-08 | Added adminBillingActionAudit after admin billing actions began recording refund/cancellation audit evidence. | Security Officer |
| 2026-05-27 | Added applicant and intern records, including separate accommodation-request handling and four-year recruiting-record retention, after expanding the Privacy Notice scope. | Privacy Officer |