Overview
PensionPortal.ai processes personal data for EU-regulated Irish occupational pension schemes under IORP II (S.I. 128/2021), DORA (EU 2022/2554), and GDPR (EU 2016/679).
This document is the primary compliance traceability record for PensionPortal.ai. Every control listed here points to a specific code location or runbook. Vague statements are not acceptable for a production system handling regulated pension data.
Art. 35 DPIA Outstanding: A Data Protection Impact Assessment is legally required before processing PPS numbers at scale. This has not yet been conducted. The DPIA must be completed before the platform goes live with real member data. Assign DPO ownership and schedule the DPIA immediately.
April 2026 Deadline: DORA ICT risk management framework documentation and third-party ICT provider registers must be finalised and submitted to the Pensions Authority by the next supervisory review cycle. Ensure the ICT Risk Management Policy (written policy #11) is reviewed and signed off by trustees before April 2026.
GDPR Article → Control Mapping
Implemented Controls
| GDPR Article | Requirement | Implemented Control | Code Location |
|---|
| Art. 5(1)(a) Lawfulness | Lawful basis for processing | Employment contract + legitimate interest (pension administration) | N/A — legal basis |
| Art. 5(1)(b) Purpose limitation | Data only used for pension admin | Role-scoped access (ActorContext), no data sharing outside tenant | src/lib/actor-context.ts |
| Art. 5(1)(c) Data minimisation | Only necessary data collected | PPS collected only when legally required; AI receives aggregates only | src/app/api/ai/chat/route.ts |
| Art. 5(1)(e) Storage limitation | Data not kept longer than necessary | 7-year retention for pension records; soft-delete preserves audit trail | src/db/schema/members.ts |
| Art. 5(2) Accountability | Controller can demonstrate compliance | Audit log on every state change with actor, timestamp, IP | src/lib/audit.ts |
| Art. 6 Lawful basis | Explicit lawful basis required | Contractual necessity (Art. 6(1)(b)) + legal obligation (Art. 6(1)(c)) | Documented in DPA |
| Art. 9 Special categories | Sensitive data requires explicit basis | PPS numbers encrypted; health data not collected | src/db/schema/members.ts |
| Art. 17 Right to erasure | Right to be forgotten | Soft-delete + anonymisation procedure | runbooks/backup-restore.mdx |
| Art. 25 Privacy by design | GDPR built into system design | PPS encrypted, AI data minimisation, role-scoped access | src/lib/actor-context.ts, src/lib/auth.ts |
| Art. 30 Records of processing | Register of processing activities | Document all data flows (this document) | docs-site/compliance.mdx |
| Art. 32 Security of processing | Appropriate technical measures | AES-256 PPS encryption, bcrypt passwords, HTTPS/TLS, audit logs | src/lib/auth.ts |
| Art. 33 Breach notification | 72-hour PA/DPC notification | Incident response runbook | runbooks/incident-response.mdx |
| Art. 44 Transfers | Restrictions on third-country transfers | Anthropic (US): SCCs in place; Vercel (US): SCCs in place | See vendor list |
Pre-Launch Requirements (Not Yet Implemented)
The following GDPR controls are required before production launch with real member data. Each item must be completed and verified before the platform processes personal data at scale.
| GDPR Article | Requirement | Planned Control | Status |
|---|
| Art. 13/14 Transparency | Privacy notice to data subjects | Privacy policy page at www.pensionportal.ai/privacy | Not started — Requires legal drafting |
| Art. 15 Right of access | Members can request their data | Self-service data export UI in admin panel | Not started — Manual process available via admin email |
| Art. 20 Data portability | Data in machine-readable format | Export endpoint at /api/members/[id]/export | Not started — Manual database export available |
| Art. 21 Right to object | Object to AI-assisted analysis | Opt-out flag on member record, honoured in AI pipeline | Not started |
| Art. 35 DPIA | Impact assessment for high-risk processing | Data Protection Impact Assessment for PPS processing at scale | Not started — Legal/DPO ownership required |
DORA Requirements → Control Mapping
| DORA Article | Requirement | Implemented Control | Runbook |
|---|
| Art. 5 ICT Risk Management | Written ICT risk management framework | ICT Risk Management Policy (11th mandatory policy under IORP II) | src/db/schema/compliance.ts (writtenPolicies) |
| Art. 10 Detection | Anomaly detection capabilities | Pino structured logging, health probe monitoring. Sentry integration planned. | runbooks/incident-response.mdx |
| Art. 12 Backup & Recovery | Data backup + RTO/RPO requirements | Neon PostgreSQL automated backups (daily), RTO: 4h, RPO: 24h | runbooks/backup-restore.mdx |
| Art. 13 Learning | Post-incident review | Incident review process | runbooks/incident-response.mdx |
| Art. 17 ICT Incident Reporting | Report significant incidents to PA | Incident response runbook with PA notification procedure | runbooks/incident-response.mdx |
| Art. 19 Testing | Regular operational resilience testing | Unit tests (Vitest), E2E tests (Playwright), annual TLPT | docs-site/deployment/vercel.mdx |
| Art. 24-27 Third-party ICT | Third-party ICT risk management | Vendor list + DPA agreements | See vendor list below |
| Art. 28 Register | Register of ICT third-party arrangements | Vendor/subprocessor list in this document | This document §5 |
Data Classification Inventory
| Data Category | Classification | Tables | Retention | Lawful Basis |
|---|
| PPS Numbers | PII — Highly Sensitive (encrypted) | members.ppsNumberEncrypted | 7 years post-scheme closure | Art. 6(1)(c) legal obligation |
| Member names, DOB, email | PII — Personal | members | 7 years | Art. 6(1)(b) contract |
| Scheme compliance records | Operational — Regulated | ora_reports, health_check_assessments, written_policies, acs_wizard | 7 years | Art. 6(1)(c) legal obligation |
| Audit logs | Operational — Security | audit_logs | Indefinite (regulatory requirement) | Art. 6(1)(c) legal obligation |
| KFH appointments | Operational — Regulated | key_function_holders | 7 years | Art. 6(1)(c) legal obligation |
| Contribution records | Financial — Regulated | contribution_periods, contribution_files | 7 years (Revenue requirement) | Art. 6(1)(c) legal obligation |
| AI-generated policy drafts | Operational | written_policies.aiDraftContent | Retained until broker deletes | Art. 6(1)(b) contract |
| RAG corpus | Regulatory Text (public) | rag_corpus | Indefinite | N/A (public documents) |
| Authentication credentials | Security | users.passwordHash | Active + 90 days post-deletion | Art. 6(1)(b) contract |
Vendor / Subprocessor List
| Vendor | Role | Data Processed | DPA Location | Transfer Mechanism |
|---|
| Neon (US) | PostgreSQL database hosting | All application data | Neon DPA at neon.tech | EU SCCs |
| Vercel (US) | Application hosting + Edge Network | Application code + logs | Vercel DPA at vercel.com | EU SCCs |
| Anthropic (US) | AI/LLM inference (Claude) | Scheme aggregates (NO PII) | Anthropic DPA at anthropic.com | EU SCCs |
| Resend (US) | Transactional email delivery | Email addresses + notification content | Resend DPA at resend.com | EU SCCs |
| Cloudflare (US) | CDN + WAF + DNS | HTTP headers + IP addresses (not body) | Cloudflare DPA at cloudflare.com | EU SCCs |
| Auth.js (Open Source) | Authentication library | N/A (self-hosted code) | N/A | N/A |
The openai npm package is imported as a dependency and is used as the client library for OpenRouter (RAG embedding generation via openai/text-embedding-3-small). It does not connect to OpenAI directly. Only Anthropic Claude is used for LLM inference. OpenRouter is used solely for vector embeddings.
Data Subject Rights Handling Process
Right of Access (Art. 15) — Manual Process
- Member or trustee submits request via email to admin@pensionportal.ai.
- 30-day response window begins from date of receipt.
- Admin exports member record from the database via admin panel or direct database query.
- Deliver response as an encrypted PDF to the data subject.
Planned improvement: A self-service data export UI in the admin panel is planned to reduce manual effort and response time. Until implemented, the manual process above fulfils the Art. 15 obligation.
Right to Erasure (Art. 17) — Implemented
- Request is received and evaluated against the legal obligation to retain pension records (7-year statutory hold).
- If no legal hold applies: anonymise the record — name replaced with
"DELETED", PPS set to null, email set to null.
- Soft-delete preserves the audit trail for regulatory purposes; the row is not physically removed.
Code location: src/db/schema/members.ts, Backup & Restore Runbook — Data Anonymisation
Right to Portability (Art. 20) — Manual Process
Member data can be exported as JSON via direct database query by a SuperAdmin.
Planned improvement: A dedicated export endpoint at /api/members/[id]/export is planned to enable programmatic data portability. Until implemented, manual database export fulfils the Art. 20 obligation.
Right to Object (Art. 21) — Not Yet Implemented
Member can object to AI-assisted analysis of their data. An opt-out flag on the member record is planned, which will be honoured in the AI chat pipeline (src/app/api/ai/chat/route.ts).
Until the opt-out mechanism is implemented, the AI assistant does not process any member PII — it receives only scheme-level aggregates. Individual member data is never sent to the AI provider (see AI Data Minimization).
Annual Compliance Statement (ACS) Process
The Annual Compliance Statement is legally required under Section 26T, Pensions Act 1990 (as amended).
- Due: 31 January annually
- Submitted to: Pensions Authority of Ireland
Process
- Broker opens the ACS Wizard in the PensionPortal.ai portal.
- AI pre-fills answers based on existing scheme data (written policies, health check assessments, ORA reports).
- Broker reviews and amends each answer.
- Dual trustee sign-off is required before submission.
- PDF is generated and submitted to the Pensions Authority.
Code locations:
- ACS Wizard UI:
src/components/compliance/AcsWizardForm.tsx
- ACS API route:
src/app/api/schemes/[id]/acs/route.ts