Owner: Ayisha "Balboa" Oglivie (Strategic Operations / COO-acting) — signs the response, owns the legal posture
Data ops executor: Lola (Laura Daniels — Chief of Staff / Head of Operations)
Engineering executor: Robert "Rep" Taylor (Head of QA Engineering & AI Automation)
Author: Workflow Architect (Amena) — for Chief of Staff team
Status: Draft v0.1 — pending sign-off from Ayisha, Lola, Rep, Jonathan
Effective: TBD — after sign-off + §16 routing live + DSAR pipeline tested
Pairs with: §16 Channel Routing Map, §17.4 Customer Support, §17.5 Regulator-Direct; docs/REGULATORY_COMPLIANCE_MASTER.md (GDPR / CCPA section)
Supersedes: None
Front door per §16. DSARs (Data Subject Access Requests) arrive through:
privacy@gethempdash.com — primary intended landing zone. Routing owner Ayisha; data ops Lola.gdpr@gethempdash.com / ccpa@gethempdash.com — same routing as privacy@.support@, SMS, phone IVR. Override fires per §16 §3.1 and the ticket re-routes to Ayisha within 5 minutes. Original-channel agent stops asking for personal data; the DSAR pipeline has its own ID-verification gate.A request from an identified or identifiable individual about their own personal data. Covered by GDPR (EU residents), CCPA / CPRA (California residents), and a growing list of US state privacy laws (Colorado CPA, Connecticut CTDPA, Virginia VCDPA, Texas TDPSA effective July 2024, etc.).
Request types we handle:
| Right | Common name | What we do |
|---|---|---|
| Right to Know / Access | "Send me my data" | Compile a copy of personal data we hold; deliver via secure channel |
| Right to Delete / Erasure | "Delete my account/data" | Delete except where retention law applies; document exceptions |
| Right to Correct / Rectification | "Fix my record" | Update specific fields after verification |
| Right to Portability | "Export my data in a portable format" | Machine-readable export (JSON, CSV) |
| Right to Opt-Out of Sale | "Don't sell my data" | We don't sell, but log the opt-out anyway |
| Right to Limit Use of Sensitive PI | "Don't use my sensitive PI beyond necessary" | Apply CCPA SPI flag |
| Right to Non-Discrimination | n/a (passive) | Don't penalize the user for exercising rights |
Actor: Ayisha (routing owner) + Amena (auto-classification).
Action: Identify request type (Know / Delete / Correct / Portability / Opt-Out / Limit-SPI / Non-Discrim). Identify applicable law (GDPR / CCPA / TDPSA / etc.) based on requester's claimed jurisdiction. Open a dsar_request row.
Timeout: 1 business day from inbound.
Input: Inbound message.
Output on SUCCESS: Classified → GO TO STEP 2.
Output on FAILURE:
FAILURE(ambiguous_request): Reply asking the requester to clarify which right they're exercising. Clock pauses (per applicable law's "extension" rules) and resumes when they clarify.FAILURE(third_party): Branch to §1.10.FAILURE(out_of_jurisdiction): If requester's jurisdiction has no applicable privacy law, document and respond per HempDash policy default (provide access on good-faith basis but no statutory clock).Actor: Ayisha or Lola (drafts via Amena, sends as a named human).
Action: Send acknowledgment. Tells the requester: we received the request, the clock has started, we'll respond within N days (30 for CCPA/most US, 45 for "complex" requests with extension; 30 for GDPR, extendable to 60 with notice).
Timeout: Within 10 calendar days of intake (CCPA requires acknowledgment within 10 business days).
Input: Classified request.
Output on SUCCESS: Acknowledgment sent → GO TO STEP 3.
Output on FAILURE:
FAILURE(no_sender_email): Request came via phone/SMS without an email. Use the channel the request came in on; document delivery.Actor: Lola (executor) + Ayisha (decides if proof is sufficient).
Action: Confirm the requester is who they say they are. Required for Right-to-Know, Right-to-Delete, Right-to-Correct, Right-to-Portability. Optional for Opt-Out (low risk; do not over-collect to verify).
Identity verification methods, in order of preference:
Timeout: Reasonable additional time per CCPA (typically up to 45 days for "complex" cases). Verification attempts should be made in the first 7 calendar days.
Output on SUCCESS: Verified → GO TO STEP 4.
Output on FAILURE after 2 attempts:
Notes on minimization: Per CCPA + GDPR, do not collect more proof than needed. A reasonable basis to believe the requester is the data subject is the standard.
Actor: Rep (technical inventory) + Lola (ops inventory) + Ayisha (decides scope).
Action: Identify every system that holds personal data about the requester:
Timeout: 7 calendar days from verification.
Output on SUCCESS: Scope list complete → GO TO STEP 5.
Actor: Ayisha.
Action: Cross-reference the requester's data scope against active do_not_purge flags (set by §17.5 legal-hold events). If any record in scope is under legal hold, deletion / correction / portability for that record is deferred until the hold lifts.
Conflict resolution:
Timeout: 2 business days from scope.
Output on SUCCESS: Conflict resolved → GO TO STEP 6.
Actor: Rep + Lola.
Action:
deleted_at). Backups noted as not-purged with explanation.Timeout: Working backward from the response deadline: package complete 5 business days before deadline for review buffer.
Actor: Lola + Ayisha.
Action: Scan the package for personal data about other people (e.g., a Chatwoot conversation thread where the requester's CS agent's name and email appear is fine; one where another customer's data appears is not). Redact other-person PII.
Output on SUCCESS: Redacted package → GO TO STEP 8.
Actor: Ayisha (named signer on every DSAR response).
Action: Cover letter that states: request type, applicable law, what we did (or denied + why), how to contest, retention pointer. Letter is Ayisha-signed PDF.
Actor: Lola sends, Ayisha co-signs the email.
Action:
Actor: Amena (automated).
Action: Write dsar_request final row with all metadata: request type, applicable law, intake date, ack date, verification method + result, scope summary, exception list (legal-hold-protected records), response sent date, delivery method, package retention URI (encrypted, 7 years).
Per STEP 5. Deletion proceeds for non-protected records; protected records held with documented exception. Re-evaluate on hold-lifted event (Amena monitors legal_hold_event rows and re-opens any deferred DSARs whose holds clear).
LedgerEntry rowsPer project_ledger_write_only.md, ledger entries are immutable. Deletion is not possible on ledger rows. Response documents the exception with the regulatory basis (retention obligations for financial transaction records — IRS 7 years, payment-processor 5 years, etc.).
If the requester says "delete all my data," scope per STEP 4 across all systems. Apply the legal-hold and ledger exceptions per §1.12.1 / §1.12.2. Document the exceptions in the response.
GDPR Article 12 allows a controller to refuse or charge a reasonable fee for manifestly unfounded or excessive requests (e.g., the 17th access request from the same person in 6 months with no legitimate purpose). Ayisha + counsel review before refusing. Document the refusal basis.
CCPA allows a one-time 45-day extension beyond the initial 45 days, with notice. GDPR allows extension to 90 days for complex requests, with notice. If the matter is genuinely complex, Ayisha notifies the requester before the original deadline and extends with documented reason.
A request about someone else's data — "please send me my partner's data." Default: refuse with explanation; the data subject must request on their own behalf. Exceptions: legal guardian for a minor, legally-documented power of attorney. Ayisha + counsel review.
If the requester is identified as under 21, route through §17.4 §8.5 (minor-user concern) in parallel. Process the DSAR per parent/guardian; compliance side handles the under-21 concern.
A family member requests data for a deceased account holder. Counsel-driven; varies by jurisdiction. Ayisha drafts response after counsel input.
Re-route to privacy@ with a polite reply asking them to email so we can verify identity. Do not share data on a public channel.
If the requester deletes then signs up again with the same email within the retention window, treat as a new account. Document in audit.
HANDOFF: Ayisha -> Lola (DSAR execution)
PAYLOAD: {
matter_id: uuid,
request_type: enum('know','delete','correct','portability','opt_out','limit_spi'),
applicable_law: enum('gdpr','ccpa','tdpsa','other'),
requester_email: str,
customer_id: uuid?, // if identifiable; null if anonymous
deadline_ts: timestamptz,
identity_verified: bool,
verification_method: str,
scope_summary: text,
legal_hold_conflicts: [hold_id]
}
SUCCESS RESPONSE: { execution_started: true, started_at: timestamptz }
FAILURE RESPONSE: { ok: false, error: str, code: str }
TIMEOUT: 2 business days from scope
ON FAILURE: Re-scope; if blocked on tech access, page Rep
HANDOFF: Lola -> Rep (technical data export / deletion)
PAYLOAD: {
matter_id: uuid,
request_type: enum,
customer_id: uuid,
systems_in_scope: [
'auth0','customer_app','chatwoot','erpnext','mattermost','springbig','grafana_loki','analytics'
],
exclusions: [
{ system: str, record_pattern: str, exclusion_reason: str } // legal_hold, ledger_immutable, etc.
]
}
SUCCESS RESPONSE: {
package_uri: str?, // for know/portability
deleted_record_count: int?, // for delete
corrected_record_count: int?, // for correct
exceptions_applied: [str]
}
FAILURE RESPONSE: { ok: false, error: str, retryable: bool }
TIMEOUT: 7 business days
ON FAILURE: Document gap; counsel reviews
HANDOFF: HempDash -> Requester
PAYLOAD: {
matter_id: uuid,
cover_letter_uri: str, // Ayisha-signed PDF
data_package_uri: str?, // password-protected ZIP or signed URL
package_password_channel: str?, // 'sms', 'separate_email_24h_later'
delivery_method: enum('email','signed_url','none_deletion_confirmation')
}
SUCCESS RESPONSE: { delivered_at: timestamptz, requester_ack: bool? }
FAILURE RESPONSE: { ok: false, error: str, retryable: bool }
TIMEOUT: Hard deadline = statutory deadline
ON FAILURE: Re-send via alternate channel; document
| Stage | Requester sees | Operator sees | Database |
|---|---|---|---|
| Inbound | Auto-ack: "We received your request and will respond within 30 days" | Ticket tagged dsar_unclassified |
dsar_request row created |
| Classified | Same | Tag updated dsar_type:<x> |
Row updated |
| Acknowledged | Formal ack email from Ayisha | Status acknowledged |
Row updated ack_at |
| Identity verification request | Email asking for verification proof | Status awaiting_verification |
Row updated |
| Identity verified | Confirmation of verification | Status verified |
Row updated verified_at, verification_method |
| Scope complete | (nothing externally) | Scope list in matter folder | Row updated scope_complete_at |
| Legal hold conflicts | (nothing externally) | Conflicts flagged | dsar_request.legal_hold_conflicts |
| Package compiled | (nothing externally) | Package URI | Row updated |
| Response sent | Email + password-protected package | Status responded |
Row updated responded_at |
| Closed | Nothing further | Status closed |
Row updated closed_at |
| Step | Internal SLA |
|---|---|
| Intake (STEP 1) | 1 business day |
| Acknowledge (STEP 2) | 10 calendar days (CCPA) |
| Verify identity (STEP 3) | First attempt within 7 calendar days |
| Scope (STEP 4) | 7 calendar days from verification |
| Legal-hold check (STEP 5) | 2 business days from scope |
| Compile package (STEP 6) | 5 business days buffer before deadline |
| Redaction (STEP 7) | 1 business day |
| Sign cover letter (STEP 8) | 1 business day |
| Deliver (STEP 9) | Before statutory deadline |
Statutory clocks:
Clock starts at receipt of the request, not at verification. Verification time counts against the response window in most jurisdictions.
Document the miss in dsar_request.deadline_missed:true. Ayisha + counsel decide remediation: apologize, fast-track, file a self-report with the AG if required. Treat as P0 retrospective.
We deleted data we shouldn't have because we mis-verified or mis-scoped. Counsel-driven; potential breach notification triggers. Treat as a P0 security incident; trigger §17.4 §8.6 legal-hold path.
Cannot delete. Response documents the exception per §1.12.2. Standard outcome.
Requester says "you didn't give me everything" or "you didn't really delete." Re-open the matter; Lola + Rep re-audit scope; Ayisha responds. If requester escalates to a regulator (AG, FTC), §17.5 fires in parallel.
Should be impossible per §16 §4 (no Amena outbound externally). If somehow Amena leaks PII in an outbound message: P0 incident, breach-notification analysis by counsel, notify Jonathan.
A bad actor passes verification with stolen credentials and requests another person's data. Mitigation: prefer authenticated-session verification (Auth0) when possible; require multiple matching facts for high-stakes requests; require government-ID for full-account deletion. If we discover post-response that we verified an impostor, notify the real account owner and the appropriate regulator if required.
Industry standard: backups are out-of-scope for deletion purposes because immutable + rotation-based. Response documents this. If the requester insists on backup purge, counsel-led response (typically: backups are retained for a documented business-continuity period and rotate out within N days; we won't restore-and-delete from a backup).
CREATE TABLE dsar_request (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
chatwoot_conv_id INT,
inbound_channel TEXT NOT NULL, -- 'email:privacy', 'phone:ivr', etc.
requester_email TEXT NOT NULL,
requester_phone TEXT,
customer_id UUID, -- null if requester not yet identified
request_type TEXT NOT NULL, -- 'know','delete','correct','portability','opt_out','limit_spi'
applicable_law TEXT NOT NULL, -- 'gdpr','ccpa','tdpsa','other'
received_at TIMESTAMPTZ NOT NULL,
ack_at TIMESTAMPTZ,
deadline_ts TIMESTAMPTZ NOT NULL,
verification_method TEXT,
verified_at TIMESTAMPTZ,
scope_summary TEXT,
legal_hold_conflicts JSONB, -- [{matter_id, scope}]
exceptions_applied JSONB, -- [{system, reason}]
package_uri TEXT,
responded_at TIMESTAMPTZ,
delivery_method TEXT,
delivery_receipt_uri TEXT,
closed_at TIMESTAMPTZ,
deadline_missed BOOLEAN DEFAULT false,
denied BOOLEAN DEFAULT false,
denial_reason TEXT,
notes TEXT,
CONSTRAINT dsar_type_check CHECK (request_type IN
('know','delete','correct','portability','opt_out','limit_spi','non_discrim'))
);
CREATE INDEX idx_dsar_deadline ON dsar_request(deadline_ts) WHERE closed_at IS NULL;
CREATE INDEX idx_dsar_customer ON dsar_request(customer_id);
The DSAR audit row + cover letter retained 7 years from matter close. The actual data package delivered to the requester is retained encrypted for 90 days after delivery (for re-delivery / dispute), then purged. The retention policy itself is documented in the privacy notice.
| # | Question | Owner | Why it matters |
|---|---|---|---|
| Q1 | Privacy notice — is the current public privacy policy aligned with this SOP's commitments? | Ayisha + counsel | Privacy notice is the public-facing commitment; SOP execution must match. |
| Q2 | Identity-verification fact set — which transaction facts do we accept (last 4 of card, last order #, shipping addr, etc.)? | Lola + Ayisha | Codifies STEP 3 method 3. |
| Q3 | dsar_request table — new migration, Katherine reviews. |
Rep | Migration gate. |
| Q4 | In-app privacy-request form — built? Planned? | Lola + Rep | Affects intake quality. Default v0.1: email only. |
| Q5 | Data-package delivery — password-protected ZIP, signed S3 URL, or both? | Rep + Ayisha | Affects STEP 9 default. |
| Q6 | Backup-purge stance — formally documented as out-of-scope-for-deletion? | Ayisha + counsel | Statutory defense for §5.7. |
| Q7 | LedgerEntry exception — codified in privacy notice as a retention reason? | Ayisha + counsel | Defends §1.12.2. |
| Q8 | Marketing-systems opt-out propagation — Springbig and any future ESP have API support for unsubscribe? | Rep + Lola | Required for opt-out STEP 6 execution. |
| Q9 | DSAR-volume forecasting — at current scale we may get 0-5/year. Do we need workflow automation now or revisit at scale? | Lola + Ayisha | Sizes v0.1 vs v1.0 build effort. |
| Q10 | Self-service portal — when do we build an in-product privacy portal? | Jonathan + Lola | Eventually a Layer 1 feature (Compliance Seal). |
dsar_request table exists; Katherine reviewed.do_not_purge flag fully integrated with legal_hold_event per §17.5.| Version | Date | Author | Change |
|---|---|---|---|
| 0.1 | 2026-05-11 | Workflow Architect (Amena) | Initial draft. |
SOP index · DSAR Execution · Privacy Rights Matrix · Data Retention Policy · Home