Owner: Ayisha "Balboa" Oglivie (Strategic Operations / COO-acting) — operational + regulatory owner
Routing owner (initial intake): Katherine "Katie" Ulbricht
Founder loop: Jonathan Sullivan (mandatory, within minutes)
Outside counsel: Vicente LLP (Susan Hays + Shawn Hauser warm-contacted Oct 2025; advisor pipeline)
Quality oversight: Purple (VP of Product Quality and Experience)
Author: Workflow Architect (Amena) — for Chief of Staff team
Status: Draft v0.1 — pending sign-off from Ayisha, Katherine, Jonathan, Lola, Purple
Effective: TBD — after sign-off + §16 routing rules go live + legal-hold pipeline confirmed
Pairs with: §16 Channel Routing Map, §17.4 Customer-Support Escalation (§8.2 regulator-complaint edge case), §17.6 PII / DSAR, §17.7 Press; docs/REGULATORY_COMPLIANCE_MASTER.md
Supersedes: None
Front door per §16. Regulators contact HempDash through:
compliance@gethempdash.com — primary intended landing zone. Routing owner Katherine; substantive responder Ayisha.legal@gethempdash.com — for litigation-adjacent matters. Routing owner Ayisha; substantive responder outside counsel + Ayisha.regulator_inbound in Chatwoot compliance inbox.support@, customer Chatwoot widget, SMS, founder's direct email. Override triggers per §16 §3.1 and routes to Ayisha within 5 minutes. Stop replying on the original channel until Ayisha clears.If unclear, escalate to Ayisha. The cost of false-positive over-escalation is low; the cost of missing a real NOV is catastrophic.
Actor: Katherine (routing owner at compliance@) + Amena (auto-detection).
Action: Verify the inbound is from a genuine agency address (cross-check sender domain against the known-regulator list maintained by Ayisha). Classify the document type (NOV / subpoena / inquiry / complaint forward / inspection request). Tag the Chatwoot conversation tier:regulator, agency:<name>, doc_type:<type>.
Timeout: 30 minutes from inbound timestamp.
Input: Inbound message + attachments.
Output on SUCCESS: Genuine + classified → GO TO STEP 2.
Output on FAILURE:
FAILURE(false_positive): Re-route per §16 override; audit row; END.FAILURE(spoof_suspected): Sender domain doesn't match known agency. Quarantine attachment, do NOT click links, escalate to Ayisha immediately, treat as potential phishing per Ayisha's IR lane.FAILURE(timeout_30min): No human picked up within 30 minutes. Auto-page Ayisha + Lola.Observable states during this step:
tier:regulator with regulator_unclassified tagchannel_routing_overrides[amena] regulator-keyword override fired channel=<x> trigger=<y>Actor: Amena (automated page) + Katherine (manual confirmation).
Action: Mattermost URGENT DM to Ayisha (@balboanyc), Jonathan, and Lola simultaneously. Subject line: "REGULATOR-DIRECT: <agency> <doc_type> — inbound at <time>". Body includes Chatwoot conversation URL and the classified doc_type.
Timeout: Must complete within 15 minutes of STEP 1 success.
Input: Classified ticket from STEP 1.
Output on SUCCESS: Ayisha or Jonathan acknowledges the DM (emoji-ack or "got it") → GO TO STEP 3.
Output on FAILURE:
FAILURE(no_ack_15min): Auto-page via PagerDuty P0 to Ayisha + Jonathan + Lola.FAILURE(no_ack_30min): Auto-page on-call rotation + SMS Jonathan's personal phone.Observable states:
@balboanyc tag in #leadership if no DM acksupport_escalations row written from_tier:t1, to_tier:t3, reason_tag:regulator_inboundActor: Ayisha decides; Amena executes flags; Lola + Rep confirm preservation.
Action: Apply legal_hold:true flag to all customer records, vendor records, COA records, and ledger entries materially related to the matter. Notify Rep + Lola in #legal-hold Mattermost channel. Suspend any scheduled deletions on related records.
Timeout: 2 hours from STEP 2 ack.
Input: Scope determined by Ayisha (which customers, vendors, products, batches, transactions).
Output on SUCCESS: Legal hold confirmed; preservation snapshot scheduled → GO TO STEP 4.
Output on FAILURE:
FAILURE(scope_unclear): Ayisha and outside counsel scope the hold within 24h; in the meantime apply a maximum hold ("freeze everything tagged with the relevant product / vendor / batch").FAILURE(record_already_purged): Document the gap, notify counsel, capture what was lost.Observable states:
legal_hold:true flag visible on affected records; do_not_purge flag set per §17.6 §3.2legal_hold_event row appended (write-only, ledger-style)[legal_hold] applied scope=<x> by=<ayisha> matter=<id>Actor: Rep (technical) + Lola (operational) + Ayisha (decides scope).
Action: Snapshot in-scope records to a tamper-evident archive (S3 bucket with object-lock, retention period = 7 years minimum). Snapshot includes Chatwoot conversation thread, customer records, vendor records, COAs, ledger entries, product images, shipment logs, communication logs.
Timeout: 24 hours from STEP 3 success.
Input: Legal-hold scope from STEP 3.
Output on SUCCESS: Archive checksum verified → GO TO STEP 5.
Output on FAILURE:
FAILURE(checksum_mismatch): Re-snapshot. Document the original failure.FAILURE(records_missing): Document gap, notify counsel.Observable states:
evidence_snapshot row with checksum, scope, snapshot URIActor: Ayisha + Amena.
Action: Create a clock-tracker entry with all applicable regulatory deadlines. Common windows:
| Document type | Clock | Default duration | Notes |
|---|---|---|---|
| Texas DSHS Notice of Violation | NOV response | 10 days to cure or contest (per 25 TAC Chapter 300) | Day 1 = postmark date or hand-delivery date. |
| Texas DSHS NOV | Contest window | 20 days to file formal contest with State Office of Administrative Hearings (SOAH) | Default ask: have outside counsel evaluate by Day 7. |
| FDA Warning Letter | Response | 15 business days | Counsel-drafted only. |
| FTC Civil Investigative Demand (CID) | Production | Specified in document, typically 20–30 days | Negotiable; counsel-led. |
| Subpoena (administrative or judicial) | Compliance | Specified in document | Counsel reviews scope; may move to quash. |
| BBB complaint | Response | 14 calendar days | Lower-stakes but still tracked. |
| Inspection request | Site availability | Specified | Lola schedules. |
| State AG inquiry | Response | Specified | Counsel-led. |
Timeout: Tracker created within 1 hour of STEP 4 success.
Input: Document deadlines from intake.
Output on SUCCESS: Clock visible on /admin/regulatory-matters dashboard with countdown → GO TO STEP 6.
Output on FAILURE:
FAILURE(deadline_already_short): If clock is under 5 days at intake, page Jonathan + outside counsel immediately.Observable states:
regulatory_matter row with deadline_ts, deadline_type, agency, doc_typeActor: Ayisha (notifies); outside counsel acknowledges.
Action: Email Vicente LLP attorney-of-record (Susan Hays or Shawn Hauser for hemp; or general counsel for non-hemp matters) with: scanned document, classification, deadline, evidence snapshot URI, proposed initial response strategy.
Timeout: Within 24 hours of STEP 2 ack. For NOVs with deadlines under 5 days, within 4 hours.
Input: Matter package from STEP 1–5.
Output on SUCCESS: Counsel acknowledges receipt and confirms engagement → GO TO STEP 7.
Output on FAILURE:
FAILURE(counsel_unavailable): Try secondary counsel; if no counsel reachable in 24h with a deadline under 10 days, Jonathan decides whether to retain new counsel or respond pro se under Ayisha's lead. Document the decision.Observable states:
regulatory_matter rowActor: Ayisha + outside counsel jointly. Amena drafts NOTHING customer- or regulator-facing on this matter; her contribution is internal summary only.
Action: Draft the response. Counsel-led, Ayisha provides operational facts, Jonathan reviews substance.
Timeout: Working back from the deadline: draft complete with 3 business days of buffer.
Input: Document, evidence snapshot, counsel's legal analysis, Ayisha's operational facts.
Output on SUCCESS: Draft reviewed by counsel + Ayisha + Jonathan → GO TO STEP 8.
Output on FAILURE:
FAILURE(scope_dispute): Counsel and Ayisha disagree on response strategy. Escalate to Jonathan. Document the disagreement.FAILURE(deadline_pressure): If buffer drops below 1 business day, request extension from the agency. Document the request.Actor: Jonathan.
Action: Review final draft. Jonathan is the named signer on any HempDash regulatory response unless counsel directs otherwise.
Timeout: Within 24 hours of STEP 7 success.
Input: Final draft.
Output on SUCCESS: Signed PDF → GO TO STEP 9.
Output on FAILURE:
FAILURE(jonathan_unavailable): Lola, with Ayisha's confirmation, may sign as "on behalf of" if counsel approves and the regulatory framework allows it. Document the substitution.FAILURE(jonathan_changes_requested): Loop back to STEP 7 with Jonathan's edits.Actor: Outside counsel (preferred) or Ayisha (if counsel directs).
Action: Send via the channel specified in the original document (certified mail, agency portal, attorney-of-record email). Always send via a method that produces a delivery receipt. Send before deadline with at least 1 business day buffer.
Timeout: Hard deadline = the regulatory deadline. Soft deadline = 1 business day before.
Input: Signed response.
Output on SUCCESS: Delivery confirmation captured → GO TO STEP 10.
Output on FAILURE:
FAILURE(delivery_failed): If certified mail returns or portal upload fails, re-send immediately and document the original failure. If deadline is hours away, courier-deliver and call the agency contact to flag.Observable states:
regulatory_matter.response_sent_at, response_doc_uri, delivery_receipt_uriActor: Ayisha.
Action: Regulator may respond with follow-up questions, schedule a hearing, close the matter, or escalate. Track agency replies and loop back to STEP 7 for each new response.
Timeout: Open-ended; matter stays open until agency closes it in writing.
Input: Agency reply (if any).
Output on SUCCESS: Matter closed by agency in writing → audit retained 7 years.
Output on FAILURE:
FAILURE(agency_escalation): Agency moves from inquiry to enforcement action (suspension, fine, license revocation). Escalate to Jonathan + counsel; matter restarts at STEP 6.FAILURE(agency_silent_60d): No reply from agency in 60 days. Counsel decides whether to ping or let matter age. Document the decision.A DSHS inspector or other agency representative arrives unannounced at a HempDash location.
Steps:
@balboanyc + Jonathan + Lola immediately with the photographs.Police, FBI, ATF, DEA, or other law enforcement arrives.
Steps:
@balboanyc + Jonathan + Lola AND calls Jonathan directly.A subpoena demands documents.
Steps:
Private-party C&D is not a §17.5 matter — it's a legal hold under §8.6 of §17.4. Re-route to Ayisha + outside counsel via legal-hold channel.
Steps:
HANDOFF: Intake (Katherine) -> Substantive Owner (Ayisha)
PAYLOAD: {
chatwoot_conv_id: int,
inbound_channel: str, // 'email:compliance', 'phone:ivr:2', etc.
agency: str, // 'dshs', 'tabc', 'fda', etc.
doc_type: str, // 'nov', 'subpoena', 'inquiry', 'cid', 'inspection'
received_at: timestamptz,
deadline_ts: timestamptz?, // null if not yet parsed
sender_domain: str,
sender_verified: bool, // domain matches known-agency list
attachments: [uri]
}
SUCCESS RESPONSE: { acknowledged: true, ack_by: 'ayisha', ack_at: timestamptz }
FAILURE RESPONSE: { ok: false, error: str, code: str }
TIMEOUT: 15 minutes (page Jonathan + Lola on miss)
ON FAILURE: Auto-escalate to PagerDuty P0 (Ayisha + Jonathan + Lola)
HANDOFF: Ayisha -> Outside Counsel (Vicente LLP attorney-of-record)
PAYLOAD: {
matter_id: uuid,
agency: str,
doc_type: str,
deadline_ts: timestamptz,
document_uri: uri, // scanned, in tamper-evident archive
evidence_snapshot_uri: uri,
proposed_strategy: text,
operational_facts: text,
contacts: { ayisha_email, jonathan_email, lola_email }
}
SUCCESS RESPONSE: { engaged: true, attorney_of_record: str, billing_arrangement: str }
FAILURE RESPONSE: { ok: false, error: str, retryable: bool }
TIMEOUT: 24 hours (4 hours if deadline under 5 days)
ON FAILURE: Try secondary counsel; escalate to Jonathan
HANDOFF: HempDash -> Agency
PAYLOAD: {
matter_id: uuid,
response_doc_uri: uri, // signed PDF
signed_by: str, // 'jonathan' or counsel-of-record
delivery_method: str, // 'certified_mail' | 'agency_portal' | 'email' | 'courier'
delivery_recipient: str, // agency contact name + title
sent_at: timestamptz,
deadline_ts: timestamptz
}
SUCCESS RESPONSE: { delivery_receipt_uri: uri, received_at: timestamptz }
FAILURE RESPONSE: { ok: false, error: str, code: str }
TIMEOUT: Hard deadline = regulatory deadline. Soft = 1 business day before.
ON FAILURE: Re-send via alternate method; call agency; document
| Stage | Customer/regulator sees | Operator sees | Database | Logs |
|---|---|---|---|---|
| Inbound landed | Auto-ack from compliance@ if email; nothing if other channel |
Chatwoot conv with regulator_unclassified tag |
channel_routing_overrides row |
Routing event |
| Classified | Same | Conv tag updated to agency:<x>, doc_type:<y> |
regulatory_matter row created |
Classification event |
| Ayisha paged | Same | Mattermost URGENT DM thread visible | support_escalations row |
Page fired |
| Legal hold active | Same | legal_hold:true flag on affected records |
legal_hold_event row |
Hold applied |
| Evidence preserved | Same | Archive URI in matter | evidence_snapshot row |
Snapshot complete |
| Clock tracker live | Same | Countdown on /admin/regulatory-matters |
regulatory_matter.deadline_ts |
Tracker created |
| Counsel engaged | Same | Counsel-engagement flag set | regulatory_matter.counsel_engaged_at |
Engagement |
| Response drafted | Same | Draft in matter folder | Draft URI on row | Draft saved |
| Response sent | Regulator sees response | Sent flag + delivery receipt | regulatory_matter.response_sent_at |
Send event |
| Matter closed | Closure letter from agency | Closed flag on matter | regulatory_matter.closed_at |
Close event |
| Step | Internal SLA | Regulatory deadline |
|---|---|---|
| Intake (STEP 1) | 30 minutes from inbound | n/a |
| Ayisha + Jonathan paged (STEP 2) | 15 minutes from intake success | n/a |
| Legal hold (STEP 3) | 2 hours from page-ack | n/a |
| Evidence snapshot (STEP 4) | 24 hours from legal hold | n/a |
| Clock tracker (STEP 5) | 1 hour from snapshot | n/a |
| Counsel engaged (STEP 6) | 24h (4h if deadline under 5 days) | n/a |
| Response drafted (STEP 7) | 3 business days before deadline | Per document |
| Jonathan signs (STEP 8) | 24h from draft ready | n/a |
| Response sent (STEP 9) | 1 business day buffer before deadline | Hard deadline = agency deadline |
Key regulatory clocks (Texas focus):
If the document does not state a deadline, Ayisha + counsel assume the most restrictive applicable timeline.
If Katherine doesn't pick up compliance@ and Amena's auto-page also fails (Mattermost down, etc.), the after-hours fallback in §16 §5 fires — Ayisha gets pinged via secondary channel. Worst-case (full Mattermost + email outage), the inbound still sits in the Google Groups inbox; Ayisha is a member and will see it on next inbox check. Risk: deadline burn during outage. Mitigation: Ayisha checks compliance@ inbox every morning regardless of paging.
Lola covers for Ayisha. The escalation chain on Ayisha-unavailable: Lola → Jonathan → outside counsel direct. Lola has full authority to engage counsel under §16 §8 founder-pull threshold; she does not need Jonathan's approval to call counsel on a regulator matter.
A customer who isn't a regulator may threaten to "report this to DSHS." That's a §17.4 matter (abuse / threat or T2 escalation depending on tone). It's not a regulator-direct contact until DSHS contacts us. Do not initiate §17.5 from a customer threat.
If an agency files a lawsuit, this becomes a litigation matter under §8.6 of §17.4. Outside counsel takes over; §17.5 audit trail feeds into discovery.
Document the miss in regulatory_matter.deadline_missed:true. Outside counsel and Ayisha decide the recovery posture (apologize + cure, contest the timeline, request extension, accept the penalty). Jonathan reviews. Treat as a P0 retrospective.
This should be impossible. Amena's outbound contract (§16 §4) forbids external replies. If somehow Amena does reply, treat as a P0 incident: Rep audits the bot's outbound, Ayisha reviews the message content, Jonathan decides whether to contact counsel about retraction.
Common: DSHS sends a NOV by mail, then a DSHS staffer calls or emails directly. Amena correlates new inbound to existing regulatory_matter.id by sender domain, agency name, and matter context. Ayisha confirms the correlation manually. New inbound becomes a STEP 11 (follow-up) on the existing matter, not a new matter.
CREATE TABLE regulatory_matter (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
chatwoot_conv_id INT,
agency TEXT NOT NULL, -- 'dshs', 'tabc', 'fda', etc.
doc_type TEXT NOT NULL, -- 'nov', 'subpoena', 'inquiry', etc.
received_at TIMESTAMPTZ NOT NULL,
deadline_ts TIMESTAMPTZ,
deadline_type TEXT, -- 'nov_cure', 'contest', 'production', etc.
document_uri TEXT NOT NULL, -- in tamper-evident archive
evidence_snapshot_uri TEXT,
counsel_engaged_at TIMESTAMPTZ,
counsel_of_record TEXT,
response_draft_uri TEXT,
response_sent_at TIMESTAMPTZ,
response_doc_uri TEXT,
delivery_receipt_uri TEXT,
closed_at TIMESTAMPTZ,
closure_reason TEXT,
deadline_missed BOOLEAN DEFAULT false,
notes TEXT,
created_by TEXT NOT NULL,
CONSTRAINT regulatory_matter_doc_type_check
CHECK (doc_type IN ('nov','subpoena','inquiry','cid','inspection','warning_letter','bbb_complaint','other'))
);
CREATE INDEX idx_regulatory_matter_agency ON regulatory_matter(agency);
CREATE INDEX idx_regulatory_matter_deadline ON regulatory_matter(deadline_ts);
CREATE INDEX idx_regulatory_matter_open ON regulatory_matter(closed_at) WHERE closed_at IS NULL;
CREATE TABLE legal_hold_event (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
matter_id UUID NOT NULL REFERENCES regulatory_matter(id),
action TEXT NOT NULL, -- 'applied' | 'removed' | 'scope_changed'
scope JSONB NOT NULL, -- which customers, vendors, batches, ledger entries
by_actor TEXT NOT NULL,
at_time TIMESTAMPTZ NOT NULL DEFAULT now(),
notes TEXT
);
-- LedgerEntry-style write-only invariant per project_ledger_write_only.md
CREATE TABLE evidence_snapshot (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
matter_id UUID NOT NULL REFERENCES regulatory_matter(id),
archive_uri TEXT NOT NULL,
checksum TEXT NOT NULL,
scope JSONB NOT NULL,
taken_at TIMESTAMPTZ NOT NULL DEFAULT now(),
taken_by TEXT NOT NULL
);
7 years minimum from matter close, or longer if any regulatory framework requires longer. DSHS-related matters: 7 years per state retention rules. FDA-related: 7 years per FDA recordkeeping guidance.
| # | Question | Owner | Why it matters |
|---|---|---|---|
| Q1 | Outside counsel arrangement — is Vicente LLP on retainer or pay-per-matter? Engagement letter signed? | Jonathan + Ayisha | Affects STEP 6 timeline. If no retainer, intake-to-engagement may be slower. |
| Q2 | Known-agency sender domain list — maintained where? | Ayisha | Needed for STEP 1 spoof detection. |
| Q3 | Tamper-evident archive — S3 + object lock + KMS? Or different provider? | Rep + Ayisha | Required for STEP 4 evidence integrity. |
| Q4 | regulatory_matter table — new migration, Katherine reviews. |
Rep | Migration gate. |
| Q5 | /admin/regulatory-matters dashboard — already exists, planned, or new build? |
Lola + Rep | Visibility for STEP 5 clock tracker. |
| Q6 | DSHS contact directory — current named contacts at the agency? | Ayisha | Faster response if we know the right human. |
| Q7 | After-hours regulator inbound — if a NOV arrives at 8pm Friday, what's the 15-minute page-target on a weekend? | Ayisha + Jonathan | Default: SMS Jonathan + Ayisha personal phones. Confirm. |
| Q8 | Legal hold scope-default — when scope is unclear, "freeze everything tagged with the relevant product / vendor / batch" is the proposed default. Confirm. | Ayisha + counsel | Avoids accidental data destruction during scoping. |
regulatory_matter, legal_hold_event, evidence_snapshot tables exist; Katherine reviewed./admin/regulatory-matters dashboard live with countdown timers.| Version | Date | Author | Change |
|---|---|---|---|
| 0.1 | 2026-05-11 | Workflow Architect (Amena) | Initial draft. |
SOP index · NOV Response · Inspection Day Response · Press/Media Routing · Home