Every cold prospect DarDev imports into Twenty CRM starts with consentEmail set to UNKNOWN—not OPT_IN, not blank, and never implied by a public directory email. UNKNOWN means we may hold legitimate interest data for sales follow-up in CRM, but we do not treat the contact as subscribed to Listmonk marketing or bulk outreach lists. The 20.tn ecoles.com.tn school pipeline applies this rule to roughly nine hundred staging records; Hesabi OECT and Startup Tunisia imports used the same field years earlier.
CRM-first discipline is the spine of crm-driven-product-lists on news.dardev.net: Twenty owns segmentation, consent, and human decisions; Listmonk owns opted-in product audiences. Unified Mailer transport in inside-unified-mailer-stack moves mail only after those gates clear. Sales staff experience the policy daily in 20tn-outreach-one-school-at-a-time workflows—approve one Person, send one tracked intro, never import-and-blast.
What UNKNOWN means operationally
UNKNOWN is an explicit enum value on Person records, not an empty field waiting for a default. Importers set it on create alongside targetSolution, leadSource, and regionMarket so views and sync jobs can filter predictably. Documented tag vocabulary—consent:unknown on notes or future automations—mirrors the field but does not replace it; workflows and platform-bus read consentEmail, not free-text tags.
- UNKNOWN — cold import; CRM sales allowed; no marketing list; tracked TX only after sync gates and approval
- OPT_IN — subscribe form, written consent, or explicit marketing permission; may sync to Listmonk product lists
- OPT_OUT — unsubscribe webhook or human request; block all promotional sends and update CRM immediately
20.tn ecoles import defaults
The ecoles.com.tn pipeline documented in ecoles-scrape-to-crm-pipeline maps schools into Companies and Persons with targetSolution OPT20TN, leadSource ECOLES_ANNUAIRE, recordSegment by ownership, and regionMarket TUNISIA. consentEmail UNKNOWN is set in import_ecoles_twenty.py for every created Person regardless of whether the listing card showed an email address. No Listmonk API calls run during import; staging checkpoints and scrape-state.json never contain marketing list ids.
Scope v1 includes public and private schools; ICP prioritization happens in CRM views—filter private with email for first outreach waves—without deleting public records or rewriting consent at import time. Empty Person rows are acceptable when the directory lists phone only; fabricating placeholder emails would poison deliverability and falsify consent.
Allowed paths while consent stays UNKNOWN
- CRM research, notes, tasks, and timeline activities attached to Company or Person
- Phone-first outreach logged manually when no email exists
- Segmentation views for sales prioritization without SMTP
- Workflow dry-run and send-one validation with dryRun true
- Promotion to Listmonk private list via sync-20tn-outreach when bus rules pass—still not a campaign blast
- Single tracked transactional intro after human approval in 20tn outreach workflows
Sync to Listmonk product:20tn:marketing is not consent upgrade by itself. Sync creates a subscriber row for transactional APIs; consentEmail remains UNKNOWN until OPT_IN from a form or explicit permission change. Bus sync filters allow UNKNOWN alongside OPT_IN for outreach candidates but never OPT_OUT. SkippedConsent counters in sync responses usually mean OPT_OUT or missing email—not a reason to force subscribe.
Forbidden shortcuts
- Auto-subscribe on CRM Person created webhook to any marketing list
- Listmonk campaign to entire import CSV
- Setting OPT_IN because the source was a public website
- Bulk Zoho mail merge from @dardev.net to cold schools
- Removing unsubscribe handling on the 20.tn Listmonk list
DarDev Ops orchestrates pipelines; it does not override consent fields. Scraper connectors write staging JSON on the operator PC; import scripts respect the lock file pattern used in other Twenty bulk jobs so partial reruns do not duplicate Persons or flip consent accidentally.
Transitioning UNKNOWN to OPT_IN
Valid upgrades include: director submits a product subscribe form with double opt-in, written reply granting marketing mail, or in-person demo agreement logged by sales with a Note citing evidence. Workflows may PATCH consentEmail to OPT_IN and trigger webhook sync to Listmonk tags—product:20tn:marketing and future newsletter segments. Each upgrade should leave a timeline artifact auditors can follow.
Invalid upgrades: bulk spreadsheet edit, because competitor does it, or because one intro email got a polite reply without marketing permission. Reply to a tracked transactional intro starts a sales conversation—it does not automatically opt someone into monthly product news.
OPT_OUT and webhook authority
When a recipient unsubscribes from a tracked message, Listmonk fires webhooks that platform-bus translates into CRM notes and consentEmail OPT_OUT. Future sync and send-one calls must skip that Person. Re-subscribe requires a fresh OPT_IN path—not a CRM admin toggling the field without evidence.
This mirrors Hesabi and DarDev Services pipelines: marketing product lists are downstream of consent state, not upstream of sales judgment.
Cross-product consistency
Hesabi OECT accountant imports and Startup Tunisia SMB scrapes land in CRM with the same UNKNOWN default—documented in prospect import playbooks under integrations in the monorepo. DarDev Services Tunisia SMB outreach uses targetSolution DARDEV with identical Listmonk separation. 20.tn is not a special case exempt from ethics; it is the newest large directory import using mature fields.
deployed-realities-explained on news.dardev.net states what is live versus roadmap without inventing customer counts. Consent discipline is live; full engagement automation for every product is still phased—see 20tn-outreach-roadmap-honest-status for executor maturity.
Fields and views sales should use
- Filter consentEmail = UNKNOWN for cold pool review
- Require outreachApproved true before workflow send steps
- Join company schoolOwnership PRIVE when running first-wave email outreach
- Exclude outreachStatus ERROR until data fixed
- Use outreachPersonalLine for human tone—not consent bypass
Technical orchestration—HTTP Request URLs, bus bearer tokens, iterator batch sizes—lives in 20tn-crm-workflow-orchestration. This guide states the policy those workflows must enforce: CRM first, consent explicit, mail tracked and singular.
Publication and privacy boundaries
Public articles cite aggregate import totals and field names only—no sample school emails, phone numbers, or staging row excerpts. PII stays in CRM and gitignored data directories on the operator workstation. When sharing progress externally, cite rounded counts and phase status, not individual établissement identities unless the school agreed to a case study.
Does UNKNOWN mean we cannot email the school?
It means we cannot treat them as marketing subscribers. Approved tracked transactional outreach to one Person—after sync and workflow gates—is the designed path for 20.tn intros, not newsletter campaigns.
Why import emails at all if consent is unknown?
CRM needs accurate contact data for segmentation and lawful sales outreach. UNKNOWN separates having an address from having newsletter permission.
Does sync-20tn-outreach change consent to OPT_IN?
No. Sync adds or updates a Listmonk subscriber for transactional delivery. consentEmail stays UNKNOWN until an explicit opt-in event updates CRM.
How does this relate to Hesabi imports?
Same field, same rule: CRM only on import, Listmonk only after opt-in. See crm-driven-product-lists for the worker and webhook promotion pattern.
What should engineers implement first?
Importers that set UNKNOWN, sync filters that exclude OPT_OUT, send-one validation, and unsubscribe webhooks that PATCH consent—before any campaign UI shortcut.



