Financial reasoning rarely requires a person's identity
A portfolio workflow may need balances, holdings, tax lots, cash needs, risk tolerance, or a target allocation. It usually does not need an email address, phone number, Social Security number, or account number to calculate the answer. Combining those two classes of data in every prompt creates avoidable exposure without improving the analysis.
Privacy by design begins by separating them:
- Financial facts needed for the task can be preserved when they are relevant.
- Direct identifiers should be removed or replaced before model processing.
- Credentials and secrets should be removed, never used as continuity tokens.
- The relationship between an identifier and a protected reference should remain inside the narrowest application boundary that needs it.
That separation is data minimization in practice. It does not make the remaining financial facts harmless, and it does not remove the need for contracts, access controls, retention limits, or secure provider configuration. It makes one important data path smaller and safer.
Sometimes minimization means not collecting the data
Payment credentials illustrate a stronger privacy pattern. Rainlight now sends users
to Stripe's hosted billing portal to add or manage a payment method and does not render
PAN or CVC inputs. The two former Admin API POST paths for manual card entry return
410 provider_managed_payment_methods, so an older client cannot silently restore the
retired application-side collection path.
For billing displays, reads use an explicit PAN/CVC-excluding projection rather than
selecting historical card-credential columns. It can still include personal billing
data such as cardholder name, billing address, and application metadata; those fields
remain subject to authorization, minimization, and retention. Canonical database SQL
keeps the legacy card_number_enc and card_cvc_enc compatibility columns in place
temporarily but requires both to be NULL. A focused regression test checks the UI,
retired API routes, service projection, and database constraint.
This is preferable to encrypting CVC or full card numbers inside the application: data that is not collected cannot leak from that application store. It reduces Celestice's payment-data and potential PCI DSS scope, but it is not a PCI compliance claim. The hosted integration, scripts, webhooks, authorization, incident response, and applicable self-assessment responsibilities still need periodic review.
The Admin API applies the same collection discipline to its browser-facing user-
integration routes. The self-scoped and legacy per-user POST paths return
410 provider_callback_required instead of accepting OAuth access, refresh, or ID
tokens. List, disconnect, and delete operations return an explicit metadata-only field
allowlist, and canonical SQL requires the legacy bearer-token columns to stay NULL.
The combined focused regression test covers these controls as well as the payment
boundary.
This claim is deliberately scoped to Admin API user integrations. A future OAuth connection still needs a validated server-side provider callback and an appropriate secret boundary. Financial-data connector credentials require a separate storage, encryption, rotation, logging, and access review; this control is not a claim of platform-wide secret handling or a complete OAuth implementation.
Authentication data follows a related non-replication rule. Rain's canonical
auth.users schema does not represent the upstream Supabase password hash or the
top-level confirmation, recovery, email-change, and phone-change one-time-token
fields. Internal synchronization uses an explicit allowlist projection, so those
upstream credential and OTP fields are ignored rather than copied into a second
application database. Regression tests and a clean canonical database deployment
exercise that boundary.
That guarantee applies to freshly created canonical databases and to the named top-level fields. Existing development databases must be recreated through the repository's canonical workflow to remove historical columns and data. Nested metadata and identity payloads are not recursively scrubbed by this projection, so they remain subject to separate inventory and minimization work.
One boundary for the shared agent path
A privacy control that developers must call manually in each prompt will eventually be missed. Celestice therefore places the control in shared context preparation rather than relying on every specialist agent to invent its own scrubber.
On the protected shared path, the filter runs before context can be sent to:
- a model used to compact or summarize a long conversation;
- the primary specialist model producing the response;
- a model evaluating response quality; or
- a model extracting information for long-term memory.
The Proposal specialist uses this shared boundary. The Director's model-assisted routing call applies the same privacy primitives and falls back to local routing rather than sending raw text when privacy configuration is invalid. OpenViking context integration protects stored content and uses purpose-scoped pseudonyms for explicit subject and agent identifiers.
This placement matters. Filtering only the final user prompt would leave older messages, system-added context, tool arguments, artifacts, evaluation payloads, and memory extraction as alternate routes. The Celestice filter recursively protects textual values in message content and structured model-bound fields, including tool calls and artifacts.
The same boundary also produces a non-sensitive report: policy version, operating mode, key version when relevant, and counts by transformed data class. Raw values and the internal purpose scope are excluded. That is useful evidence without turning the security log into another sensitive-data store.
Redaction and pseudonymization solve different problems
Celestice supports two transformations.
Redaction replaces a recognized value with a category marker such as
[EMAIL_REDACTED]. It is the safer default when downstream reasoning does not need to
know whether two occurrences refer to the same value.
Pseudonymization replaces a recognized identifier with a stable protected reference within a deliberately narrow scope. Two appearances of the same email can receive the same pseudonym for one user, agent, and purpose, while the same email receives a different pseudonym in another scope. This preserves limited continuity without creating a platform-wide tracking key.
The shared privacy filter derives those references with a keyed cryptographic function. It includes the environment, purpose, agent, and subject in the scope, and includes a key version so rotation can be controlled. The raw identifier and internal scope are not embedded in the output. Credentials are always redacted even when identifier pseudonymization is enabled.
Some systems use vault-backed tokens when an authorized application workflow must restore an original display value. That is a different pattern: the protected token map must remain inside the application boundary, be separately access-controlled, and be limited to the workflow that needs re-linking. A model should receive the token, never the map. Celestice's shared HMAC pseudonyms are not themselves reversible; they are stable, purpose-limited references.
The privacy effect of pseudonymization
This distinction is both technical and legal. Anonymization aims to make a person no longer identifiable by reasonable means. Pseudonymization keeps additional information that can distinguish or re-link records, even if that information is held separately. Under the GDPR definition, pseudonymized data remains personal data.
Pseudonymization reduces direct exposure and cross-context linkability while preserving the limited continuity a workflow needs. Celestice combines it with data minimization, tenant authorization, provider governance, access controls, retention practices, and customer configuration so each privacy layer has a clear purpose.
“The privacy boundary belongs before every shared model call—not in a promise that developers will remember to scrub one prompt at a time.”
Fail closed where the policy matters most
Production privacy controls should not quietly become optional because of a missing environment variable. The shared Celestice boundary rejects unsafe configuration:
- production code cannot disable the filter through normal agent configuration;
- pseudonymization requires adequate secret key material;
- unsupported modes and unsafe key-version labels are rejected;
- Director model-assisted routing falls back to a local, non-model path when privacy setup fails; and
- secrets, bearer tokens, and recognized credentials are redacted regardless of mode.
Keys belong in a deployment secret manager, not source code or logs. Environments should use different keys. Rotation deliberately changes the derived references, which prevents an old key from becoming a permanent correlation mechanism.
Current classifier coverage
The implemented text control recognizes several high-risk classes, including labeled names and addresses, email addresses, formatted phone numbers, Social Security numbers, dates of birth, validated payment-card patterns, IBANs, labeled financial account or routing numbers, IP addresses, and common credential forms. Validation is important: for example, card-like digit sequences are checked rather than blindly masking every long number.
Celestice continuously extends classifier coverage as international formats, document types, tool payloads, and financial-data structures evolve. Three practices keep that work systematic:
- keep the filter centralized so recognition can improve in one place;
- test the supported classes, nested payloads, bypass attempts, and failure modes; and
- inventory model clients and require the shared boundary or an equivalent tested control for each path.
Testing the negative space
The meaningful tests are not only “does an email become a marker?” They ask whether the value can escape through a less obvious field or secondary model call. Current tests cover:
- stable pseudonyms inside one scope and different pseudonyms across purposes;
- credential redaction even in pseudonymization mode;
- message cloning without mutating the raw application state;
- nested message content, tool arguments, metadata, and artifacts;
- content-free policy evidence;
- fail-closed production configuration;
- protection before main-model, compaction, evaluation, and memory calls; and
- protected Director routing, OpenViking context integration, and the migrated Proposal specialist path.
These regression tests make privacy review continuous. Every new model path passes through the canonical boundary or carries an explicit equivalent control and tests.
The takeaway
Celestice minimizes direct identifiers whenever the task does not require them, applies the rule consistently on shared model paths, and makes policy decisions visible through content-free evidence.
Pseudonymization is one layer of that design. Tenant-scoped authorization, encryption, retention and deletion, provider governance, trace protection, access review, and incident response remain separate controls. Privacy is strongest when each layer has a clear job and no single layer is asked to prove more than it can.



