Data requests
On this page
privacy: in app.jadpo turns on generated routes for a person's
requests to export or erase their data. Jadpo generates the endpoints
only, never the pages: your frontend builds the page, and a recipe can
show you one. There are three ways a request starts.
Self-service by email
privacy: { self_service: {} } turns it on. Anyone can ask by email
address, without signing in:
- Your frontend posts the address to
POST /privacy/requests(address). It answers202for every address, so it never reveals who has an account, and sends an email to check the address. - The email's single-use link opens your frontend's path, set as
self_service: { link: "/privacy/confirm" }, at the browser origin, with a token. - That page posts
POST /privacy/requests/confirm(token, andkind:exportorerasure) to create the request. - The erasure confirmation email has a cancel link, which opens
self_service: { cancel_link: "/privacy/cancel" }. That page postsPOST /privacy/requests/cancel(token).
Loading a frontend page uses up nothing, so a mail scanner that follows the links confirms and cancels nothing.
Signed in
POST /privacy/export and POST /privacy/erasure need a recent sign-in
(RouteAuthentication.fresh)
and act only on the caller's own record: there is no person id to pass.
Export answers 202 and delivers a download link when it is ready.
Made by staff
Requests received by email or phone are made through generated actions,
after staff have checked who the person is. You grant them in
policy.jadpo, as privacy.create_request: [StaffRole.support]. Each
request records who created it and how the person's identity was
checked. The export still goes to the person's own email, never to the
staff member.
A schedule or subscriber never makes a request. The only erasure that happens on a schedule is retention's.
Exports
An export is delivered as a single-use download link that expires after 7
days, never as an attachment. The file is encrypted at rest and deleted
when the link expires, and every download is in the access records. You
set where the files are kept in privacy: { exports: { store: keep: } }.
Erasures
An erasure waits out a cooling-off period your app sets, 14 days by
default, and the confirmation email has a cancel link. The completion
email says what was kept and why, since the person must be told. So an
entity marked Erasure.retained needs a wording in its domain's language
files, which the email lists.
Deadlines and events
Every request is a record with its one-month legal deadline.
jadpo privacy requests and the console list them, and one nearing its
deadline raises an alert.
Each step emits an event: PrivacyRequestReceived, PrivacyExportReady
(with the download link), PrivacyErasureScheduled,
PrivacyErasureCompleted and PrivacyRequestOverdue. The built-in
emails are subscribers to these events. Your app can add its own, to
post to Slack or a CRM, say, or replace the emails. With no mail
connection, the compiler requires a subscriber that delivers
PrivacyExportReady.
Protection
The routes have rate limits, their links are single-use and short-lived, and every step is in the access records.
Changing the routes
These routes take path: and routes: false like every
generated route. They run over generated
privacy.request, privacy.confirm and privacy.cancel operations,
which keep every protection.
The privacy emails
The privacy emails are the address check, export ready, erasure confirmed and erasure completed. They are built-in emails, which you can change as much as you need, in five levels:
- Jadpo's own email, as it comes.
- Its words, changed in the root
translations/folder underjadpo: { }(Translations). - Your app's shared email layout.
- Your app's own
EmailMessage, withemail:. - Your app's own sending, with
send:.
They go through your app's one email: connection in application { },
and need application { display_name: }.
Each email has a built-in type, and a request type for send::
PrivacyAddressCheckEmail, PrivacyExportEmail,
PrivacyErasureConfirmedEmail and PrivacyErasureCompletedEmail. You set
them in privacy: { emails: { address_check: { } export_ready: { } erasure_confirmed: { } erasure_completed: { } } }. Each entry takes
email: or send:, never both. Their fields are on the
Built-in services page.
Markdown for agents: /docs/data-requests.md.Built from Jadpo main at a707efb.