Privacy notice
Last reviewed 2026-05-17. Served live at /privacy.
How eudr.dev processes personal data under Regulation (EU) 2016/679 (GDPR).
Roles
- Controller: the operator running due diligence. Reg. (EU) 2023/1115 imposes the obligation; the operator decides what is processed and why.
- Processor: Vortx AI Private Limited, operating
eudr.dev, acting on the controller's instructions. - Sub-processor:
emem.dev(Vortx AI Private Limited). Receives plot geometry, HS code, country, quantity only. No operator or supplier identity is sent.
Lawful basis
Art. 6(1)(c) GDPR. Legal obligation. The obligation is the EUDR due diligence duty (Reg. 2023/1115 Arts. 8–12 + Annex II).
What we process
Per task:
| field | category | why we need it |
|---|---|---|
| Operator name, address, EORI | identifying data (personal when natural-person operator) | required by Annex II point 1 |
| Supplier name and identifier | identifying data | required by Art. 9(1)(e) and (a) |
| Product HS code, description, quantity | commercial metadata | required by Annex II point 2 |
| Plot geolocation (Polygon or Point) | location data; may be personal when it identifies a smallholder | required by Annex II point 3 + Art. 9(1)(d) |
| Country of production, harvest window | regulatory metadata | required by Annex II point 3 + Art. 9(1)(c) |
No special categories (Art. 9 GDPR), no children's data, no behavioural profiles.
Connector surface
The operator can supply a Scenario through three inbound surfaces: the
dashboard form, a CSV upload, or a POST of a GS1 EPCIS 2.0 document.
The CSV and EPCIS connectors parse the payload locally inside the
engine and emit Scenario objects which then run through the same
pipeline as a hand-entered scenario. The connector layer does not
transit the data to any new third party, so the same Art. 6(1)(c)
GDPR basis (legal obligation under Reg. 2023/1115) applies, and the
sub-processor list is unchanged.
Data minimisation
- Logs record
task_id, stage names, state transitions. No operator or supplier identifiers in general logs. - The pipeline event stream is per-task; only the subscribed SSE client receives it.
- The agent sends plot geometry, HS code, country, quantity to
emem.dev. Identities stay in the agent. - No external fonts. Analytics (Google Analytics 4) loads only after explicit cookie consent and defaults to denied — see the Cookies section and the processor table below. No other third-party trackers.
Retention
| layer | retention | basis |
|---|---|---|
| Operator's own archive | 5 years from DDS submission | Reg. 2023/1115 Art. 4(3), Art. 9(1), Art. 12(5) |
eudr-a2a working memory | configurable, default 7 days | data minimisation, Art. 5(1)(c) GDPR |
An in-process background sweep enforces the 7-day window
(EUDR_TASK_RETENTION_DAYS). After eviction the receipt CID is still
re-derivable from the operator's archived receipt; the agent itself
keeps no trace of the scenario.
Retention sweep. What runs
Hourly the server (a) purges in-memory Task entries older than the
configured horizon and (b) issues a SQL DELETE FROM shipments WHERE created_at < cutoff AND erased_at IS NOT NULL against the SQLite
store. The DB sweep only touches rows that have already been through
controlled erasure (their annex_ii_json / scenario_json are already
NULL); rows still carrying the live operator payload are out of scope
and remain available for the 5-year regulatory audit. The number of
rows evicted in each pass is logged at INFO level (shipment retention sweep) so an operator can confirm the sweep is healthy.
Your rights
| right | how |
|---|---|
| Information (Art. 13/14) | This notice + the engine's compliance audit at COMPLIANCE.md. The engine also serves /privacy live and surfaces every data-source citation in every DDS receipt. |
| Access (Art. 15) | GET /app/api/account/export returns everything we hold on you as a single JSON file — user record, every org you belong to, shipments per org, API keys (hash + last-four only, never the raw key), connectors, payment methods (vault token id only, no card data). |
| Rectification (Art. 16) | Edit your details in the dashboard or re-submit the corrected scenario. The previous task can be erased with DELETE /a2a/tasks/:id. |
| Erasure (Art. 17) | Two paths: (1) DELETE /a2a/tasks/:id scrubs scenario_json + annex_ii_json for one task; (2) DELETE /app/api/account does the same for every shipment you created AND deletes the user row + revokes all sessions. The audit-aggregate columns (HS code, country, quantity, verdict, receipt CID, DDS reference) and the audit-log table are retained for the regulation-mandated record under Art. 17(3)(b) GDPR + EUDR Art. 4(3), 9(1), 12(5). |
| Restriction (Art. 18) | Contact the deployer. Cookie-revocation + signing-out happens client-side; deeper restriction (suspending re-attestation, freezing a record) is operational and handled by the deployer's controller. |
| Portability (Art. 20) | The Art. 15 export is the portability artifact: a single JSON file in a structured, commonly-used, machine-readable format (RFC 8259 JSON) that another controller can import. |
| Object (Art. 21) | The lawful basis is Art. 6(1)(c) (legal obligation), so the absolute Art. 21(1) right to object does not apply. For any processing the deployer ever extends beyond the EUDR mandate (e.g. analytics), Art. 21 applies and the deployer must offer an opt-out. The shipped engine performs no such extended processing. |
| Automated decision-making (Art. 22) | The engine emits a risk verdict from satellite + country-tier signals. The verdict is explainable (every input is on the receipt) and non-final — the operator retains the legal decision to submit. Art. 22 is therefore not triggered, but the engine is built so a human can audit and override at every step. |
| Lodge a complaint | With your national supervisory authority. For EU residents the lead authority depends on the deployer's establishment. |
Requests against eudr.dev should be sent to avijeet@vortx.ai. The endpoints above are also exposed in-app for signed-in users.
Audit-log content (what survives erasure)
The audit_log table records:
- Sign-in events (actor = user id, no IP in clear, no email body in clear)
- Shipment compile events (subject =
sha256(shipment_id || EUDR_AUDIT_SALT)truncated to 16 hex chars. The receipt CID indetails_jsonis the authoritative anchor; the pseudonymised subject lets us replay an audit without exposing a row id that could be used to enumerate live shipments) - API-key issuance and revocation (subject = key id, never the raw key)
- Account-deletion event (subject = the user id at deletion time; the row stays as a tombstone)
No PII is in the audit-log free-text fields. The details_json field carries only counts and identifiers. Salt precedence at boot: EUDR_AUDIT_SALT env-var (operator override) → persistent instance_salt table row (self-seeded on first start, stable across reboots) → per-process random fallback if both are unavailable. The persistent row keeps shipment subject pseudonyms consistent across reboots without the deployer having to manage the secret out-of-band.
Security
- Receipts: ed25519 signature over canonical JSON. CID changes on any byte change; offline verify against the agent pubkey.
- Session cookie:
HttpOnly,Secure,SameSite=Lax,__Host-prefix over HTTPS. - CSRF: cookie-authenticated mutations require
X-Requested-With: eudr-app. - Sign-in rate limit: 5 magic links per email per hour, 30 per IP per hour.
- Magic links: 32 bytes CSPRNG hex, SHA-256 at rest, single use, 15-minute TTL.
- Production: TLS terminator in front,
EUDR_AGENT_PRIVKEY_B64set to a real 32-byte secret (the server refuses to boot with the dev key over HTTPS).
Trusted proxy
The server reads the originating client IP from the direct TCP peer
by default. X-Forwarded-For and X-Real-IP headers are only
honoured when the peer is in the deployer-configured allow-list
EUDR_TRUSTED_PROXY_IPS (comma-separated, IPv4 or IPv6; empty by
default). Without this list set, an attacker could attach any header
and have it logged as their IP. Art. 32 expects forgery defence on
identifiers used for rate-limiting and audit. Behind nginx /
Cloudflare / a load balancer, list the proxy's IP(s) here so the
forwarded address is honoured; everywhere else, leave it empty.
Session re-validation: each authenticated request hashes the current
peer IP and compares it to the hash stored at sign-in. Drift is
logged as a WARN with the first 8 chars of the session id (no IP,
no email). Sessions are not auto-revoked. Mobile users on cellular
networks legitimately change IP, but the drift signal is available
for the deployer's SOC to act on.
Third-party processors and independent controllers
eudr.dev engages a small number of third parties. Some are
processors under Art. 28 GDPR (they process on our instructions);
some are independent controllers (they decide on their own how they
process the data they receive). The split matters for the legal
basis and the data-subject's rights.
Processors (Art. 28 GDPR)
| Name | What it sees | Location | When it runs |
|---|---|---|---|
emem.dev (Vortx AI Private Limited) | plot geometry, HS code, country, quantity (never operator or supplier identity) | India / global responders | Every DDS compile |
| AWS EMEA SARL — compute + SES | the live operator data while a request is being served; outbound magic-link email recipients | eu-central-1 Frankfurt (compute), eu-north-1 Stockholm (SES) | Always |
| Google Ireland Limited (Google Analytics 4) | pseudonymous visitor identifier (_ga), URL paths visited, basic device class, IP (anonymised before processing) | EU/EEA collection endpoints, onward transfer to Google LLC (US) under the EU-US Data Privacy Framework | Only after the visitor clicks "Accept analytics"; default is denied |
Independent controllers (not our processors)
| Name | What it sees | Location | When it runs |
|---|---|---|---|
| PayPal (Europe) S.à r.l. et Cie, S.C.A. | the buyer's payment data | Luxembourg for EU buyers | The Customer chooses card / PayPal settlement |
| x402 facilitator | settlement-layer wallet address + amount | Per-deployer choice | The Customer enables x402 |
| TRACES NT (DG ENV, European Commission) | the filed DDS document | Brussels | The operator submits the DDS through TRACES |
The full catalogue with lawful-basis routes and the 30-day change-
notice procedure is at /legal/subprocessors.
No other third-party network calls happen during data entry. Leaflet
and Leaflet.Draw are vendored under /console/vendor/. No CDN, no
basemap tile server. The polygon editor draws on a local grid canvas.
emem.dev is a transfer outside the EEA. Data transferred: plot
geometry, HS code, country, quantity. Where a plot polygon is personal
data of a smallholder, the flow is intra-entity remote processing
(eudr.dev and emem.dev are operated by the same legal person), assessed
and protected per the Transfer impact assessment —
identity is stripped at source and Art. 6(1)(c) (the EUDR
due-diligence duty) is the processing basis.
To add a basemap, re-enable L.tileLayer(..) and update this notice
to disclose the new processor.
Cookies
Four strictly-necessary cookies (no consent required under Art. 5(3)
ePrivacy + EDPB Guidelines 2/2023): __Host-eudr_sid (or eudr_sid
on localhost HTTP), eudr_csrf, eudr_locale, and eudr_consent
(records the analytics-consent choice itself). Two analytics cookies
set only after explicit Accept: _ga and _ga_C654QTBTFX (Google
Analytics 4, default denied via Consent Mode v2). Full inventory at
/legal/cookies. The consent banner appears on
the first visit; "Manage cookies" in the footer reopens it.
Contact
Security: avijeet@vortx.ai (see /.well-known/security.txt).
Privacy queries: contact the deployer of the specific instance. The
deployer is the controller.