refactor: architecture revision — modular monolith, auth-commit, event protobuf, privacy-from-day-0
- ADR-0003: modular monolith for Phase 0 with documented extraction triggers - ADR-0004: Auth.js + OIDC-shaped boundary; dedicated provider when mobile ships - ADR-0005: protobuf for events, OpenAPI for HTTP, schema-registry CI gate - New architecture docs: data-model, metrics (magic proxies), privacy (Phase-0 feature) - Prime directives updated: privacy-as-feature, modular-by-package-deployable-by-stage - Roadmap revised: Apple OAuth deferred to M1; web push in M1; k3s intermediate; tip-kind-aware UI - PLAN updated: Phase-0 deletion endpoint, metrics baseline, compose profiles, import-boundary lint - License decision in README (ARR with OSS plan in Phase 5)
This commit is contained in:
40
docs/architecture/privacy.md
Normal file
40
docs/architecture/privacy.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Privacy architecture
|
||||
|
||||
Privacy is a Phase 0 feature, not a Phase 5 compliance project. This doc is the minimum.
|
||||
|
||||
## Principles
|
||||
|
||||
1. **Data minimization.** Store only what we need for the tip. Raw task titles stay at Todoist; we store references + computed features. If a feature doesn't lift a metric, its input data doesn't get stored.
|
||||
2. **User-visible controls.** Every connection shows exactly which scopes we hold and what we've computed. One tap disconnects and revokes.
|
||||
3. **Deletion is real.** Deleting an account revokes provider tokens, purges credentials immediately, and soft-deletes user data for a 30-day recovery window, then hard-deletes.
|
||||
4. **No surprise sharing.** Cross-user / collaborative features are opt-in, per category, per integration.
|
||||
5. **Encryption in transit and at rest.** TLS everywhere; column-level encryption for credentials; disk-level for backups.
|
||||
|
||||
## Flows
|
||||
|
||||
### Connect
|
||||
User taps "Connect Todoist" → consent screen lists: scopes requested, what we store, what we compute, retention, revocation instructions → OAuth → stored credential is immediately testable and shows in `/connect`.
|
||||
|
||||
### Disconnect
|
||||
User taps disconnect → `Credential.revoked_at` set → provider-side revocation attempted (Todoist: token revocation endpoint) → credential erased on success → `credential.revoked` event → downstream modules drop associated cursors, caches, derived features for that `(user, provider)` pair.
|
||||
|
||||
### Delete account
|
||||
User taps "Delete account" in settings → hard confirm → `User.deleted_at` set, all sessions revoked, `user.deletion_requested` event fanned out → every module processes its portion (credentials revoked + purged; profile scrubbed; tip history anonymized to aggregate stats only or purged, per retention policy; events purged on schedule) → within 24 hours account is non-recoverable operationally; within 30 days all rows are hard-deleted.
|
||||
|
||||
### Export (Phase 2)
|
||||
`GET /me/export` returns a JSON bundle of everything we hold for the user: profile, consents, credentials-metadata (not secrets), events, tip history.
|
||||
|
||||
## Scope boundaries
|
||||
|
||||
Each integration declares the scopes it requests and the features it derives. The `Profile.consents` column is the source of truth; a scope removed from consent short-circuits derived-feature computation at the feature store.
|
||||
|
||||
## Audit
|
||||
|
||||
- Privileged actions (admin-initiated deletions, credential decryption outside the normal refresh path) go to an append-only audit log from Phase 0.
|
||||
- Per-user access log available via `GET /me/access-log` (Phase 2).
|
||||
|
||||
## Legal surface (Phase 0 minimum)
|
||||
|
||||
- Terms of Service + Privacy Policy documents shipped alongside the sign-in page.
|
||||
- Consent capture on first sign-in, with a versioned ToS/PP hash stored per user.
|
||||
- Data-subject request inbox (email) wired up before onboarding the first external user.
|
||||
Reference in New Issue
Block a user