Data Subject Access Request (DSAR) Procedure
[PLATFORM PROVIDER] — Internal Operational RunbookLast Updated: [DATE]
Internal operational runbook. This procedure guides [PLATFORM PROVIDER]'s response to GDPR data subject rights requests. It is published on the legal documentation site alongside the customer-facing policies.
GAP-GOV-03 · GOVERNANCE — KNOWN GAP, REMEDIATION PENDING
This procedure previously stated on its face that it is for internal use only and is not published to customers or attendees. It is in fact registered in the published legal navigation of this documentation site, which requires no authentication and indexes the whole corpus in its site search, so the operational detail it contains — including the rights-request gaps recorded below — is public. This divergence is recorded on the compliance remediation register and is under review.
1. Overview
Under GDPR Articles 12–22, individuals (Data Subjects) have rights regarding their personal data. Since [PLATFORM PROVIDER] acts as Data Processor, most GDPR requests are received by Customers (Data Controllers) and forwarded to [PLATFORM PROVIDER] for assistance. However, Data Subjects may occasionally contact [PLATFORM PROVIDER] directly.
Response SLA: 5 business days from receiving a valid, complete request (per DPA Section 7.2).
Statutory deadline: the Controller must respond within 1 month of receipt, extendable by 2 further months where the request is complex or numerous (GDPR Art 12(3)). The five-business-day figure above is an internal target agreed with Customers; it is not the statutory limit, and it does not displace the Controller's obligation.
2. Types of Requests
| GDPR Right | Article | Description |
|---|---|---|
| Right of Access | Art 15 | Data Subject requests a copy of all their personal data |
| Right to Rectification | Art 16 | Data Subject requests correction of inaccurate data |
| Right to Erasure | Art 17 | Data Subject requests deletion of their data ("right to be forgotten") |
| Right to Restriction | Art 18 | Data Subject requests temporary suspension of processing |
| Right to Portability | Art 20 | Data Subject requests machine-readable export of their data |
| Right to Object | Art 21 | Data Subject objects to processing (e.g., marketing, profiling) |
Which of these can be recorded as a request type. The GDPR request register accepts exactly five values — deletion, access, portability, objection and restriction — and the dashboard's New Request form offers the same five. An erasure is recorded as deletion. There is no rectification type: a request under Art 16 is fulfilled and evidenced as described in Section 5.3, not in the register.
3. Request Reception
3.1 Requests Via Customer (Normal Path)
- Customer receives DSAR from attendee
- Customer logs the request in the [PLATFORM PROVIDER] dashboard (GDPR → New Request, at
/gdpr). The form's only subject field is the SHA-256 hash of the Data Subject's email address, which is required; it is shown on the contact detail page and can otherwise be computed as SHA-256 of the lowercased, trimmed address. A request cannot be filed from a plaintext email address alone - The request is created with status
pending. There is no notification: no alerting integration exists, no message is sent, and nothing processes a pending request automatically. The only surfacing is a "Pending GDPR" count tile on the dashboard home page, which a member of staff must look at - [PLATFORM PROVIDER] team processes per Section 5 below and updates request status in dashboard
- Customer communicates outcome to Data Subject
Standing operational control. Because nothing surfaces a pending request except that count tile, a member of staff must review the GDPR page for pending requests at least once per business day. Requests raised by attendees through the self-service deletion route, and requests raised automatically by the email-change flow (Section 4), reach no one otherwise and will sit at pending indefinitely.
GAP-PROC-02 · PROCESS — KNOWN GAP, REMEDIATION PENDING
This procedure previously stated that [PLATFORM PROVIDER] receives a dashboard notification when a Customer logs a request, and that the erasure pipeline executes within 24 hours. Neither describes system behaviour: no notification, alerting or paging mechanism exists anywhere in the platform, and there is no timer, queue drain or scheduled job for GDPR requests — the pipeline runs only when a member of staff presses the process button, and then completes within the same request. This divergence is recorded on the compliance remediation register and is under review.
3.2 Requests Directly to [PLATFORM PROVIDER]
If an attendee contacts [PLATFORM PROVIDER] directly (e.g., emailing [PLATFORM PROVIDER LEGAL EMAIL] or [PLATFORM PROVIDER PRIVACY EMAIL]):
- Log the request — create entry in internal DSAR tracking sheet within 24 hours
- Acknowledge receipt only — email the Data Subject to confirm that the request has been received and is being forwarded to the Controller. Do not confirm an outcome, a timeline for fulfilment, or the existence of any particular data
- Identify the Customer — determine which org the Data Subject attended events for (ask for email address and event name/URL)
- Forward to Customer within 2 business days — notify the Customer org that a DSAR was received and provide the Data Subject's details. This deadline is a contractual term of the DPA (Section 7.3)
- Await Customer authorisation — [PLATFORM PROVIDER] does not respond substantively to the Data Subject, and does not fulfil any part of the request, without the Customer's authorisation
- Process as normal — once authorised, work with Customer to fulfil the request within the 5-day SLA
Note: Direct requests from Data Subjects to [PLATFORM PROVIDER] are unusual. As Processor, [PLATFORM PROVIDER]'s obligation is to assist the Controller (Customer), and the DPA commits [PLATFORM PROVIDER] to forwarding such a request to the Customer within 2 business days and not responding without Customer authorisation. Acting on a Data Subject's instruction without that authorisation would place [PLATFORM PROVIDER] outside the Controller's documented instructions (GDPR Art 28(3)(a) and Art 29). Technical capability to fulfil a request unilaterally — Postgres and Firestore deletion, for example — is not authority to use it.
3.3 Identity Verification
Before processing any DSAR:
- Verify the requester's identity to prevent unauthorized data disclosure
- For requests via Customer dashboard: Customer is responsible for identity verification
- For direct requests: ask the Data Subject to confirm their email address and the event they attended. If in doubt, do not process until identity is confirmed.
- Do NOT require excessive documentation (GDPR principle of not imposing disproportionate burden)
- Note that a request is addressed by the email hash alone. Confirm that the hash entered corresponds to the verified address before processing: an incorrect hash silently matches no contact and, for a deletion, completes without deleting anything (see Section 4)
4. Request Logging
All DSARs must be logged in the internal GDPR request register (gdpr_requests Postgres table). The table holds exactly the following columns:
| Field | Description |
|---|---|
id | Request identifier (UUID), generated on creation — this is the reference number quoted to the Data Subject |
org_id | Customer organization |
type | One of deletion, access, portability, objection, restriction. No other value is accepted |
email_hash | SHA-256 hash of the Data Subject's email address. No plaintext email address is stored — no PostgreSQL table holds one |
status | pending (on creation), processing (while the pipeline runs), completed (on finish). No other value is ever written |
requested_at | Timestamp the request was created |
completed_at | Timestamp the request finished, set when status becomes completed |
requested_by | Identifier of whoever created the request — a staff user, attendee:self-service, or attendee:email-change. It does not record who processed it |
log | JSON array of pipeline step entries (step, status, free-text detail, timestamp). This is the only place free-text notes can be recorded |
created_at | Row creation timestamp |
There is no deadline column and no rejected status. The response deadline is not computed or stored anywhere in the platform; it must be tracked in the internal DSAR tracking sheet. A refused or rejected request — which Section 8 requires for a fraudulent request — has no state in the register: it can only be recorded as free text in the internal tracking sheet, and a request left unprocessed remains indistinguishable from one nobody has looked at.
GAP-RET-11 · CODE — KNOWN GAP, REMEDIATION PENDING
This Section previously described the register as holding a request_type, a plaintext or hashed subject_email, a received_at, a computed deadline, a processed_at, a processed_by and a free-text notes field, with statuses of pending, in progress, completed or rejected. Of those, only the organisation identifier exists: the register stores type, email_hash, requested_at, completed_at, requested_by and a JSON log, it has no deadline field, and the only statuses ever written are pending, processing and completed, so a refusal cannot be recorded against the request at all. This divergence is recorded on the compliance remediation register and is under review.
Rectification cannot be logged here. The register accepts no rectification type and the processing endpoint rejects one, so Art 16 requests are evidenced through the audit log instead — see Section 5.3.
Register entries created by the email-change flow are not fulfilled erasures. When an attendee changes their email address through the preferences page, the platform rewrites the contact's email hash to the new value and then raises a deletion request against the old hash, with requested_by set to attendee:email-change. When a member of staff processes that request the pipeline looks for a contact under the old hash, finds none, records find_contact: not_found, marks the request completed with a completion timestamp, and stops — before every deletion step. The email-hash-keyed records it was raised to clean up (email delivery records, push delivery records, device tokens, segment broadcast records) therefore survive. Requests with requested_by of attendee:email-change must not be counted as fulfilled erasures in any accountability report, and must not be used as evidence that data was deleted.
GAP-RET-08 · CODE — KNOWN GAP, REMEDIATION PENDING
This procedure previously treated every completed entry in the register as evidence that an erasure had been performed. The email-change flow raises a deletion request against an email hash that no longer identifies any contact, and the pipeline records that request as completed without deleting anything, so the register accumulates completions that performed no deletion while the records keyed to the former hash remain. This divergence is recorded on the compliance remediation register and is under review.
5. Processing Procedures
5.1 Right of Access (Art 15)
Goal: Provide a complete, readable copy of all personal data held about the Data Subject.
Steps:
- In the dashboard, go to GDPR (
/gdpr), locate the access or portability request, and press Process. There is no separate export action or export endpoint: processing anaccessorportabilityrequest produces the JSON export and renders it inline - The system generates a JSON export containing exactly the following, and nothing else:
- Contact record (email hash, flags, restriction state, timestamps)
- Registrations (
webinar_registrations, including the attendance columnsattended_viaandattended_at— there is no separate attendance table) - Behavioral events (only where
behavioral_trackingconsent was granted at the time the event was recorded) - Consent records (all purposes, timestamps, methods) and the consent event history
- Segment memberships
- Email delivery records (
email_sends: template type, status, timestamps) - Push delivery records (
push_sends: template type, status, open timestamp) - Device tokens (FCM tokens linked to their account, pseudonymous)
- Lead scores
- Firestore contact PII (plaintext email address, name, telephone number), Firestore consent documents and Firestore registration documents
- Live-session data per registration: attendance, actor record (display name), presence sessions, poll votes, offer clicks, feedback responses, banned and muted flags, chat messages in the live and removed streams, reactions, and reported messages
- Collect the omitted stores manually. The automated export does not query the following, all of which hold personal data of the Data Subject. Each must be retrieved by hand and added to the response, or the response is incomplete:
- Funnel entries (
funnel_entries) — every UTM parameter, advertising click identifier and click platform, landing page URL, referrer URL, country code, city, device type, operating system, browser, browser time zone, referral source, and, for webhook-sourced entries, the raw webhook payload and order metadata - Funnel page views (
funnel_page_views) — the persistent pseudonymous visitor hash derived from IP address and user agent - SMS delivery records (
sms_sends) — webinar and session, template type, tracking code, provider message identifier, delivery status, and delivery and click timestamps - Segment broadcast records (
segment_broadcast_sends) — which broadcasts the Data Subject was sent - Automation enrolments and step executions (
automation_enrollments,automation_step_executions) — including the step result documents, which hold the recipient's plaintext email address for email steps and their plaintext telephone number for SMS steps - AI generation records (
ai_jobs) — where the Data Subject has submitted a testimonial that staff approved, their name, quote, company and rating are embedded in stored generation prompts and outputs
- Funnel entries (
- Review the export and the manually collected material for completeness before sending
- Answer the Art 15(1)(a)–(h) questions in writing alongside the JSON. The export is data only; it does not state the purposes of processing, the categories of personal data, the recipients, the retention periods, the existence of the other rights, the right to lodge a complaint with a supervisory authority, or the source of the data. In particular:
- Recipients must include the sub-processors and onward recipients listed in Section 6, not only the storage providers
- Source (Art 15(1)(g)) must be disclosed where the data was not collected from the Data Subject. Order and form data arrives from Customer-side webhooks — MerchantPro, WooCommerce, Tally or a generic sender — and was not collected from the Data Subject by [PLATFORM PROVIDER]
- Consent records must be annotated. Consent rows whose method is
importwere written by the bulk importer for contacts who never interacted with the platform, and the export renders them identically to consents the Data Subject actually gave. Consent is recorded only as a grant, so the ledger holds no record of a refusal: a purpose that is absent may mean the Data Subject declined it or may mean they were never asked, and the export cannot distinguish the two. Say so
- Deliver the response to the Customer, which is the Controller. Where the request reached [PLATFORM PROVIDER] directly, do not send the export to the Data Subject without the Customer's authorisation (Section 3.2)
- Mark request as completed in dashboard
- Timeframe: Within 5 business days
Format: JSON (machine-readable). If Data Subject requests a more readable format, provide a human-readable summary alongside.
GAP-RET-04 · CODE — KNOWN GAP, REMEDIATION PENDING
This procedure previously described the export as containing attendance records and attribution data (UTM parameters and click identifiers), and presented it as a complete copy of the personal data held. The export never queries funnel entries — where all attribution, device and approximate-location data is held — nor funnel page views, SMS delivery records, segment broadcast records, automation enrolments and step executions, or AI generation records, so those categories are processed but are not reachable through Article 15 or Article 20 without the manual collection step above. This divergence is recorded on the compliance remediation register and is under review.
What is NOT included:
- Other attendees' data (even if they were in the same event)
- Aggregated/anonymized statistics that cannot be linked to the individual
- Internal audit log entries in full. A blanket refusal is not available: there is no "legitimate interest override" in the GDPR, Art 15(4) protects only the rights and freedoms of others, and any further restriction requires a Union or Member-State legislative measure under Art 23. Audit entries created by the data-subject rights workflow record the Data Subject's own email hash, and other entries concern the Data Subject directly. The correct posture is to release the entries that concern the Data Subject with the identifiers of [PLATFORM PROVIDER] and Customer staff — acting user identifier, role, IP address and user agent — redacted under Art 15(4), and to state in the response what has been redacted and on what basis
5.2 Right to Erasure (Art 17)
Goal: Delete the Data Subject's personal data from the systems the pipeline reaches, and record what it does not reach.
Steps:
- In the dashboard, go to GDPR (
/gdpr) and locate the deletion request - Confirm identity and validity (not subject to a legal hold or legitimate retention ground). Confirm the email hash on the request corresponds to a real contact — a hash that matches nothing completes as a no-op (Section 4)
- Press Process — this runs the deletion pipeline synchronously:
Automated pipeline actions:
| System | Action |
|---|---|
Postgres email_sends | Explicit delete by (org_id, email_hash) — linked by email hash, not by foreign key, so it is not reached by CASCADE |
Postgres push_sends | Explicit delete by (org_id, email_hash) |
Postgres device_tokens | Explicit delete by (org_id, email_hash) |
Postgres funnel_entries | Explicit delete by (org_id, contact_id); share referrals pointing at the Data Subject's share links are nullified first |
Postgres contacts | Hard delete — CASCADE removes behavioral_events, segment_members, consents, webinar_registrations (which carries the attendance columns), shares, lead_scores and automation_enrollments, and from the enrolments, automation_step_executions |
| Firestore registration documents | Hard delete, one per registration (orgs/{orgId}/webinars/{webinarId}/sessions/{sessionId}/registrations/{registrationId}) |
| Firestore consents subcollection | Hard delete (orgs/{orgId}/contacts/{emailHash}/consents) |
| Firestore contact PII document | Hard delete (orgs/{orgId}/contacts/{emailHash}/pii/private) |
| Firestore contact document | Hard delete (orgs/{orgId}/contacts/{emailHash}) |
| RTDB actor data | Best-effort delete by actor identifier, for the single actor identifier recorded on each registration — see below |
| Firebase Auth | Admin SDK delete of the anonymous account for each recorded actor identifier and of the account referenced on the contact document |
| Email provider | The Data Subject's email address is submitted to the suppression list — see below |
Firestore documents are removed only by this pipeline or by the manual deletion of a parent webinar or session: no time-to-live policy is configured on any Firestore collection.
- Verify pipeline completion. The dashboard shows the request's log entries with timestamps. Read them rather than treating completion as success:
- The live-database step reports
deleted N RTDB paths (M registrations without actor_id skipped). Check that skipped count. Every skipped registration is a session whose live-session data — display name, chat messages, poll votes, reactions — was not touched - Every live-database and Firebase Auth deletion is best-effort: a failure is logged as a warning and the pipeline continues, so a step can report completion while individual paths were not removed
- Where the skipped count is non-zero, or a failure is logged, perform the manual fallback: for each of the Data Subject's sessions, read
live/{sessionId}/identityCacheand delete the data of every actor identifier mapped to the Data Subject's email hash, not only the one recorded on the registration
- The live-database step reports
- Record the outcome. The pipeline writes its step log to the
gdpr_requestsrow and sets the status tocompleted; there is no separate logging action - Timeframe: the 24-hour figure is an internal operational target for a member of staff to process the request, not automated behaviour — nothing triggers the pipeline, and once triggered it runs in seconds within a single request. Confirmation to Customer/Data Subject within 5 business days
What is NOT deleted on erasure:
- Anonymized/aggregated stats (session view count totals, not tied to individual)
- Audit log entries. They are retained for security and accountability purposes (GDPR Art 5(2)). The audit log and the data-subject request register are not among the data types the retention job recognises, and nothing else in the platform deletes from them, so both grow without limit. The audit log records the acting user's IP address and user agent, and entries created by the data-subject rights workflow record the subject's email hash in their metadata, so an erased subject's email hash remains in the audit log after erasure. The application database role holds only select and insert privileges on the audit log, which makes it append-only for the application but also means it cannot be purged through the application's connection
- The
gdpr_requestsrecord itself, retained as evidence that the request was handled. It is retained indefinitely for the same reason as the audit log consent_events, the append-only consent trail retained as Art 7(1) evidence. Its rows are not deleted: the contact reference is set to null and the row survives in pseudonymised form, retaining the organisation, webinar and registration identifiers, the scope, purpose, action, method, policy version and timestamp. No retention rule covers it. Theconsentstable, which holds current state, is deleted by CASCADE- Two tables holding personal data keyed by email hash are not reached by the erasure routine and have no foreign key to the contact record, so they are not removed by cascade either: the SMS delivery log and the segment-broadcast recipient log. A per-person record of SMS messages sent — email hash, webinar and session, template type, tracking code, provider message identifier, delivery status and delivery and click timestamps — therefore persists after an Article 17 erasure, and neither table is included in the Article 15 data export
- AI generation records (
ai_jobs). Rows are keyed to an entity and to the member of staff who started the job, with no link to a contact record, so they are reached neither by the erasure routine nor by cascade. Where the Data Subject submitted a testimonial that staff approved, their name and quote persist in the stored prompt and output after erasure - Per-actor deduplication markers and message counts in the live database. The live-database cleanup covers eighteen node families but has no path for the per-actor deduplication markers under
live/{sessionId}/synced/or forlive/{sessionId}/actorMessageCounts/{actorId}, so the Data Subject's anonymous actor identifier and their per-session message count remain as leaf values - Live-session data under any actor identifier other than the one recorded on the registration. Each registration stores a single actor identifier and keeps the first one seen, so an attendee who joined from a second device, or re-joined under a new anonymous identity, retains their display name, chat messages, poll votes and reactions under the unrecorded identifier
Live-session residue is permanent unless removed by hand. Live-session data in the Realtime Database is retained indefinitely. There is no scheduled cleanup function: the Cloud Functions codebase exports ten functions, of which nine are database triggers and one is a minutely presence reconciler, and none deletes session data. Moving a session to replay or archived status does not prune it either — the lifecycle job writes a statistics snapshot to Firestore and performs no deletion in the Realtime Database. The only operations that remove a live-session node are the manual deletion of a session and the manual deletion of the parent webinar. Chat message text, attendee display names, presence and attendance records, poll votes, reactions, offer clicks and feedback responses therefore persist for the lifetime of the webinar record.
Erasure at the email provider is a suppression, not a deletion. On completing an erasure the platform submits the contact's email address to the email provider with a permanently-rejected status, so that no future message can be delivered to it. By design this keeps the plaintext email address on file at the provider indefinitely. The Data Subject must be told this, and the retention justified — it is processing necessary to give effect to their own erasure and to prevent further contact, relied on under Art 17(3)(b) and Art 6(1)(c)/(f).
Plaintext copies may remain in memory on other API instances. The API holds an in-process cache of plaintext contact details (email address, name and telephone number), keyed by organisation and email hash, to avoid repeated Firestore reads. The cache has no expiry, and entries are invalidated only within the process that performs the write. Where more than one API instance is running, a correction or a deletion applied on one instance does not evict the copy held by another. The pipeline evicts the entry on the instance that ran it; on a multi-instance deployment only a restart or redeployment guarantees eviction everywhere. "Verify pipeline completion" is not proof that no plaintext copy remains.
GAP-RET-03 · CODE — KNOWN GAP, REMEDIATION PENDING
This Section previously stated that the pipeline deletes all personal data about the Data Subject from all systems, and listed CASCADE deletion of tables named registrations, attendance_records and attribution_data, none of which exists in the schema. Several categories in fact survive an erasure: the SMS delivery log and the segment-broadcast recipient log, the AI generation records containing approved attendee testimonials, the per-actor deduplication markers and message counts in the live database, and all live-session data belonging to any actor identifier other than the single one recorded on each registration; the email address is additionally retained at the email provider as a permanent suppression. This divergence is recorded on the compliance remediation register and is under review.
GAP-RET-05 · CODE — KNOWN GAP, REMEDIATION PENDING
This procedure previously stated that audit logs are retained for two years under the security policy and that the GDPR request register is retained for three years as compliance evidence, and repeated the two-year figure in the erasure-confirmation template sent to the Data Subject. Neither table is among the data types the retention job recognises and no other mechanism deletes from them, so both are retained indefinitely; the application's database role additionally holds no delete privilege on the audit log. This divergence is recorded on the compliance remediation register and is under review.
Legal grounds to refuse erasure:
- Legal obligation to retain (e.g., tax/financial records — not applicable for attendee data)
- Legal hold order
- Processing is necessary for legal claims
- Compliance with the erasure itself: the email address held on the provider's suppression list is retained under Art 17(3)(b) so that the erasure can be given effect
- Note that the audit log and the consent event trail are not refused under an override. They are retained as accountability evidence under Art 5(2) and Art 7(1), which is a retention ground, not a ground to refuse the right; the Data Subject must be told what is retained and why
5.3 Right to Rectification (Art 16)
Goal: Correct inaccurate personal data.
What can actually be corrected:
- By Customer staff, in the dashboard: the contact's name only (Contacts → [Contact] → Edit name). The correction is written to the Firestore contact PII document
- By the Data Subject, on the attendee preferences page: their name, their email address (which rewrites the contact's email hash), and removal of their telephone number
- Nothing in PostgreSQL requires correction, because no PostgreSQL table holds a plaintext email address, telephone number or personal name. Contacts are keyed by an SHA-256 hash of the lowercased, trimmed email address, and plaintext contact details are held only in Firestore at
orgs/{orgId}/contacts/{emailHash}/pii/private. Two exceptions apply. First, the automations engine records the outcome of each executed step as a JSON document in PostgreSQL, and for email and SMS steps that document includes the recipient's plaintext email address or telephone number; those records are removed when the contact is deleted, by cascade, but they are not otherwise pseudonymised — and they are not updated by a rectification. Second, theai_jobstable stores the full prompt text of each AI generation, which may contain an approved attendee testimonial together with the name and company recorded on it; those rows carry no contact link, are not removed on erasure and are not updated by a rectification - The attendee display name held in the live database is not updated by a rectification and retains its previous value
Steps:
- Customer makes the correction in dashboard (Contacts → [Contact] → Edit), or the Data Subject makes it themselves on the preferences page
- The correction is written to Firestore. Propagation to other API instances is subject to the in-process plaintext PII cache described in Section 5.2: on a multi-instance deployment, a stale copy may be served by another instance until it restarts
- If mobile app contact doc needs update, API handles sync
- Evidence the rectification through the audit log. A rectification cannot be recorded in the GDPR request register — no
rectificationtype is accepted. A staff-made name correction writes anupdated_contact_nameaudit entry with the contact identifier, the new value, the acting user and the timestamp; that entry is the record of the correction. A correction the Data Subject makes themselves on the preferences page is not audited, and must be recorded in the internal DSAR tracking sheet by hand - Timeframe: Immediate upon Customer edit, subject to cache refresh on other API instances; confirm to Data Subject within 5 business days
GAP-RET-08 · CODE — KNOWN GAP, REMEDIATION PENDING
This procedure previously instructed the operator to log a rectification in the GDPR request register, and described corrections as propagating automatically to Firestore and PostgreSQL. The register accepts only deletion, access, portability, objection and restriction, and rejects a rectification type, so that step cannot be performed; corrections are written to Firestore alone and reach neither the attendee display name held in the live database, nor the plaintext addresses and telephone numbers held in automation step-execution records, nor the in-process caches of other API instances. This divergence is recorded on the compliance remediation register and is under review.
5.4 Right to Restriction (Art 18)
Goal: Suspend processing for a Data Subject without deleting their data.
Steps:
- In dashboard, mark contact as
processing_restricted, or process arestrictionrequest from the GDPR page. Either sets the restriction flag and its timestamp on the contact record; nothing else is written - A GDPR Article 18 processing restriction is enforced consistently as a hard stop: a restricted contact cannot be granted or re-granted any consent, receives no email, SMS or push message, is excluded from contact and segment exports and from segment broadcasts, and no server-side conversion event is sent for them
- Behavioural event recording is not suppressed by the restriction, and must be stopped by hand. Setting the restriction flag writes nothing to Firestore and the behavioural ingest path performs no restriction check, so a restricted contact's chat messages, poll votes, reactions, offer clicks and feedback continue to be recorded to the analytics database and to the live database for as long as they attend sessions. To stop analytics recording, the contact's
behavioral_trackingconsent document in Firestore must be set to revoked as a separate operator action — see the note on consent revocation in Section 5.6 — after which the change is synchronised to the analytics database automatically. To stop live-session capture, exclude the contact from further sessions; nothing in the product suppresses it - Contact remains in system (data not deleted) but is otherwise frozen
- Log restriction in
gdpr_requests(typerestriction) - Notify Data Subject of restriction confirmation, and tell them what the restriction does and does not stop
- Timeframe: Within 2 business days
GAP-RET-09 · CODE — KNOWN GAP, REMEDIATION PENDING
This procedure previously stated that a processing restriction suppresses behavioural event recording. Setting the restriction writes only the restriction flag on the contact record: the behavioural ingest path performs no restriction check, and the upstream gate in the Cloud Functions is the contact's behavioural-tracking consent, which the restriction does not revoke — so behavioural events continue to be recorded for a restricted contact. The other suppressions listed in this Section are enforced. This divergence is recorded on the compliance remediation register and is under review.
Lifting restriction: Customer can lift restriction in dashboard (requires documented reason from Data Subject).
5.5 Right to Portability (Art 20)
Goal: Provide data in machine-readable format for transfer to another service.
Steps:
- Same as Access (Section 5.1) — the same JSON export, produced by the same action, subject to the same omissions. The manual collection step at Section 5.1 step 3 applies in full: funnel entries, funnel page views, SMS delivery records, segment broadcast records, automation records and AI generation records are not in the export
- Confirm export is in standard format (JSON is machine-readable and portable)
- Timeframe: Within 5 business days
5.6 Right to Object (Art 21)
Goal: Stop processing based on legitimate interest or for direct marketing.
Applicable scenarios:
| Objection | Action |
|---|---|
| Object to marketing emails | Revoking email_marketing consent is not sufficient: that consent gates only whether the contact is synchronised into the marketing email provider's list and segments. Every in-product email — registration confirmation, reminders, "starting now", replay, automation email, resend and segment broadcast — runs on the transactional gate alone (contact not suppressed for bounce, complaint or global opt-out, and not subject to an Art 18 restriction). To stop them, additionally set the contact's global opt-out flag, remove them from the segments used for broadcasts, or apply an Art 18 processing restriction |
| Object to marketing push | Not implemented. No marketing push send path exists, and the push_marketing consent gates nothing. Revoking it records the objection but changes no behaviour. Transactional push is stopped by an Art 18 processing restriction |
| Object to behavioral tracking | Revoke behavioral_tracking consent. Where an attendee has not granted behavioural-tracking consent, their chat messages, poll votes, reactions, offer clicks and feedback are still written to the live-session database and remain visible to staff on the live dashboard, and their attendance is still recorded against their registration. Only the granular behavioural event rows in the analytics database are suppressed. Events already recorded are removed only by an Art 17 erasure |
| Object to WhatsApp/SMS | SMS: revoke sms_notifications; this is an enforced gate — no SMS message is sent without a granted, unrevoked sms_notifications consent. sms_marketing gates nothing. WhatsApp: not implemented. WhatsApp exists only as an organisation integration toggle and as share links; there is no message-sending path, so whatsapp_notifications and whatsapp_marketing gate nothing |
| Object to ad conversion tracking | Apply an Art 18 processing restriction. There is no advertising-consent gate on the server-side conversion paths: the Meta Conversions API and the TikTok Events API send on every registration where the Customer has enabled the integration, and the advertising-consent value recorded on the registration document is read by nothing. The processing restriction is the only mechanism that suppresses them. Note that this stops future transmissions only — see Section 6 |
| Object to transactional communications | Cannot be honored under legitimate interest if attendee is an active registrant — inform Data Subject |
| Object to landing-page measurement | Cannot be honoured retrospectively and cannot be switched off per person. A unique-visitor identifier — a hash of the visitor's IP address and user agent — is recorded for each funnel step a visitor loads, once per day, without a consent gate and with no link to a contact record, so it cannot be located for a given individual. Where the Customer has enabled the Meta integration, a server-side page view carrying the visitor's raw IP address and user agent is additionally sent to Meta Platforms, Inc. on the landing-page path |
| Object to automated chat moderation | Cannot be switched off per person. Where the Customer configures banned words, each chat message is checked automatically; a matching message is either masked in place or removed from the live stream and moved to a staff-visible removed stream, which retains the original message text together with the removal reason and timestamp. Removed messages are deleted for a Data Subject only by an Art 17 erasure, and only under the actor identifier recorded on their registration |
How a consent is actually revoked. There is no staff-facing control that revokes a consent. The dashboard's contact consent view is read-only, cancelling a registration does not revoke any consent because consents are organisation-scoped, and no staff API endpoint exists for it. A consent can be revoked only by the Data Subject on the attendee preferences page, by following an unsubscribe link (which revokes email_marketing alone), or by an operator setting the consent document in Firestore to revoked, which is then synchronised to the analytics database automatically. data_processing and tos_acceptance cannot be revoked through the preferences page at all.
Steps:
- Log objection in
gdpr_requests(typeobjection). Note that processing anobjectionrequest applies a processing restriction — it sets the same flag as arestrictionrequest and does nothing else. It does not revoke any consent - Revoke the relevant consents by one of the routes above, and apply any additional suppression the table requires
- Confirm to the Data Subject what has actually stopped, distinguishing it from what the revoked consent does not control
- Confirm to Data Subject within 5 business days
GAP-CONSENT-06 · CODE — KNOWN GAP, REMEDIATION PENDING
This procedure previously presented consent revocation, performed by staff in the dashboard or through the API, as the mechanism that stops each category of processing. No staff-facing revocation control exists, and several of the consents named gate nothing — push_marketing, sms_marketing, whatsapp_notifications and whatsapp_marketing have no send path behind them, while email_marketing gates only synchronisation to the marketing email provider rather than in-product email, and there is no advertising-consent gate on the server-side conversion paths. The Article 18 processing restriction is the only cross-cutting suppression the platform enforces. This divergence is recorded on the compliance remediation register and is under review.
6. Sub-Processor Coordination
[PLATFORM PROVIDER] engages eleven sub-processors, listed in Annex III (annex-sub-processors.md). The table below covers those that hold or receive a Data Subject's personal data in a way that affects a rights request, plus the Customer's own Firebase project, which is not a [PLATFORM PROVIDER] sub-processor.
| Sub-Processor | DSAR Impact | [PLATFORM PROVIDER] Action |
|---|---|---|
| Google LLC (Firestore, RTDB, Firebase Auth) | Auth account deletion, Firestore/RTDB data deletion | Covered by the deletion pipeline (Admin SDK calls), subject to the live-database exclusions in Section 5.2 |
| Railway Corp. (Postgres) | Postgres table deletions | Covered by the deletion pipeline (direct DB operations), subject to the table exclusions in Section 5.2 |
| NewsmanApp SRL (email delivery) | Holds the Data Subject's plaintext email address, first and last name, segment membership, and the view, click, bounce, complaint and unsubscribe events it returns to the platform | Automated, and it is a suppression rather than a deletion. The pipeline reads the plaintext email address from Firestore before deleting it and, after deletion, submits it to the provider with a permanently-rejected status. The call is best-effort and its outcome is logged. The address is therefore retained at the provider indefinitely so that no future message can be delivered to it; the Data Subject must be told this. [PLATFORM PROVIDER] does not delete the subscriber record or the behavioural events held by the provider — where the Customer requires that, the Customer must action it in its own provider account |
| SendSMS.ro (Romania) | The recipient's telephone number and the full message body are transmitted to the provider as URL query-string parameters, which should be assumed to be recorded in the provider's request logs. On delivery the message reaches the recipient's mobile network operator | No action is taken on erasure. The pipeline makes no call to the provider, and the local delivery log (sms_sends) is not deleted either (Section 5.2). Inform the Customer that deletion of message logs held by the provider must be requested under the Customer's own agreement with it, and that the provider's retention period for message content and delivery logs is not established |
| Meta Platforms, Inc. | Has already received, for each registration where the Customer enabled the integration, SHA-256 hashes of the email address, first name and last name, the registration identifier unhashed, and the raw client IP address and user agent — but no telephone number; and, on funnel landing pages, a server-side page view carrying the raw IP address and user agent | No action is taken on erasure. No deletion call and no exclusion-audience mechanism exists in the platform. Applying an Art 18 processing restriction stops future transmissions only. For data already transmitted, direct the Customer to Meta's own data-deletion request process; [PLATFORM PROVIDER] cannot action it |
| TikTok Pte. Ltd. | Has already received, for each registration where the Customer enabled the integration, SHA-256 hashes of the email address, first name, last name and registration identifier — but no telephone number — together with the raw client IP address, user agent, ttclid click identifier and _ttp cookie value | No action is taken on erasure, as for Meta. An Art 18 processing restriction stops future transmissions only; for data already transmitted, direct the Customer to TikTok's own data-deletion request process |
| Anthropic PBC (USA) | Where the Data Subject submitted a testimonial that staff approved, their name, quote, company and rating have been transmitted in generation prompts, and are retained locally in the AI generation records | No action is taken on erasure. The generation records are keyed to an entity and a staff user, not to a contact, so the pipeline does not reach them and the testimonial content survives the erasure. Anthropic's retention period for API inputs and outputs is not established |
| Cloudflare, Inc. | Terminates TLS for and proxies all attendee traffic in production, including registration submissions carrying plaintext email address, name and telephone number; every client IP address the platform records or forwards is derived from a Cloudflare-supplied header | Transient proxy and edge logs only. No stored personal data to delete and no action is taken on erasure |
| Customer-org Firebase (FCM) | FCM token associations on Customer's Firebase project | Customer must action separately — [PLATFORM PROVIDER] deletes device_tokens record from its Postgres, but cannot revoke tokens in Customer's Firebase project |
Important: Erasure does not propagate to the advertising platforms. Hashed identifiers, raw IP addresses and user agents already transmitted to Meta Platforms, Inc. and TikTok Pte. Ltd. remain with them; the platform makes no deletion call and operates no exclusion audience. It likewise makes no call to the SMS provider or to the AI provider. The only automated onward action on erasure is the email suppression described above, which retains rather than removes the email address. Inform Customers that their own Firebase project, their SMS provider account and the advertising platforms require separate deletion actions, and that [PLATFORM PROVIDER] cannot perform these on the Customer's behalf.
GAP-RET-06 · CODE — KNOWN GAP, REMEDIATION PENDING
This Section previously stated that [PLATFORM PROVIDER] cannot access the Customer's email provider account and that the Customer must delete the contact there itself, and listed four sub-processors as the full set affected by a rights request. The deletion pipeline in fact calls the email provider automatically to place the address on a permanent suppression list, which retains the plaintext address indefinitely rather than deleting it, and at least five further recipients — the SMS provider, Meta Platforms, Inc., TikTok Pte. Ltd., Anthropic PBC and Cloudflare, Inc. — receive the Data Subject's personal data and were absent from this table. This divergence is recorded on the compliance remediation register and is under review.
7. Response Templates
7.1 Acknowledgment (sent within 3 business days)
Subject: Your GDPR Request — Received
Dear [Name],
We have received your [access / erasure / rectification] request dated [DATE]. We will process your request within 5 business days and update you with the outcome.
Reference number: [GDPR-REQUEST-ID]
If you have any questions, reply to this email.
Regards, [Organization Name] Privacy Team
7.2 Erasure Confirmation
Subject: Your Data Deletion Request — Completed
Dear [Name],
Your data deletion request (reference: [GDPR-REQUEST-ID]) for the email address [email] has been processed. We have deleted your contact record, your registrations and attendance, your consent records, your behavioural and engagement data, your email and push delivery records, your device tokens, your campaign and funnel entries, and your live-session data — including your display name, chat messages, poll votes, reactions and feedback — from our systems.
Some records are not deleted, and we are required to tell you which and why:
- Your email address has been placed on a permanent suppression list with our email delivery provider. We keep it there so that no further message can be sent to you. It is retained indefinitely for that purpose.
- Our security audit log and our record of this request are retained indefinitely as evidence that we handled your request correctly and to keep our security records complete (GDPR Art 5(2)). Where the audit log refers to you, it does so by a one-way hash of your email address.
- The history of consents you gave and withdrew is retained, with the link to your contact record removed, as evidence that consent was properly obtained (GDPR Art 7(1)).
- A record that SMS or broadcast messages were sent to you, identified by a one-way hash of your email address, is retained in our message delivery logs.
- Where you submitted a testimonial that was approved for publication, your name and the text of your testimonial may remain in stored content-generation records.
- Where you joined a live session from more than one device or re-joined under a new session identity, data recorded under the additional identity may remain. Internal technical markers holding only your anonymous session identifier and a count of messages sent also remain. Tell us if you believe this applies to you and we will remove it.
- Anonymised usage statistics (for example, total event view counts) cannot be attributed to you and are not subject to erasure.
We have not deleted, and cannot delete, data already transmitted to the advertising platforms your event organiser uses. Please contact them directly, or ask your event organiser to do so.
If you believe any data was missed, contact us at [[email protected]].
Regards, [Organization Name] Privacy Team
GAP-RET-03 · CODE — KNOWN GAP, REMEDIATION PENDING
This template previously told the Data Subject that all personal data associated with their email address had been deleted from our systems, and that security audit logs are retained for two years. Neither statement was accurate: several categories of personal data survive the erasure pipeline, as set out in Section 5.2, and neither the audit log nor the request register is subject to any retention rule. The template above states the position as implemented; it must not be reverted to the earlier wording. This divergence is recorded on the compliance remediation register and is under review.
7.3 Access Export Delivery
Subject: Your Data Export — Ready
Dear [Name],
Your data export (reference: [GDPR-REQUEST-ID]) is attached, together with a summary of the purposes for which we process your data, who receives it, how long we keep it, where it came from, and the other rights available to you.
[Attach JSON export]
If you would like a human-readable summary, reply to this email.
Regards, [Organization Name] Privacy Team
8. Escalation
| Scenario | Action |
|---|---|
| Request cannot be fulfilled within 5 business days | Inform Data Subject of delay and extended deadline (max 1 month per GDPR Art 12(3), extendable by a further 2 months where the request is complex) |
| Identity cannot be verified | Request additional confirmation; do not process until verified |
| Request involves a legal hold | Consult legal counsel before processing |
| Data Subject threatens DPA complaint | Escalate to legal counsel; ensure response is documented |
| Data Subject is a minor (under 16) | Consult legal counsel; determine if parental consent applies |
| Request appears fraudulent | Document and decline. The register has no rejected state and a declined request cannot be recorded against it, so record the decision, its reasons and the evidence in the internal DSAR tracking sheet, and leave the register entry unprocessed rather than marking it completed |
9. Review Cycle
This procedure must be reviewed:
- Annually
- After any DSAR that reveals a gap in the process
- When new data types or processing activities are added that affect DSAR scope
Changes incorporated in this revision. The third trigger above fired repeatedly between this procedure's previous revision and this one without a review taking place. The following changes to the platform are reflected in Sections 5.1, 5.2 and 6:
- Segment broadcasts and the segment-broadcast recipient log
- The inbound e-commerce order-webhook ingestion channel, which introduces personal data not collected from the Data Subject (Art 15(1)(g))
- Automated chat moderation, which retains the original text of removed messages in a staff-visible stream
- The TikTok Events API server-side mirror, active since 8 May 2026
- The server-side Meta Conversions API page view on funnel landing pages
- The move of per-actor deduplication markers in the live database to a node the erasure pipeline does not reach
Proposed control. To stop this class of drift recurring, tie the third trigger to a concrete gate: any new PostgreSQL table holding personal data must be added to the export routine and the deletion routine, or explicitly recorded as an exclusion in Sections 5.1 and 5.2, before it ships.
Document Version: 1.0 (DRAFT) Prepared by: [Legal Team / Engineering] Review Status: ⚠️ REQUIRES LEGAL REVIEW — Procedure and response templates must be reviewed by GDPR counsel before use.
Last Updated: [DATE]