Consent is a runtime check, not a field
Quiet hours, attempt caps, and channel blocks have to be evaluated at the moment of the touch.
Open any CRM and find the consent field. It is a checkbox, or a tag, or a custom property named something like “SMS opt-in”. It was set once, by someone, on some date. Then the contact texted STOP to your provider, or moved to a state with different quiet hours, or asked on a call last week not to be texted before nine. The checkbox did not hear any of that.
That is the problem with consent as a field. A field is a fact about the past. Contactability is a question about now: is this touch, on this channel, to this person, at this location’s local time, allowed? The only honest way to answer it is to ask at the moment of the touch.
What “runtime” means here
In DialSplice the contactability preflight runs before every touch and evaluates per channel. It checks, at execution time:
- Consent for the channel. Voice, SMS, and email are separate answers, because a person can agree to one and refuse another.
- Quiet hours in the location’s local time, not the agent’s.
- The attempt cap for the location, and how many attempts have already been made.
- Holidays and channel blocks.
The result is shown to the agent as a row per channel. In the workspace it looks like this: Voice · OK · consent on file. SMS · Blocked · quiet hours until 8:00 local. Email · OK · opt-in on file. The agent knows, before pressing anything, which of Call, Text, and Email is actually available.
“Runtime” is doing real work in that sentence. The check is not cached from the morning. It is not the result of a nightly sync. It is computed when the agent is about to act, against the rules that are active in the location’s configuration at that moment.
Why “at the moment of the touch” is the whole point
Consider a confirmation SMS scheduled as part of a callback workflow. The disposition “Callback requested” is set early in the afternoon. The policy says: send a confirmation now, send a reminder one hour before the callback. Both messages are policy sends. Both are preflighted separately, at send time.
The confirmation passes: consent on file, quiet hours clear, sent via the provider. The reminder is scheduled for later and preflighted again when it comes due. If the contact revoked SMS consent in between, or the reminder time falls inside quiet hours, the reminder is blocked, and the block is visible in the workflow as “Policy · pending”. The confirmation passing did not grant the reminder anything.
A system that checked once, at scheduling time, would have sent both. A system that checks at execution time sends only the one that was allowed when it was actually sent.
The same logic applies to the callback itself. A contact who asked to be called at 4 p.m. has not waived the attempt cap or the quiet-hours rule. When the callback surfaces, the preflight runs again, and the agent sees the current answer, not the one from when the promise was made.
The rules are configuration, and configuration is versioned
Quiet hours, attempt caps, and cadence are not hard-coded. They live in the location configuration, which is a revision with a content hash. A revision is approved, then activated, and can be rolled back, and each of those is a separate ledger event. The admin panel shows “Consent and quiet-hours rules · Valid” under readiness checks because the rules are validated before a revision can go live.
This matters for a compliance lead in a specific way. When someone asks what the quiet hours were at Northgate on a given afternoon, the answer is a revision number, and the ledger shows when it was activated and by whom. The preflight row itself is on the ledger too, as preflight.evaluated with the actor “policy”. You can show not only what the rule was but that it was evaluated before the touch.
Fail closed
If the location is unknown, or the scope on the request is ambiguous, the preflight does not fall back to the organization’s default rules. It fails closed. An unknown location never inherits another’s consent state, caller ID, or quiet hours. The agent sees a block rather than a guess, and the block is logged.
That is uncomfortable the first time it happens on a busy afternoon. It is also the behaviour you want on the ledger when someone asks why a contact in a different state was not texted before eight in the morning.
Where the consent data lives
DialSplice does not become the consent system of record. Consent and do-not-contact flags are read from your CRM under your scopes at evaluation time. The preflight asks; it does not copy the answer into its own store. What the ledger keeps is the evaluation event and its hash, not the contact’s identity. So the audit trail proves that consent was checked without becoming a second place where consent lives.
This also means a correction in the CRM takes effect on the next touch. There is no sync to wait for and no cached verdict to expire. If the contact withdraws consent on a call, the agent sets the disposition “Do not contact”, the CRM is updated from that event, and the next preflight for any channel returns a block.
What to ask your vendor
- Is consent evaluated per channel, or is there one flag for the contact?
- When is the check performed: at scheduling, at queue time, or at the moment of the send or dial?
- Whose time zone are quiet hours computed in?
- What happens when the location or scope is unknown: default rules, or a block?
- Is the evaluation itself logged, so you can prove it ran, not only that the rule existed?
See your stack, spliced.
Bring the names of your phone system, CRM, and system of record; we'll show you the workspace your agents would use.