# Security and redaction

## Credentials

NoticeFox has four bearer credentials. Each is a prefix followed by 32 random letters and
digits (about 190 bits), sent as `Authorization: Bearer <credential>`. The service stores
only their SHA-256 hashes, so it can't show you a token again: it is displayed once, when it
is created.

| Credential | Prefix | Held by | Can |
|---|---|---|---|
| Account key | `nfx_acct_` | Your apps, in iCloud Keychain | Everything for the account |
| Device credential | `nfx_dev_` | One device | Sync its inbox and register itself |
| Send token | `nfx_send_` | A sender: a script, Home Assistant, an agent, the CLI | Send, and read the status of its own messages and the names of your devices |
| Link poll secret | `nfx_poll_` | A device or the CLI waiting for a link approval | Poll and cancel its own link request |

What each may do, route by route: [Authorization](authorization.md).

## Keeping a send token safe

- **Prefer the header.** The simple endpoint puts the token in the URL path, where it can leak
  through shell history, proxy and server logs, browser history and chat-app link previews.
  Use `Authorization: Bearer` wherever the tool supports it.
- **One token per sender**, labeled with what uses it. Every notification shows "via
  <label>", so you can always tell which sender a notification came from, and revoke just
  that token from the app.
- **Narrow it.** A token can be limited to a scene allowlist, have URLs turned off (`url` and
  `image` then answer `422 urls_not_allowed`), drop its read scopes, and expire.
- **Agent tokens** (for AI agents) have URLs off by default, so an agent's notifications
  carry no link unless the person allows it.
- **Revoking** takes effect at once for new sends, and queued sends from the token are
  dropped.
- A link preview or preloader that fetches a simple-endpoint URL without a `message` sends
  nothing (`400 missing_field`).

## What the service logs (redaction)

The service's logger enforces these rules on every field, nested value and error message:

| Data | Logged as |
|---|---|
| Every credential (in full, in part, or hashed in a request), the `Authorization` and `NoticeFox-Merge-Key` headers | Never, not even a prefix or suffix |
| The send key in a simple-endpoint path | The route template `/v1/send/{send_key}`, never the path |
| Titles, subtitles, messages, scene parameters, URL titles | Never |
| `url`, `image`, `service_url` | The origin only (scheme and host) |
| APNs device tokens | The last 6 characters |
| Client IP addresses | A SHA-256 hash only |
| Public ids: `request_id`, message ids (`ntf_…`), account ids, token ids, link grant ids, device ids, token labels | As they are |

Error messages never contain secrets or message text, and errors never say whether a
resource exists for someone else: another account's message or token is `404 not_found`.

## Accounts and data

- Accounts are anonymous: no Apple ID, email or name is stored.
- "Delete my data" in the app deletes the account, its devices, tokens and message history.
  A push already handed to Apple may still arrive.
- Messages stay in the inbox history for 30 days.
