How the SMS-Compliance Auditor works
SMS-Compliance Auditor · Internal reference
How a case travels from a domain to a Twilio-ready submission.
The auditor is a four-stage pipeline. Each stage produces a saved report a Twilio reviewer could read.
The document below walks the flow end-to-end and zooms in on the piece we rebuilt this session — the
TCPA scope-alignment step inside the Submit Package Draft.
Backend · sms-compliance-auditor
Region · us-east1
Frontend · brand-audit.html (CDN)
Storage · Firestore cases/{domain}
1 · the pipeline
Four stages, each one saveable and shareable.
Every case walks the same path: audit the brand's website, generate the implementation package the
brand needs to update on their site, generate the submit package the operator sends to Twilio, and,
if the submission is rejected, generate a remediation package. Each stage writes a Firestore report;
each stage's public URL is what the operator shares with the brand.
STAGE 1
Initial scan
Audit the site
score + findings
STAGE 2
Implementation
Corrected copy
for the brand's site
STAGE 3 · this session
Submit package
Draft the 3 fields
Twilio requires
STAGE 4
Rejection fix
Only if Twilio
rejects the kit
Operator enters
site + signup URLs
Every stage writes a report doc to Firestore cases/{domain}
and returns a public URL the operator shares with the brand.
Stage 3 is where the TCPA scope-alignment feature lives — it's the diagram we spend the rest of this
document unpacking.
2 · what happens inside an audit
The audit does three passes in one call.
When the operator hits Run audit , the backend does three concurrent-ish passes: fetch every
page the operator listed, run deterministic regex checks against the extracted text, and run the LLM
audit that produces the human-facing findings. This session added a fourth pass — the TCPA checkbox
classifier — that reads the sign-up consent text and figures out which message categories the live
checkbox actually authorizes. That output is the ground truth Stage 3 later uses to pre-select scopes.
POST /audit
site_url · privacy_url · terms_url · signup_url · signup screenshot
Pass 1 · Fetch & render pages
HTML + text stored on pages.{site,privacy,terms,signup}
Pass 2 · Deterministic
Regex checks (STOP, HELP,
rates, frequency, links, addr)
Extracts consent paragraph
Pass 3 · LLM audit
Reads all pages + screenshots
Emits PASS/FAIL per check,
recommends Path A / B / D
Pass 4 · TCPA classifier
Reads the extracted checkbox
text and/or the screenshot;
outputs authorized scope IDs
consent paragraph handed off
Audit report saved to Firestore
report.sections.signup.checkbox_scope_analysis
is where the classifier's verdict lives — Stage 3 reads it directly.
Blue outline = new in this session · The classifier writes both authorization verdicts and per-scope evidence with quoted phrases.
3 · what happens when you press "generate submit package draft"
Stage 3 is the TCPA loop — from checkbox to Twilio-ready draft.
This is the flow we rebuilt this session. The operator picks a path (A, B, or D), and the picker
below the path selector pre-ticks the scopes the classifier said the live checkbox authorizes.
Every deviation from that ground truth surfaces as an alert; the operator either fixes the
checkbox, force-includes with a written justification, or accepts the warning and proceeds.
Once the operator hits Generate , the backend assembles a prompt that feeds the LLM the
verbatim live checkbox text, the selected scopes, and any force-included scopes with their
admin justification.
Operator opens the draft card
Picks Path A / B / D from the dropdown
Picker pre-ticks scopes the checkbox authorized
Reads checkbox_scope_analysis.detected_scope_ids
Blue AUTO badges with hoverable quoted evidence
Operator ticks / unticks scopes
Every change re-computes the alert banner in real time
Alert banner evaluates 5 conditions
H1 empty overlap · H2 authorization absent · H3 no consent text
S1 over-selected · S2 low classifier confidence
(reference table further down)
Fix the checkbox
"Copy suggested language"
— operator updates site,
re-audits, warning clears.
Force include
Per-scope chip opens modal;
40-char justification + ack;
stored on the case record.
Accept the warning
Proceed at compliance risk.
Twilio reviewer will likely
reject with 30454 / 30496.
POST /submit-draft
Payload: selected_scopes + forced_scopes[] + extracted_consent_text
LLM emits the 3 Twilio fields, aligned to the scopes
opt_in_workflow_description · use_case_description · sample_messages
The forced_scopes payload carries the admin justification into the LLM prompt so the model treats
the override exactly like an operator-selected scope for alignment purposes — descriptions and
samples still cover it, and the audit trail lives on the case record.
4 · reference — the three checkbox states
What the picker shows for each scope.
Every scope checkbox lands in one of three visual states. The state encodes the compliance basis
behind the tick, not the operator's preference — the amber FORCED pill on a scope means an admin
approved it out-of-band, not that the operator "really wants" it.
Auto-detected
Blue left border, "AUTO" badge, hoverable tooltip showing the exact phrase from the checkbox
that authorized this category.
Fires when: the scope appears in detected_scope_ids
Manually added
Amber-tinted row with a red "not in checkbox" chip. The operator ticked something the classifier
didn't detect — a compliance risk that needs to be resolved before submission.
Fires when: operator ticks a scope not in the detected set
Force-included
Amber left border, "FORCED" pill, tooltip showing the admin justification, timestamp, and the
live checkbox snapshot at time of override.
Fires when: admin approved via the Force Include modal
5 · reference — the five alert conditions
What the "Checkbox Insufficient" banner is telling you.
Hard conditions block confident submission — the campaign is misaligned with what the checkbox
legally authorizes. Soft conditions signal something worth eyeballing but not blocking. Both fire
live as the operator toggles scopes.
H1
None of your selected scopes are authorized by the checkbox. Every ticked scope is outside the detected set — the campaign has no TCPA basis. Untick the mismatched scopes, update the checkbox, or force-include each one.
Hard
H2
Marketing (or transactional) authorization is absent. The classifier read the checkbox and found no language authorizing this path at all. Path A campaigns with an absent marketing authorization are the Vitalveo failure mode — Twilio reject 30496.
Hard
H3
No consent-checkbox text could be read. Neither the sign-up URL fetch nor the uploaded screenshot yielded readable text. Provide a clearer sign-up URL or a higher-res screenshot and re-audit.
Hard
S1
N selected scopes are NOT covered by your checkbox. Each over-selected scope gets its own per-scope "Force include" chip in the banner body — the primary Force Include entry point.
Soft
S2
N auto-detected scopes have low confidence. Classifier match confidence is below 0.5 for at least one detected scope. Hover the AUTO badge, read the quoted phrase, decide whether it really authorizes that category.
Soft
6 · the force-include lifecycle
What happens when an admin overrides.
Force Include is the escape hatch for cases where the operator has confirmed out-of-band that the
live checkbox will be updated before submission, or where legal has separately authorized the
override. Every use writes an audit-trail entry. Re-audits preserve the entry and flag it for
re-verification unless the fresh classifier now catches the scope on its own.
1 · Modal opens
Admin clicks per-scope
"Force include" chip in the
alert banner.
2 · Justify & acknowledge
Min 40 chars written reason;
acknowledgement checkbox;
save button unlocks.
3 · Recorded on the case
Firestore arrayUnion writes to
cases/{domain}.
force_included_scopes[]
4 · Scope row swaps to FORCED
Amber left border, "FORCED" pill,
tooltip carries the justification.
No page reload.
5 · Next Generate carries it forward
The scope pre-ticks; the payload includes
forced_scopes[] with the justification.
LLM aligns descriptions + samples to it.
6 · Re-audits preserve, with a re-verify flag
If the fresh classifier still misses the scope: entry carries over,
shows a "Re-verify" badge. If the checkbox has caught up and the
classifier now detects it natively: entry is marked redundant.