# Addendum — What RetiFlo treats as personally identifiable information

**An addendum to [`privacy-policy.md`](privacy-policy.md).** Processors are named once in
[`data-processors.md`](data-processors.md); this document answers the other half of the question —
*what is removed before your data goes to any of them.*

> **GENERATED FILE — DO NOT EDIT.**
> Source: `scripts/llm-schema-manifest.mjs` · Regenerate: `npm run generate:pii-classification`
>
> This is generated from the classification the build enforces, not written alongside it. Every text
> field in the database must be classified before it can ship (`npm run audit:llm:schema` fails
> otherwise), so this document describes what the code actually does rather than what it was
> intended to do when someone last edited a policy.

## The commitment, in one sentence

**We send your plan's data — with personally identifiable information removed — to the processors
named in [`data-processors.md`](data-processors.md).**

"Your plan's data" is broad and meant to be: account balances and types, income and expenses,
year-by-year projections, tax figures, and any question you type into an AI feature. What is *not*
sent is everything in the table below.

## What is removed

Before anything leaves the application, these are replaced with neutral placeholders. The
substitution is reversed on the way back, so you still see "Fidelity Rollover IRA" on screen — the
processor never does.

| Category | Examples | Fields |
|---|---|---|
| Names | your name, your spouse's name, a named beneficiary, an advisor's name | 18 |
| Contact details | email address, phone number | 8 |
| Date of birth | used for every age-based calculation, never sent | 1 |
| Address and location | the street address of your home or a rental property | 1 |
| Account, institution and document identifiers | "Fidelity Rollover IRA", an account number, an uploaded statement's filename | 9 |
| Free text you write | notes on an account, a question you ask the Companion, an advisor's rationale | 32 |
| Links and media | a photo of a property, a profile or website link | 4 |
| Other identifying text | fields not yet placed in a category above | 7 |

**80 fields in total** are treated as personally identifiable and removed.

A further **73 fields never leave the application at all** under any circumstances —
passwords, authentication tokens, and payment identifiers. These are not "removed from the message";
no message is ever built that contains them.

## What this does not cover

- **Aggregate and anonymised statistics** about product usage, which contain no household data.
- **Data you choose to share elsewhere** — a report you export and send to someone yourself.
- **Payment details**, which are collected by Stripe directly and never held by RetiFlo.

## How this is kept honest

1. Every text column in the database must carry a classification before it can be merged.
2. `npm run audit:llm:schema` fails the build on any unclassified column — and equally on a stale
   entry for a column that no longer exists, so the list cannot rot in either direction.
3. All AI features route through a single gateway that applies the removal. `npm run audit:llm`
   fails the build if any code path constructs its own connection to a processor.
4. This document is regenerated from that classification rather than maintained beside it.

**What these controls do and do not prove.** They prove a human classified every field and that
there is one enforced exit point. They are a review gate, not a runtime proof of the redaction
engine's behaviour — that comes from its default-deny design and its own test suite. The distinction
is recorded in `plans/design_3.0/pii-column-classification-REVIEW.md`.

---

# Appendix — full field-level classification

For auditors. The categories above are the readable view of this list.

### Removed before sending (PII) — 80 fields

- `AdvisorBillingTransaction.description`
- `AdvisorCapacitySettings.unavailable_reason`
- `AdvisorClientInternalNote.client_label`
- `AdvisorClientInternalNote.content`
- `AdvisorClientRelationship.pending_client_email`
- `AdvisorFirm.credential_holder_name`
- `AdvisorFirm.credential_number`
- `AdvisorFirm.name`
- `AdvisorFirmBrandingProfile.disclosure_footer`
- `AdvisorFirmBrandingProfile.display_name`
- `AdvisorFirmInvite.email`
- `AdvisorFirmMembership.credential_holder_name`
- `AdvisorFirmMembership.credential_number`
- `AdvisorMarketplaceProfile.bio`
- `AdvisorMarketplaceProfile.headline`
- `AdvisorMarketplaceProfile.linkedin_url`
- `AdvisorMarketplaceProfile.website_url`
- `AdvisorPlanVariance.rationale`
- `AdvisorRating.comment`
- `AdvisorRating.hidden_reason`
- `AdvisorReviewRequest.preferred_advisor_email`
- `AdvisorReviewRequest.review_notes`
- `AiConversation.title`
- `AiMessage.content`
- `AiMessage.feedback`
- `AiMessage.feedback_note`
- `Asset.account_number`
- `Asset.beneficiary_name_529`
- `Asset.description`
- `Asset.institution`
- `Asset.name`
- `Beneficiary.name`
- `ClientDeliverable.title`
- `ClientDeliverableAudit.actor_name`
- `ClientTask.title`
- `ClientTask.why`
- `CompanionExchange.answer`
- `CompanionExchange.question`
- `DebtAccount.name`
- `DocumentAccessLog.actor_name`
- `DocumentAiShareGrant.granted_by_name`
- `DocumentAiShareGrant.revoked_by_name`
- `EmailChangeRequest.new_email`
- `EmailChangeRequest.old_email`
- `EmailNotificationLog.email_address`
- `EstatePlanningDocument.file_name`
- `EstatePlanningDocument.notes`
- `ExpenseCategoryRule.pattern`
- `ExpenseWorksheet.name`
- `ExpenseWorksheetTransaction.notes`
- `IncomeSource.name`
- `LifeEvent.notes`
- `LinkedAccount.account_name`
- `LinkedAccount.institution_name`
- `Notification.action_url`
- `Notification.message`
- `Notification.title`
- `PdfExportJob.error`
- `Plan.name`
- `PlanComment.content`
- `PlanDocument.file_name`
- `PlanDocument.label`
- `PlanDocument.note`
- `PlanDocument.uploaded_by_name`
- `RealEstateFutureEvent.notes`
- `RealEstateProperty.address_text`
- `RealEstateProperty.name`
- `RealEstateProperty.photo_url`
- `Scenario.name`
- `SpendingPattern.name`
- `StatementUpload.error_message`
- `StatementUpload.original_filename`
- `SystemEventLog.message`
- `Transfer.description`
- `User.dob`
- `User.email`
- `User.firstName`
- `User.lastName`
- `User.phone`
- `UserWebAuthnCredential.friendly_name`

### Never sent to any AI provider — 73 fields

- `AdvisorBillingTransaction.charge_id`
- `AdvisorClientRelationship.invite_token`
- `AdvisorFirm.stripe_customer_id`
- `AdvisorFirm.stripe_subscription_id`
- `AdvisorFirmBrandingProfile.logo_file_name`
- `AdvisorFirmBrandingProfile.logo_mime_type`
- `AdvisorFirmInvite.invite_token`
- `AdvisorMarketplaceProfile.photo_mime_type`
- `AdvisorReviewRequest.advisor_payout_id`
- `AdvisorReviewRequest.client_payment_intent_id`
- `AdvisorReviewRequest.client_stripe_charge_id`
- `AiMessage.feedback_disposition_note`
- `AuditEvent.actor_email`
- `AuditEvent.operation`
- `AuditEvent.target`
- `CashFlowProjection.input_data_hash`
- `CashFlowProjectionHistory.input_data_hash`
- `ClientDeliverable.draft_fingerprint`
- `DocumentAccessLog.ip`
- `DocumentAccessLog.user_agent`
- `DocumentAiShareGrant.content_sha256`
- `EmailChangeRequest.new_token`
- `EmailChangeRequest.old_token`
- `EmailNotificationLog.resend_message_id`
- `EmailVerificationToken.token`
- `EstatePlanningDocument.content_sha256`
- `EstatePlanningDocument.file_mime_type`
- `EstatePlanningDocument.storage_locator`
- `ExpenseCategoryMonthly.source_ref_id`
- `Feedback.app_version`
- `Feedback.build_sha`
- `Feedback.disposition_note`
- `Feedback.dispositioned_by_user_id`
- `Feedback.internal_note`
- `Feedback.kind`
- `Feedback.message`
- `Feedback.route`
- `Feedback.user_agent`
- `Feedback.user_role`
- `Feedback.viewed_by_user_id`
- `Feedback.viewport`
- `JobRun.error`
- `JobRun.job`
- `LinkedAccount.institution_id`
- `LinkedAccount.plaid_access_token_encrypted`
- `LinkedAccount.plaid_account_id`
- `LinkedAccount.plaid_item_id`
- `LinkedAccount.plaid_transactions_cursor`
- `MonteCarloSimulation.input_data_hash`
- `PasswordResetToken.token`
- `PdfExportJob.content_sha256`
- `PdfExportJob.result_ref`
- `PlanDocument.content_sha256`
- `PlanDocument.file_mime_type`
- `PlanDocument.storage_locator`
- `RiskGuardrailSurface.input_hash`
- `RothConversionPlan.optimizer_input_hash`
- `Scenario.primary_location`
- `Scenario.secondary_location`
- `StatementTransaction.external_id`
- `Subscription.stripe_customer_id`
- `Subscription.stripe_subscription_id`
- `Transaction.plaid_transaction_id`
- `User.external_provider`
- `User.external_subject`
- `User.password_hash`
- `UserMfaChallenge.challenge`
- `UserMfaTotp.backup_codes`
- `UserMfaTotp.secret_encrypted`
- `UserWebAuthnCredential.credential_id`
- `UserWebAuthnCredential.device_type`
- `UserWebAuthnCredential.public_key`
- `UserWebAuthnCredential.transports`

### Sent, but scanned for your values first — 6 fields

- `ScenarioLever.trade_off`
- `StatementTransaction.description`
- `StatementTransaction.merchant`
- `Transaction.description`
- `Transaction.merchant_name`
- `UndoLedger.label`

### Sent as-is — not identifying — 55 fields

- `AdvisorBillingTransaction.type`
- `AdvisorFirmBrandingProfile.accent_color`
- `AdvisorFirmBrandingProfile.primary_color`
- `AdvisorMarketplaceProfile.specializations`
- `AdvisorPlanVariance.target_key`
- `AdvisorPlanVariance.target_ref`
- `AdvisorPlanVariance.variance_type`
- `AiInsightUsage.model`
- `AiMessage.model`
- `Beneficiary.relationship`
- `Budget.effective_month`
- `Budget.expense_category`
- `CashFlowProjection.random_seed`
- `CashFlowProjectionHistory.random_seed`
- `CashFlowProjectionHistory.snapshot_reason`
- `ClientDeliverableAudit.action`
- `ClientTask.destination_route`
- `CompanionExchange.model`
- `CompanionExchange.route`
- `DocumentType.code`
- `DocumentType.label`
- `EmailNotificationPreference.opted_in_method`
- `EmailNotificationPreference.opted_out_method`
- `EstatePlanningDocument.document_type`
- `ExpenseCategory.code`
- `ExpenseCategory.label`
- `ExpenseCategoryRule.pattern_type`
- `LinkedAccount.account_subtype`
- `LinkedAccount.account_type`
- `LlmUsage.consumer`
- `LlmUsage.model`
- `LongTermCareCost.state_code`
- `LongTermCareCost.state_name`
- `MarketplaceAuditEvent.event_type`
- `MonteCarloSimulation.random_seed`
- `PlanComment.action_href`
- `PlanComment.ai_model`
- `RealEstateProperty.state`
- `RiskGuardrailSurface.random_seed`
- `Scenario.primary_marital_status`
- `Scenario.secondary_marital_status`
- `SpendingPattern.pattern_type`
- `StateTaxProfile.source_note`
- `StateTaxProfile.state_code`
- `StateTaxProfile.state_name`
- `StatementUpload.mime_type`
- `StatementUpload.parser`
- `SystemSetting.category`
- `SystemSetting.description`
- `SystemSetting.key`
- `SystemSetting.label`
- `SystemSetting.updated_by`
- `Transaction.expense_category`
- `Transaction.plaid_category`
- `User.state`
