Information Security Policy
Organization: Bradley Mayer, operating Mayer Money Owner: Brad Mayer Effective: 2026-11-10 · Next review: 2027-11-10, or sooner after any security incident or major change
This policy is published. It describes systems by what they do, not by their internal names or addresses; those are kept in the private setup notes.
1. Purpose and scope
Mayer Money is a private, self-hosted budgeting app used by one household (Brad and Ashleigh Mayer). It reads transaction and balance data from the household's own bank accounts, through Plaid and through CSV files the household downloads itself. It has no outside customers, sells nothing, and shares data with no one.
This policy covers:
- The Mayer Money application and its source code, kept in a private code repository.
- The home server that runs the app in a container, and the storage on it that holds the app's data.
- The admin accounts used to run it: the home server's administrator accounts, the code repository, the Plaid Dashboard and the private remote-access network.
- The owner's computer when it is used to develop the app or read the app's data.
Consumer financial data here means any transaction, balance, account name or bank connection token, whether it came from Plaid or from a bank CSV.
2. Roles
| Role | Who | Responsibilities |
|---|---|---|
| Security owner | Brad Mayer | Owns this policy and the others that go with it. Approves access, runs reviews, handles incidents, holds all admin accounts. |
| Household member | Ashleigh Mayer | Signs in to Mayer Money with a read-only account. No admin access to the app, the home server, the code repository, Plaid or the remote-access network unless granted by the owner. |
| Developer | Brad Mayer, with an AI coding assistant on the owner's computer | Changes code through the private repository only. Never commits financial data. Tests on a copy of the data, never the live data. |
Access rules are in the Access Control Policy.
3. How the system is protected
Network. The app is not exposed to the internet. No router ports are forwarded to it. Remote access goes only through a private, identity-based network (Tailscale): a device must be signed in to the owner's account before it can reach the app. Remote connections use HTTPS with a publicly trusted certificate. The home network's gateway filters DNS.
Every request is checked. Being on the home network or the private network is not enough. Every page and API call, except a health check that returns only the code version and the app's static code files, requires a signed-in session. Every request that changes data must also come from the app's own origin.
Sign-in. Named accounts only, no shared logins. Every sign-in needs a password and a six-digit code from an authenticator app (Microsoft Authenticator, Google Authenticator or similar). There's no way to skip the code: someone who hasn't set up an app is shown a QR code and can't get in until they do. Passwords are at least 8 characters and stored only as salted scrypt hashes. A code works once. Five wrong passwords or codes lock a name for 15 minutes; 20 from one address lock that address. Sessions are signed, HttpOnly, SameSite=Lax cookies that last 30 days. Changing or resetting a password signs that person out everywhere else.
Roles. Each account is Admin or Read only, checked by the server on every request. See the Access Control Policy.
Tokens and keys.
- Plaid access tokens are encrypted at rest (Fernet: AES-128 with an HMAC integrity check). The encryption key is stored apart from the app's data, so backups of the data never carry a working token.
- The Plaid client ID and secret live only in the app's settings file on the home server.
- The key that signs sign-in cookies is 32 random bytes, created on first start.
- The home server pulls code from the repository with a read-only key.
- None of these are ever stored in the code repository, which is set up to refuse key, settings, database and CSV files.
- Plaid tokens and sign-in accounts are never included in data exports.
File permissions. On every start the app resets its data, settings and key files so only the home server's administrators can read them, and new files are never readable by other accounts.
Bank sign-in. Banks that support it use their own sign-in page through Plaid (OAuth). Mayer Money and Plaid never see the bank password. The Plaid connection is read-only (Transactions product): it cannot move money.
Audit trail. Every budget edit is kept with who made it and when. Account changes record who created or last changed each sign-in.
Backups. The app copies its database and data files daily and keeps 30 days. Retention and deletion rules are in the Data Retention and Deletion Policy.
4. Multi-factor authentication
MFA is required on every account that can reach consumer financial data or change the system:
| System | MFA requirement |
|---|---|
| Mayer Money (where Plaid Link runs) | Built in and required for every account: password plus a code from an authenticator app (time-based one-time codes, RFC 6238). Applies at home and remotely. Remote access also needs a device enrolled in the owner's private network. |
| Private remote-access network | MFA on the identity provider account used to sign in. |
| Plaid Dashboard | MFA turned on. |
| Code repository | Two-factor authentication turned on. |
| Home server admin accounts | 2-step verification turned on. |
| Email and identity account used for the above | 2-step verification turned on. |
5. Vulnerability management
Scanning. These run on a schedule:
| What | Tool | How often |
|---|---|---|
| Software packages the app uses | Dependabot alerts on the repository, plus pip-audit before each release |
Continuous / each change |
| App code | Automated code scanning | Each change |
| Home server firmware and apps | The server vendor's security scanner | Weekly |
| Base container image | Check for a newer patch release and recreate the container | Monthly |
Patching deadlines (SLA). From the day a fix is available:
| Severity (CVSS) | Fix within |
|---|---|
| Critical (9.0–10) | 7 days |
| High (7.0–8.9) | 30 days |
| Medium (4.0–6.9) | 90 days |
| Low (below 4.0) | Next planned update, or accepted with a note |
If a fix can't be applied in time, the owner writes down why and what reduces the risk meanwhile (for example, turning off the affected feature or removing a bank connection) in the log below.
How updates ship. Code changes are tested on a copy of the data on the owner's computer, then published to the repository; the home server picks them up within 5 minutes. Package versions are pinned, so every update is a reviewed change.
Vulnerability log. Findings, what was done, and any exception to the deadlines above.
| Date | Finding | Action |
|---|---|---|
| 2026-11-10 | First Dependabot scan: 9 alerts (4 high, 3 medium, 2 low) in cryptography 46.0.3, markdown 3.7, flask 3.1.1. Some fixes had been out for months, before scanning or this policy existed. Real exposure was low: the app uses only Fernet from cryptography (none of the flaws are in it), renders only its own policy files with markdown, and has no shared cache in front of it. |
Upgraded to cryptography 50.0.2, markdown 3.11.3, flask 3.1.3. pip-audit clean. Tested on a data copy: saved bank connections still decrypt, every page loads, policy pages render identically. |
6. Development rules
- No financial data in the repository, ever. Test data stays outside it.
- Never edit the live data or the server's copy of the code directly.
- Changes to categorization or balance math are shown with before/after numbers before they ship.
- Secrets are never pasted into chat tools, tickets or commit messages.
7. Incidents
A security incident is anything that may have exposed financial data or a credential: a lost phone or laptop that was signed in, an unknown device on the private network, an unknown sign-in, a leaked key, or a breach notice from Plaid or any provider listed in section 4.
- Contain (same day): remove the device from the private network; reset the affected Mayer Money passwords (this signs that person out everywhere); rotate whatever key leaked (Plaid secret in the Plaid Dashboard, the repository's read-only key, the cookie-signing key, or the bank-token key by disconnecting and reconnecting the bank).
- Assess: check the app's edit history, its logs, and the private network's device and sign-in logs.
- Notify: if Plaid-sourced data may have been exposed, tell Plaid (security@plaid.com) and the affected household members promptly, and within 72 hours at most.
- Record what happened and what changed in the log below.
8. Policy review
Reviewed once a year, after any incident, and when the system changes in a way this document doesn't describe.
| Date | Change | By |
|---|---|---|
| 2026-11-10 | First version | Brad Mayer |
| 2026-11-10 | Internal names and addresses removed so the policy can be published | Brad Mayer |