# Keel — compliance checklist (v1)

Data protection: India DPDP Act 2023 (no GDPR/CCPA — Indian firms and companies only). Keel is a data processor for the firm (fiduciary) over director/member personal data; statutory registers are processed under a legal obligation, so erasure is answered with the retention basis, not deletion.

- [ ] Privacy notice (v1.4) shown before any seat holder's first use → `/seat/:token` consent card; `/privacy` page → Pass: no seat route works until `consents.accepted_at` is set for that seat; notice version stored with timestamp and IP.
- [ ] Firm users accept terms of use at invitation acceptance → `/invite/:token` → Pass: `users.terms_accepted_at` set before first sign-in; `/terms` page has real content (processor role, retention, escrow/export, liability cap).
- [ ] Purpose limitation per seat → seat scope enforced server-side (founder: own company; investor: cap table + published numbers; auditor: chained period, read-only, window) → Pass: any request outside scope returns 403 with a plain message.
- [ ] Consent withdrawal by the data principal → seat holder's own settings "Withdraw consent" → Pass: seat closes immediately, firm's Seats page shows "withdrawn", logged in `firm_log`.
- [ ] Revocation by the firm recorded and immediate → Seats → "Revoke and end access now" → Pass: token invalid on next request; log row written.
- [ ] Data-principal access/correction requests answered with retention basis → `/privacy` explains; corrections are new events, never edits → Pass: text present; no update/delete on `events`.
- [ ] Retention: chain kept 8 years from FY end; support access logged → `/privacy`; `firm_log` → Pass: stated; every Keel-admin view of a firm writes a log row the firm can see (Settings → Access log).
- [ ] Breach notice contact → `/privacy` names an e-mail → Pass: present.
- [ ] Personal data hosted in India → README deployment note; `/privacy` states region → Pass: stated; no third-party analytics or CDN script tags.
- [ ] No tracking cookies; only session storage and one functional cookie-free bearer token → Pass: no cookie banner needed; stated on `/privacy`.
- [ ] Sign-in security proportionate to statutory records → TOTP required for firm users; 12-hour sliding sessions; lockout after 10 failures/15 min → Pass: observable on `/api/auth/*`.
- [ ] s.63 BSA certificate of extract wording → `/packs` extract → Pass: certificate carries Part A statement (person in charge), the chain range, head hash, anchor reference, verification URL and "Keel Registrar Systems" as system operator line; states it is an extract, not legal advice.
- [ ] Rules are estimates until reviewed → every computed exposure carries "as the rules compute it; MCA computes the actual" → Pass: caption text present wherever a fee is shown; rules file version shown in rail footer.
- [ ] "Keel does not file" is stated wherever an SRN is entered → SRN drawer → Pass: text present.
- [ ] Assist outputs are labelled and never write → every assist box shows "draft · assist · not in the chain" and sources; no assist route can call the event store → Pass: code review of `Assist.php` (no EventStore use); label present in UI.
- [ ] Optional LLM use disclosed and off by default → `/privacy`; Settings shows "assist model: none" unless `KEEL_ASSIST_KEY` set; only register text of the firm's own companies is sent, never seat holders' contact data → Pass: env unset = deterministic assist only; stated.
- [ ] Accessibility (WCAG 2.1 AA basics) → all screens → Pass: focus visible (2px), every input labelled, colour never the only signal (word-pills), contrast ≥ 4.5:1 on text, 44px targets on the founder phone, keyboard reachable palette/drawers/Esc.
- [ ] Uploads restricted → `/api/upload/*` → Pass: xlsx/csv/pdf/png/jpg only, ≤ 25 MB, stored outside web root with random names, served via signed route, never executed.
- [ ] Open-source licences → README "Licences" → Pass: only MIT/BSD/Apache dependencies (React, Vite, react-router, SheetJS community edition is Apache-2.0); no copyleft; attribution list present.
- [ ] Payments: none in v1 (invoiced off-platform) → Pass: no card fields anywhere.
- [ ] Age: professional users only; no under-18 flows → Pass: terms state users must be 18+.
- [ ] E-mail: transactional only (invitations, resets, reminders, seat requests), each with the firm named and a plain reason → Pass: no marketing mail; reminders configurable in Settings → Notifications.
