Security
Effective 6 August 2026 · Last updated 6 August 2026
Citadel Money holds a household’s complete financial picture, and for couples it holds things one partner has not yet chosen to tell the other. This page describes what we actually do to protect that, and how to tell us if we have got something wrong.
Reporting a vulnerability
Email rick@yost.group with the subject line Security. Include what you found, how to reproduce it, and how you would like to be credited.
- We acknowledge every report within two business days.
- We will tell you what we found, what we are doing, and when it is fixed. If we disagree that it is a vulnerability, we will explain why rather than go quiet.
- We will not pursue legal action against anyone who reports a genuine issue in good faith, gives us reasonable time to fix it, and does not access, modify, or exfiltrate other people’s data in the process.
- Please do not run automated scans against production, attempt denial of service, or use another household’s account. If you need an account to test with, ask and we will provide one.
We do not currently run a paid bug bounty.
Authentication
- Passwords are hashed with Argon2id at the OWASP-recommended parameters (19 MiB memory, two iterations). We cannot read them, and we never transmit or log them.
- Email verification is required before any financial data persists to an account.
- Password reset tokens are single-use and expire in one hour. Resetting a password signs out every other session.
- Time-based multi-factor authentication is available, and a step-up challenge is required for the actions that could destroy or exfiltrate everything: exporting all data, and deleting a household.
- “Sign out everywhere” takes effect on the next request, not whenever a cookie happens to expire. Sessions carry a watermark that is moved forward on revocation.
- Session cookies are HttpOnly, SameSite=Lax, and Secure in production. Sign-in and password reset are rate limited, and failures never reveal whether an address has an account.
Authorisation
Every financial record belongs to a household, and the household is resolved from your session — never from anything the client sends. Service functions take the resolved household identifier, so there is no parameter for a caller to tamper with. Cross-household access is covered by automated tests that attempt it deliberately and assert it fails.
Partner privacy
The Couple Accord is the most sensitive data in the product, and it gets more than ordinary protection:
- Money-story reflections and financial snapshots are encrypted at the field level with AES-256-GCM, using a key held separately from the session secret. A database dump alone does not reveal them.
- Every read path filters on “has this been shared” in the SQL query. An unshared answer never leaves the database for anyone but its author.
- Unshared content produces no derived signal at all. Your partner is not told whether a draft exists, how long it is, or when it was edited — only that nothing has been shared. There is nothing to infer from.
Financial integrity
- Every amount is stored as an integer number of cents. Binary floating point is never used for money anywhere in the system.
- All calculations are performed server-side inside a database transaction. The browser never computes a balance you are asked to trust.
- Balances are derived by summing an append-only ledger rather than read from a stored counter, so there is no cached total that can silently drift.
- A nightly sweep re-checks the invariants the write path enforces — that allocations still sum to their transaction, that none crosses a household boundary, that no fund has a duplicate carry-forward. It reports; it never silently repairs.
- Nothing with financial history is destroyed. Deleted transactions stay recoverable for 30 days; items and accounts with activity are archived rather than removed.
Payments and bank data
- Card details are entered into the payment provider’s hosted components and never reach our servers, which keeps our PCI scope at SAQ-A.
- Payment webhooks are signature-verified before parsing, deduplicated by event identifier, and applied only when newer than the state already stored — so a replayed or out-of-order delivery cannot change your plan incorrectly.
- When bank connections ship, credentials will go directly to the aggregation provider. We will never see them. Provider tokens are encrypted with a dedicated key, and only the last four digits of an account number are ever stored or displayed.
Application and infrastructure
- TLS for all traffic, with HSTS. A Content Security Policy,
X-Content-Type-Options,Referrer-Policy, and frame-ancestor restrictions are set on every response. - Encryption at rest for the database and its backups.
- Secrets are read from the environment and validated at startup; a misconfigured deployment refuses to boot rather than failing at a user’s first sign-in.
- Error responses carry a code, a message, and a request identifier — never a stack trace, SQL, a provider token, or a financial value.
- Data exports neutralise spreadsheet formula injection, so opening a CSV cannot execute anything.
- An append-only audit trail records who changed what and when, with sensitive fields redacted from the stored difference.
What we have not done yet
Being straight about this is part of the point of the page. As of the date above, the following are planned but not complete:
- An independent third-party penetration test.
- A documented backup restore drill against our recovery targets.
- A SOC 2 report. The controls are designed for it; the audit has not been performed.
This page will be updated when each is done, rather than claiming them in advance.
Incident response
If a breach affects your personal data we will notify affected households and the appropriate authorities as required by law, and tell you plainly what happened, what data was involved, and what we are doing about it. Our retention and deletion commitments are in the Privacy Policy.
Contact
Yost Group LLC — Rick Yost
rick@yost.group