Dental patient communication

SmileCue

More Smiles, Fewer No-Shows

SmileCue is a HIPAA-compliant patient communication platform that automates SMS, email, and voice reminders with adaptive, response-driven branching. It empowers dentists, hygienists, and office managers at small-to-medium practices to cut manual scheduling by 60%, boost confirmations to 85% within three months, and reduce no-shows up to 40%.

Subscribe to get amazing product ideas like this one delivered daily to your inbox!

SmileCue

Product Details

Explore this AI-generated product idea in detail. Each aspect has been thoughtfully created to inspire your next venture.

Vision & Mission

Vision
Empower dental teams to eliminate no-shows, reclaim staff time, and deepen patient relationships with effortless HIPAA-compliant outreach.
Long Term Goal
Empower 10,000 dental practices to cut no-shows by 30% and reclaim 20+ staff hours monthly within 3 years via HIPAA-compliant automated patient outreach.
Impact
Reduces no-shows up to 40% and raises appointment confirmations to 85% within three months for dentists, hygienists, and office managers at small practices, while cutting weekly scheduling time by 60%, freeing staff to focus on care and revenue-generating tasks.

Problem & Solution

Problem Statement
Dentists, hygienists, and office managers at small dental practices spend hours making manual appointment calls and texts yet still face frequent no-shows and low confirmations because generic schedulers lack HIPAA-safe personalization, adaptive follow-ups, and two-way messaging.
Solution Overview
Automated HIPAA-compliant outreach sequences personalized SMS, email, and voice using response-driven branching to confirm appointments and enable one-click rescheduling via calendar integration, replacing hours of manual calls with higher confirmation rates and fewer no-shows.

Details & Audience

Description
SmileCue is a HIPAA-compliant patient communication platform that automates appointment reminders, confirmations, and post-care follow-ups via SMS, email, and voice. It serves dentists, hygienists, and office managers at small-to-medium dental practices. SmileCue reduces no-shows up to 40%, cuts weekly scheduling time by 60%, and raises confirmations to 85% within three months. Its adaptive messaging sequences change tone and channel based on patient responses.
Target Audience
Dentists, hygienists, and office managers (30-55) at small practices, time-pressed, adopting automated reminders.
Inspiration
During a temp shift at a packed dental clinic, I watched the receptionist spend two hours dialing, leaving voicemails, and still lose three appointments. One patient missed an urgent crown repair because a reminder text arrived in the wrong language. That afternoon I sketched an empathetic, HIPAA-safe communication engine: adaptive messages that change tone, language, and channel until patients confirm or easily reschedule, sparing staff hours and lost care.

User Personas

Detailed profiles of the target users who would benefit most from this product.

T

Treatment Closer Carla

- Role: Treatment Coordinator at a 4-operatory general practice. - Experience: 7 years dental admin; former chairside assistant. - Location: Suburban Midwest; mid-range pay with bonus tied to acceptance. - Education: Dental assisting certificate; CE in case presentation.

Background

Started as a dental assistant, learning the cadence of patient trust. Built a spreadsheet follow-up system that broke under growth. Now pushes automation to reclaim time and prevent leads from going cold.

Needs & Pain Points

Needs

1. Automated follow-ups by treatment value and urgency. 2. Objection-based branching with approved responses. 3. Payment link reminders and financing prompts.

Pain Points

1. Leads stall without timely, tailored nudges. 2. Error-prone spreadsheet tracking and sticky notes. 3. Patients unreachable during traditional call windows.

Psychographics

- Obsessive about turning intent into action. - Empathy-first persuader; builds trust before asking. - Data validates every workflow change. - Hates friction; loves crisp, guided flows.

Channels

1. LinkedIn — dental groups 2. Dentaltown — case acceptance 3. Email — work inbox 4. YouTube — how-tos 5. Zoom — CE webinars

P

Pediatric Parent Priya

- Role: Office Manager at a 6-chair pediatric dental clinic. - Experience: 8 years in pediatrics; bilingual English–Spanish. - Location: Urban Sunbelt; high parent mobility; mid-income community. - Education: BA in Health Admin; AAPD member.

Background

Started as a receptionist juggling carpool-time chaos and guardianship forms. Built bilingual scripts to calm anxious parents. Now needs automation that respects family routines and languages.

Needs & Pain Points

Needs

1. Sibling bundling and guardian-specific messaging. 2. After-school and weekend slot targeting. 3. Multilingual templates with quick toggles.

Pain Points

1. No-shows around naps and school events. 2. Guardians change numbers frequently. 3. Consent forms delay scheduling.

Psychographics

- Family-centered scheduler with relentless empathy. - Champions clear, friendly, non-clinical language. - Pragmatic; favors tools parents actually use. - Measures success by calmer lobby visits.

Channels

1. Facebook Groups — pediatric dentistry 2. LinkedIn — office managers 3. Email — practice newsletters 4. AAPD Listserv — announcements 5. YouTube — parent education

O

Ortho Optimizer Owen

- Role: Scheduling Coordinator at a two-doctor orthodontic practice. - Experience: 5 years ortho; aligner and braces workflows. - Location: Suburban commuter belt; teen-heavy patient base. - Education: Some college; AAO continuing education.

Background

Cut his teeth managing chaotic after-school rushes. Built a color-coded board that failed during growth. Now seeks automation keyed to treatment phases and school calendars.

Needs & Pain Points

Needs

1. Recurring reminders mapped to treatment phases. 2. Missed-adjustment backfill with waitlist. 3. Bite-timer and elastic-wear nudges.

Pain Points

1. Teens ignore calls and emails. 2. Missed adjustments extend treatment months. 3. Peak after-school bottlenecks.

Psychographics

- Throughput-focused, never sacrificing patient experience. - Loves templates tied to clinical phases. - Prefers dashboards over digging into spreadsheets. - Competitive; benchmarks no-show rates weekly.

Channels

1. Orthotown — workflows 2. LinkedIn — orthodontic teams 3. Email — templates tips 4. YouTube — practice efficiency 5. AAO Webinars — scheduling

S

Surgery Prep Sam

- Role: Surgical Coordinator at a maxillofacial practice. - Experience: 6 years OMS scheduling and insurance. - Location: Regional hub; high referral volume. - Education: CMA; ACLS-certified; AAOMS member office.

Background

Learned the hard cost of day-of cancellations. Built binders of checklists that couldn’t scale. Now needs automated confirmations that catch noncompliance early.

Needs & Pain Points

Needs

1. Pre-op confirmations with fasting and escort checks. 2. Driver contact capture and reminders. 3. Post-op check-ins with symptom triage.

Pain Points

1. Day-of cancellations from fasting noncompliance. 2. Incorrect or missing escort details. 3. After-hours post-op call spikes.

Psychographics

- Risk-averse, compliance-first, relentlessly thorough, always. - Direct communicator; zero ambiguity tolerated. - Relishes checklists with clear escalation paths.

Channels

1. LinkedIn — surgical coordinators 2. AAOMS Webinars — compliance 3. Email — surgeon updates 4. YouTube — patient education 5. Vendor Docs — integration guides

C

Compliance Custodian Casey

- Role: Privacy/Compliance Officer or IT Manager. - Experience: 10+ years healthcare IT or operations. - Location: Multi-provider practice; regulated payer mix. - Certifications: HIPAA, Security+, occasional SOC 2 reviewer.

Background

Started in EHR administration during an OCR audit scare. Built access controls and incident playbooks. Now evaluates messaging tools for compliance, logging, and data lifecycle.

Needs & Pain Points

Needs

1. Signed BAA and documented safeguards. 2. Role-based access and SSO. 3. Immutable audit logs and exports.

Pain Points

1. Staff using personal phones for PHI. 2. Vendors vague on data retention. 3. Manual audit prep consuming weeks.

Psychographics

- Zero tolerance for ambiguous compliance claims. - Prefers evidence over promises; asks for artifacts. - Simplifies policies so staff actually comply. - Defaults to least privilege, always.

Channels

1. LinkedIn — healthcare security 2. HHS OCR — updates 3. Email — security advisories 4. Vendor Trust — security portals 5. Reddit — r/healthIT

A

Access Advocate Carmen

- Role: Dental Care Coordinator at FQHC community clinic. - Experience: 6 years safety-net operations; multilingual. - Location: Urban core; Medicaid-heavy; high housing mobility. - Education: Community health worker certification.

Background

Grew up locally translating for relatives at clinics. Built contact-update drives and transit reminder scripts. Now needs automation that adapts to unstable phones and shifting schedules.

Needs & Pain Points

Needs

1. Auto language detection and translation. 2. Voice fallback on SMS failure. 3. Bulk outreach with dynamic time windows.

Pain Points

1. Frequent number changes and disconnected phones. 2. Transportation and childcare disruptions. 3. Limited data plans block links.

Psychographics

- Equity-driven; prioritizes access over convenience. - Resourceful problem-solver under chronic constraints. - Patient advocacy guides every workflow choice.

Channels

1. Facebook Groups — community clinics 2. Email — grantee lists 3. NACHC Webinars — operations 4. WhatsApp — staff coordination 5. LinkedIn — safety-net networks

Product Features

Key capabilities that make this product valuable to its target users.

Jurisdiction Rules

Automatically applies state- and country-specific TCPA requirements, quiet hours, and consent classes (informational vs. marketing) based on patient location and channel. Eliminates guesswork for staff and reduces legal exposure by ensuring every send follows the right rule set without manual configuration.

Requirements

Jurisdiction Resolution Engine
"As an office manager, I want SmileCue to automatically determine each patient’s applicable jurisdiction and local time so that messages always follow the correct rules without manual setup."
Description

Determine the correct legal jurisdiction and local time context for each intended communication based on patient data (verified address, phone country code/area code, and stored timezone), with robust fallback logic when signals conflict or are missing. The engine outputs a normalized jurisdiction key (state + country) and timezone to downstream services and caches results for performance. It integrates with SmileCue’s orchestration layer so every SMS, email, and voice attempt is tagged with the jurisdiction before rule evaluation. It must handle edge cases (telemedicine across borders, relocated patients, PO Boxes, daylight saving changes) and expose confidence levels to allow conservative defaults (suppress or downgrade to informational). Expected outcome: every send path reliably knows “where the law applies” without staff input.

Acceptance Criteria
Precedence-Based Jurisdiction Resolution and Normalized Output
Rule: The engine resolves jurisdiction using precedence: verified physical address (non-PO Box) > phone number metadata (country code and NANP area code) > stored timezone > practice default. Rule: The engine outputs jurisdiction_key in the format COUNTRY-PRIMARY_SUBDIVISION (e.g., "US-CA"); if subdivision unavailable, output COUNTRY only (e.g., "CA"). Rule: The engine outputs timezone as a valid IANA tz identifier (e.g., "America/Los_Angeles"). Rule: Given identical inputs, the engine returns identical outputs (deterministic) across runs. Rule: If all signals are missing, the engine returns practice default jurisdiction_key and timezone with confidence="low" and reason_codes including "no_signals".
Conflict Resolution with Confidence Levels
Given two or more signals disagree on jurisdiction, When resolution occurs, Then the engine selects the highest-precedence signal and emits confidence levels: high when the top two signals agree; medium when only the top signal is usable; low when falling back to practice default or stored timezone only. Rule: The engine includes reason_codes enumerating which signals were used, which were discarded, and why (e.g., "phone_country_mismatch", "tz_only", "address_unverified_po_box"). Rule: The engine emits conflict_summary=true when any lower-precedence signal disagrees with the chosen jurisdiction. Rule: Confidence and reason_codes are included in the response and the orchestration tag for downstream use.
DST-Safe Timezone Resolution
Given a send scheduled at 2025-03-09T09:55:00Z for a patient in "America/Los_Angeles", When resolution occurs, Then local time is 01:55 and quiet-hour evaluation uses PST; given 2025-03-09T10:05:00Z, then local time is 03:05 and PDT applies. Given a send scheduled at 2025-10-26T00:30:00Z for a patient in "Europe/Berlin", When resolution occurs, Then local time and offset reflect CET/CEST accurately across the fall-back hour with no duplicate or skipped hour errors. Rule: The timezone database is versioned and updated at least monthly; tzdb_version is included in diagnostics.
Caching and Invalidation for Jurisdiction Resolution
Rule: Resolutions are cached by patient_id plus signal fingerprints (address_hash, phone_hash, tz_value) with a TTL of up to 24h. Rule: Cache entries are invalidated within 5 seconds of any change to address, phone, or stored timezone. Rule: After invalidation, subsequent resolutions use updated signals and emit cache_status="miss_fresh". Rule: In steady state with unchanged profiles, P95 resolution latency is <= 50 ms and cache_hit_rate >= 80% under production-like load.
Pre-Rule Orchestration Tagging Across Channels
Given an SMS, email, or voice attempt enters orchestration, When the engine resolves jurisdiction, Then the attempt is tagged with jurisdiction_key, timezone, confidence, and reason_codes before any TCPA/quiet-hour rule evaluation. Rule: If the engine cannot produce a jurisdiction_key and timezone, the attempt is not dispatched; orchestration marks it blocked with error_code="jurisdiction_unresolved". Rule: Tags persist on the attempt record and are available in audit logs and analytics. Rule: Tagging is idempotent; re-evaluating the same attempt with unchanged inputs does not create duplicate tags.
Cross-Border Telemedicine and Mixed Signals
Given appointment_type="telehealth" and the patient’s verified address country differs from the practice country, When resolving jurisdiction, Then the engine prefers the patient’s verified address per precedence and outputs that jurisdiction_key and timezone. Given phone metadata indicates a different country than the verified address, When resolving, Then the verified address still governs and confidence is high unless the address is unverified, in which case confidence is medium and conflict_summary=true. Rule: Quiet-hour checks for telehealth use the patient’s timezone from the resolution output.
Auditability and Traceability
Rule: Every resolution produces an immutable audit record containing: patient_id (hashed), timestamp, input signals and hashes, chosen jurisdiction_key, timezone, confidence, reason_codes, cache_status, and tzdb_version. Rule: Audit records are queryable by time range and patient_id hash and retained for at least 24 months. Rule: A sampling endpoint returns resolution distributions by jurisdiction and confidence to support compliance monitoring.
Rule Library & Versioning
"As a compliance officer, I want a maintained, versioned library of TCPA and regional rules applied automatically so that the practice stays compliant as laws change."
Description

Maintain a centralized, versioned library of TCPA and regional regulations covering quiet hours, consent classes (informational/transactional vs marketing), channel constraints (SMS/email/voice), frequency caps, and required disclosures by jurisdiction. Rules are modeled as declarative policies with effective dates and precedence, enabling hotfix updates without code changes. The service provides a deterministic evaluator that resolves the active rule set given a jurisdiction, channel, purpose, and timestamp. It logs the rule version hash used per decision for traceability and supports staged rollouts (preview/test) before enforcement. Expected outcome: current, authoritative rules applied consistently across all sends with auditable provenance.

Acceptance Criteria
Deterministic Rule Evaluation for Send Decision
Given a jurisdiction code, channel in {SMS, Email, Voice}, purpose in {Informational, Marketing}, and a UTC timestamp When the evaluator is invoked with these inputs Then it returns exactly one decision containing: outcome in {ALLOW, DEFER, BLOCK}, defer_until (nullable), required_disclosures[], consent_class, frequency_cap_remaining, policy_set_id, policy_version_hash, evaluation_id And repeated invocations with identical inputs return the same outcome and policy_version_hash And the evaluator responds within p95 <= 150 ms at 200 RPS sustained load
Quiet Hours Enforcement in Patient Local Time
Given a patient location resolvable to a time zone and jurisdictional quiet hours window When the evaluator processes a UTC timestamp Then it converts to the patient’s local time and if within quiet hours sets outcome=DEFER and defer_until to the next permissible local time boundary And daylight saving transitions are honored so no message is sent during defined local quiet hours And defer_until is computed to the minute with no early sends across all supported channels
Consent Class and Channel Constraints Enforcement
Given purpose=Marketing and channel=SMS with no valid SMS marketing opt-in per jurisdiction When the evaluator runs Then it returns outcome=BLOCK and includes reason "consent_missing" and no required_disclosures Given purpose=Informational and channel=SMS where transactional messaging is permitted When the evaluator runs Then it returns outcome=ALLOW and includes required_disclosures per jurisdiction And per-channel, per-purpose frequency caps are enforced; when the cap is exceeded within the defined rolling window the outcome=BLOCK with reason "frequency_cap_exceeded"
Jurisdiction Precedence and Fallback
Given policies exist at Global, Country, State/Province, and Local levels with defined precedence Local > State > Country > Global When multiple policies are applicable for the same inputs and timestamp Then the evaluator selects the highest-precedence policy whose effective date range includes the timestamp And if no applicable policy exists at any level, the evaluator fails safe with outcome=BLOCK and reason "no_applicable_rule" And if the highest-precedence policy is not yet effective, the next lower-precedence active policy is used
Rule Library Versioning and Hotfix Activation
Given an authorized admin uploads a new policy version (policy_set_id, version_hash, effective_from, precedence) via API When the version is activated Then new decisions use this version within 10 minutes without service restart or code deployment And prior versions remain retrievable via API by version_hash And policy versions are immutable; attempts to modify an existing version are rejected with a validation error
Staged Rollouts with Preview/Test Mode
Given a candidate policy version is set to preview When the evaluator runs Then it computes both current and candidate outcomes and records a diff linked to evaluation_id without changing the enforced outcome And preview telemetry (match rate, allow/block/defer deltas, top rule differences) is queryable via API for a time range And promoting the candidate switches enforcement to that version; rollback to the prior version is possible via a single API call
Decision Logging and Auditability
Given any evaluation completes When the decision is logged Then the record includes evaluation_id, policy_set_id, policy_version_hash, jurisdiction, channel, purpose, input timestamp, outcome, reasons, defer_until, required_disclosures, consent_snapshot_id And decision logs are retained for 7 years and are immutable And an audit API can retrieve a decision by evaluation_id or message_id with p95 latency <= 2 seconds And a verification endpoint returns a SHA-256 digest of the policy document matching the policy_version_hash
Consent Matrix & Double Opt-In
"As a patient intake coordinator, I want the system to track and enforce consent by channel and purpose, including double opt-in where required, so that only permitted messages are sent."
Description

Model, capture, and enforce consent by channel (SMS, email, voice) and purpose (informational vs marketing) at the patient level, including jurisdiction-specific requirements for double opt-in and opt-out keywords. Ingest consent from intake forms, inbound messages (e.g., STOP/UNSUBSCRIBE), and EHR/PM integrations; timestamp and store consent provenance. Provide automatic downgrading of messages to informational when marketing consent is absent and suppression when no lawful basis exists. Sync consent state to the send pipeline in real time and reconcile discrepancies with external systems. Expected outcome: only permitted communications are delivered, with clear evidence of consent or lawful basis per message.

Acceptance Criteria
SMS Double Opt-In Enforcement by Jurisdiction
Given a patient’s location resolves to a jurisdiction requiring double opt-in for SMS marketing And the patient has not previously confirmed SMS marketing opt-in When the practice attempts to enroll the patient in any SMS marketing campaign Then the system sends a single confirmation-request SMS using the jurisdiction-approved template outside restricted quiet hours And blocks all SMS marketing sends until a valid confirmation keyword is received And upon receiving a valid confirmation keyword within 30 days, the system marks SMS marketing consent as Granted with timestamp and source And upon receiving an opt-out keyword or receiving no confirmation within 30 days, the system marks SMS marketing consent as Denied and suppresses marketing SMS And all actions are logged with the jurisdiction rule version applied
Opt-Out Keywords Suppress Further Sends
Given any inbound message on SMS, email, or voice that matches the jurisdiction-specific opt-out keywords for that channel and purpose When the message is received Then the system updates the patient’s consent state to Revoked for the matching channel and purpose with timestamp and source=Inbound And suppresses all further messages for that channel and purpose within 60 seconds across all campaigns and automations And sends a one-time opt-out confirmation where permitted by jurisdiction; otherwise no confirmation is sent And logs the event and the suppression reason in the audit trail
Intake Form Consent Capture with Timestamped Provenance
Given a patient completes a SmileCue intake form selecting consent checkboxes per channel (SMS, email, voice) and purpose (informational, marketing) When the form is submitted Then the system records a separate consent event per selected channel and purpose with timestamp, IP, user agent, form ID and version, and location determination method And associates the events to the patient record and marks corresponding consent states as Granted And triggers any required double opt-in workflows per jurisdiction for channels/purposes that require confirmation And rejects submissions with ambiguous or partially completed consent fields, prompting the patient to review
EHR/PM Consent Import and Conflict Reconciliation
Given an EHR/PM integration provides consent indicators with timestamps per channel and purpose When imported consent conflicts with SmileCue’s current consent state Then the system reconciles by applying the event with the latest valid timestamp per channel and purpose; if timestamps are equal or missing, opt-out (revocation) takes precedence And records a reconciliation entry detailing source systems, timestamps compared, decision taken, and affected fields And emits a webhook and dashboard notification when a patient’s consent state changes due to reconciliation
Automatic Messaging Downgrade Without Marketing Consent
Given a marketing message is scheduled for a patient who lacks marketing consent but has informational consent for the same channel When the message is evaluated by the send pipeline Then the system automatically substitutes the configured informational template variant for that message and updates tracking to informational classification And if no informational variant exists, the system suppresses the send and records a suppression with reason=No Lawful Basis And no marketing content is delivered to the patient in either case
Real-Time Consent State Sync to Send Pipeline
Given any consent change event is persisted (e.g., opt-in, opt-out, downgrade, reconciliation) When the event is committed to the consent ledger Then the send pipeline reflects the new state within 5 seconds and re-evaluates all pending messages for the affected patient And cancels in-flight messages that are now prohibited and prevents any further prohibited sends And adds a pipeline action log entry linking the consent event to each canceled or allowed message
Per-Message Lawful Basis Evidence and Auditability
Given any message is delivered, downgraded, or suppressed When a user views the message detail in the communication log Then the system displays the evaluated lawful basis (e.g., explicit consent, treatment, implied) with channel, purpose, consent event ID, timestamp, source, and jurisdiction rule set/version applied at decision time And provides an exportable evidence bundle (PDF and CSV) containing the message content/metadata and the consent provenance records And ensures evidence records are immutable and include a cryptographic hash for tamper detection
Quiet Hours Enforcement & Rescheduling
"As an office manager, I want messages to be automatically paused and rescheduled outside quiet hours based on patient location so that we respect regulations and avoid complaints."
Description

Automatically enforce jurisdiction-specific quiet hours by evaluating the patient’s local time prior to send. If outside allowed hours, place the message into a deferred queue and reschedule to the earliest permissible window while preserving SmileCue’s branching logic and dependencies (e.g., confirmation windows). Support practice-defined stricter hours, emergency bypass for critical care notices, and volume smoothing at window openings to avoid carrier spam heuristics. Handle daylight saving transitions and leap day edge cases. Expected outcome: compliant timing of communications without manual calendar adjustments, reducing complaints and legal risk.

Acceptance Criteria
Defer and Reschedule Outside Quiet Hours
Given a message to a patient whose local time falls within quiet hours for the channel and jurisdiction When a send is attempted Then the system must not send the message And it must place the message into a deferred queue with reason "Quiet Hours" And it must reschedule the message to the earliest permissible time within the same calendar day if any sendable window remains, otherwise the next calendar day at the window opening And the planned send timestamp is updated in message metadata And no retries are attempted during quiet hours
Jurisdiction and Channel Quiet Hours Selection by Patient Location
Given a patient has a resolvable location and timezone and a message channel C When determining the permitted send window Then the system applies quiet hours defined for the patient's country and state/province for channel C And if country and state rules differ, the stricter (longer quiet-hours span) is applied And permitted window calculations use the patient's local timezone derived from their location
Practice-Defined Stricter Hours Override
Given a practice has configured quiet hours that are stricter than jurisdiction defaults for a channel When sending or rescheduling messages for that practice Then the system enforces the stricter practice-defined hours And if practice settings are looser than jurisdiction rules, jurisdiction rules prevail
Emergency Bypass for Critical Care Notices
Given a message is tagged Emergency and of consent class Informational And the patient's local time is within quiet hours When the message is queued Then the system bypasses quiet hours and sends immediately And the bypass event is recorded with reason "Emergency" And if the message is of consent class Marketing, bypass is not allowed and the message is deferred per quiet hours
Preserve Branching Logic and Time-Dependent Windows
Given a message belongs to a workflow branch with a deadline constraint (e.g., must be sent at least X hours before appointment) When a send is deferred due to quiet hours Then the rescheduled time must still satisfy the branch's temporal constraints and dependencies And if no permissible reschedule exists before the branch's expiry, the message is canceled with status "Expired" and the defined alternate branch is triggered And downstream nodes dependent on this message update their schedules accordingly
Volume Smoothing at Quiet-Hour Window Opening
Given N deferred messages for a practice and channel share the same window opening at time T0 When T0 is reached Then the system applies uniform random jitter of 0–600 seconds to the rescheduled messages And it enforces default per-practice per-channel throughput caps of SMS ≤ 30/minute, Email ≤ 120/minute, Voice ≤ 10/minute (configurable) And no patient's messages are sent less than 60 seconds apart on the same channel And the backlog of size ≤ cap*10 is fully dispatched within 10 minutes of T0
Daylight Saving and Leap Day Scheduling Integrity
Given a patient's timezone enters Daylight Saving Time (spring forward) and 02:00–02:59 local time does not exist When a message reschedules into the nonexistent hour Then it is moved to the earliest permissible minute at or after 03:00 local time, respecting quiet hours Given a patient's timezone exits Daylight Saving Time (fall back) and 01:00–01:59 repeats When a message is rescheduled into the repeated hour Then it is sent only once at the scheduled wall-clock time without duplication Given February 29 exists in the current year When a message is deferred across Feb 28–Mar 1 due to quiet hours Then rescheduling uses the correct calendar date, and messages targeted for Feb 29 are delivered on Feb 29 at the earliest permissible time
Compliance Pre-Check Guardrails
"As a hygienist, I want the system to pre-check each message and block or adjust content and format when it violates rules so that I don’t accidentally send non-compliant communications."
Description

Introduce a pre-send compliance validator that evaluates channel, content type, consent state, frequency caps, and jurisdictional rules before dispatch. The validator blocks sends that violate policy, downgrades marketing content to informational when allowed, injects mandated disclosures/opt-out language, and enforces channel-specific constraints (e.g., voice to mobile restrictions, SMS length and opt-out footer). Provide clear, actionable error/warning messages to staff and APIs, and expose override paths only where legally permitted (with justification capture). Expected outcome: prevention of non-compliant sends and consistent, explainable guardrails within existing workflows.

Acceptance Criteria
Block Sends Outside Jurisdiction Rules and Quiet Hours
Given a patient’s jurisdiction is resolved and local time falls within quiet hours And the message content is classified as marketing without the required consent level for that jurisdiction and channel When the system validates a pending send (SMS, email, or voice) Then the validator blocks the send And returns error code COM-001 with a human-readable message indicating the violated rule(s) And includes ruleRef(s) and jurisdictionId in the response payload And no message is queued or sent And an audit log entry is created capturing userId/apiKey, decision=blocked, ruleRef(s), timestamp, and requestId
Automatic Downgrade of Marketing to Informational When Allowed
Given a message is tagged as marketing And the jurisdiction rule set permits downgrading marketing to informational for this use case and channel And the recipient has valid informational consent When the system validates the send Then the validator changes classification from marketing to informational And injects all required informational disclosures/footers And allows the send to proceed And returns warning code COM-201 indicating downgrade occurred with ruleRef And records an audit entry with action=downgrade, originalClass, newClass, ruleRef, and timestamp
Mandated Disclosures and SMS Length Handling
Given channel=SMS and content is compliant for the jurisdiction And the jurisdiction requires an opt-out footer (e.g., "Reply STOP to opt out") When the validator appends mandated disclosures Then if total length fits within up to 3 concatenated segments for the detected encoding, the message is allowed with the footer appended And a warning COM-202 is returned indicating final segment count Then if total length would exceed 3 segments, the validator blocks the send And returns error COM-002 with guidance to shorten content or switch channel And no partial messages are sent
Voice Channel Mobile-Only Enforcement
Given channel=voice And the applicable jurisdiction restricts this content class to mobile numbers only And the target number is classified as non-mobile (e.g., landline/unknown) When the validator evaluates the send Then the validator blocks the send And returns error COM-003 with message "Voice to non-mobile prohibited in this jurisdiction for this content class" And suggests compliant alternatives (e.g., SMS or email) when available And logs the decision with ruleRef and numberType
Frequency Caps by Channel and Content Class
Given a recipient has received N messages via SMS for appointment-related content within the last 7 days And the jurisdiction/org-configured cap for this channel and content class is N per 7 days When another non-urgent message is validated Then the validator blocks the send or schedules it at the next eligible time if auto-reschedule is enabled And returns code COM-004 with nextEligibleSendAt and capDetails And no message is dispatched before the cap window resets And an audit entry records the cap violation with counts and window
Structured UI/API Validation Response
Given a send request is evaluated via UI or API (single or bulk) When validation completes Then the response contains overallDecision in {allow, allow_with_warnings, block} And includes arrays of codes, messages, and ruleRefs per recipient And contains overrideAllowed boolean and requiredJustificationFields when true And for bulk requests, each recipient has an independent decision object and no compliant recipient is blocked by others And the 95th percentile validation latency for single-recipient requests is ≤300ms under nominal load
Legally Permitted Overrides with Justification and Audit
Given a validation result is block and overrideAllowed=true per the applicable rule And the user holds the Compliance Override role/permission When the user submits an override with a justification reason and a free-text explanation of at least 20 characters Then the validator allows the send And records an immutable audit entry with userId, timestamp, ruleRef, decision=overridden_allow, justificationReason, justificationText, and sourceIp And the audit record is retrievable via API within 5 seconds When overrideAllowed=false, the UI/API does not present an override option and any attempt returns HTTP 403 with code COM-403
Immutable Compliance Audit Trail
"As a practice owner, I want detailed, exportable logs showing why a message was or was not sent, what rules applied, and what consent was on record so that I can respond to audits and disputes."
Description

Create an immutable, privacy-aware audit trail for all compliance decisions and message attempts. Each record stores the patient pseudonymous identifier, timestamp, jurisdiction and timezone used, consent snapshot and provenance, rule version hash, decision outcome (sent/suppressed/downgraded/deferred), disclosures applied, and quiet-hours reschedule data. Support tamper-evident storage, configurable retention aligned with HIPAA, PHI minimization/redaction, and export APIs for audits and legal inquiries. Provide filters and reports by jurisdiction, channel, and outcome. Expected outcome: defensible evidence for audits and disputes without exposing unnecessary PHI.

Acceptance Criteria
Record Completeness per Decision Event
Given a message attempt is evaluated for delivery When the system finalizes a compliance decision (sent | suppressed | downgraded | deferred) Then an audit record is persisted before any dispatch containing: pseudonymous_patient_id; utc_timestamp (ISO 8601, ms precision); jurisdiction (country/state code) and iana_timezone used; channel; consent_snapshot {class, status, scope, captured_at}; consent_provenance {source_system, method, record_id}; rule_version_hash (SHA-256 hex); decision_outcome; disclosures_applied {ids, content_hash}; quiet_hours {original_at, rescheduled_at, reason} when applicable; and a unique immutable record_id (UUIDv4) And the write succeeds with p95 latency <= 100 ms And if the write fails, the decision is not executed and the attempt is retried until persisted or marked failed with an error code
Tamper-Evident Append-Only Log
Given the audit store is configured When any actor attempts to update or delete an existing record prior to retention expiry Then the operation is rejected and recorded in a security audit log And each record includes record_hash = SHA-256(canonical_payload + previous_record_hash) enabling a hash chain And a verify-integrity operation over any range detects modification and identifies the first invalid link And a daily chain_anchor_hash is sealed to write-once storage, and verification can start from the nearest anchor
PHI Minimization and Pseudonymization
Given audit records are persisted Then no raw PHI fields are stored (full name, DOB, full phone/email, message body, free text) And patient references use pseudonymous_patient_id; channel addresses are masked (e.g., phone last4, email local-part hashed) when stored And disclosures_applied stores IDs and content_hash, not full text And export APIs default to redacted output (include_phi=false) and require audit.read.phi scope to request minimally expanded fields
Configurable Retention and Legal Hold
Given a retention policy is set to N years When records exceed N years Then they are purged within 24 hours, leaving a cryptographic tombstone preserving chain integrity and purge metadata {purged_at, reason} And when a legal hold is applied to a patient, jurisdiction, or date range Then matching records are excluded from purge and marked with legal_hold_id and applied_at And retention changes apply prospectively and are auditable
Export API with Filters and Pagination
Given an authorized user with scope audit.read requests an export with filters {date_from, date_to, jurisdiction, channel, outcome} When the request is valid Then the API returns 200 with results filtered accordingly in the requested format (JSON or CSV), sorted by utc_timestamp ascending, with pagination (page_size up to 10000) and a next_cursor when more data exists And requests over 1000000 records are processed asynchronously, returning a job_id and completion webhook or polling endpoint within 2 seconds And the API enforces rate limits (e.g., 60 req/min per tenant) and returns 429 with Retry-After when exceeded And all export requests and deliveries are themselves logged in the audit trail with requester_id and purpose
Aggregated Reports by Jurisdiction, Channel, Outcome
Given a reporting request with filters {date_range, jurisdictions[], channels[], outcomes[]} When the report is generated Then the system returns counts grouped by jurisdiction, channel, and outcome with totals, and an optional daily breakdown in a specified timezone And reported counts reconcile exactly with the raw audit records for the same filters And report generation completes within 10 seconds for up to 30 days of data
Quiet Hours Reschedule Traceability
Given a send falls within a jurisdiction's quiet hours When the system defers the message Then the audit record captures quiet_hours {window_start, window_end, rule_timezone, reason="quiet_hours"} plus original_scheduled_at and rescheduled_for And upon actual dispatch, a subsequent record links back via prior_decision_id and records decision_outcome="sent" with the same rule_version_hash and jurisdiction snapshot And if consent changes before rescheduled_for, the new decision outcome and consent_snapshot are recorded with linkage to the original deferral

Evidence Vault

Generates immutable, audit-ready evidence packs for each consent event, including timestamp, channel, language, template version, user/source, and IP/caller ID where applicable. One-click export with role-based access lets compliance leads respond to audits or carrier inquiries in minutes instead of days.

Requirements

Tamper-Evident Consent Ledger
"As a compliance lead, I want each consent event recorded in a tamper‑evident ledger so that I can prove integrity and non‑repudiation during audits."
Description

Implement an append-only, cryptographically verifiable ledger to record every consent event with required metadata (timestamp, channel, language, template version, user/source, IP/caller ID). Entries are chained via hashes with periodic anchors (e.g., daily Merkle root) and stored on immutable, retention-enforced storage (e.g., WORM/S3 Object Lock). Each event receives a globally unique Consent Event ID. Data is encrypted at rest and in transit, with managed keys and rotation. Provide a verification service to validate event integrity against the anchored hashes. Integrate with SmileCue’s consent capture flows across SMS, email, and voice so ledger writes are synchronous and resilient with idempotency. Support retention policies aligned with HIPAA and business rules, high availability, and backfill/migration for legacy consent events. Outcome: defensible, non-repudiable records ready for audit.

Acceptance Criteria
Required Metadata and Consent Event ID
Given a consent is captured via SMS, email, or voice When the ledger write is attempted Then the record must include: ConsentEventID (globally unique, time-sortable), serverTimestamp (UTC ISO 8601), channel ∈ {sms,email,voice}, language (BCP 47), templateVersion (semver), userOrSource, tenantId, and networkIdentifier appropriate to channel (IP for web/email, callerId for voice when available) And the write is rejected with a 4xx and no append occurs if any required field is missing or malformed And upon successful write the read API returns the exact persisted metadata for that ConsentEventID And across 1,000,000 generated events there are zero duplicate ConsentEventIDs
Append-Only Immutability Enforcement
Given an existing ledger record When a client attempts to update or delete it via any API or admin tool Then the operation is blocked (HTTP 405/409) and no stored bytes are altered And a correction can only be recorded by appending a new compensating record that references the original ConsentEventID And audit logs capture the blocked mutation attempt with actor, timestamp, and reason
Synchronous Write and Idempotency Across Channels
Given a user provides consent in SmileCue via SMS link, email link, or IVR When the consent is submitted Then the application only marks the consent as captured after the ledger confirms a committed append And end-to-end additional latency introduced by the ledger commit is ≤ 300 ms at p95 under 200 requests/minute per tenant And if the client retries with the same Idempotency-Key within 24 hours Then the ledger returns the original ConsentEventID and does not create a duplicate entry And concurrent duplicate submissions (race within 1 second) yield a single persisted record And on transient failures the system retries with exponential backoff up to 3 times before surfacing an error, ensuring no partial writes
Hash Chain Integrity and Daily Merkle Anchoring
Given a sequence of events within a day When each event is written Then its hash includes the previous event hash and the record payload, producing a verifiable chain And by 00:10 UTC next day the system publishes and stores the daily Merkle root for all events from that UTC day Given a ConsentEventID When the verification service is called Then it returns Verified with the proof path and daily anchor hash if the record is intact And returns Tampered with mismatch details if any byte differs from the anchored hash And recomputing the Merkle root from raw events matches the stored anchor exactly
Immutable WORM Storage with Retention Enforcement
Given ledger data objects are written to storage with Object Lock (Compliance mode) When a user without Compliance role attempts to delete or shorten retention before the retentionUntil date Then the operation fails and no bytes are removed or altered And retention policies are configurable per tenant (default 6 years; cannot be reduced below minimum) And legal hold can be enabled/disabled only by Compliance role and is fully audited And storage metadata exposes retentionUntil and legalHold state for each object
Encryption and Managed Key Rotation
Given ledger data at rest Then it is encrypted with a managed KMS CMK (AES-256) and access is limited to approved service roles And KMS key rotation occurs at least annually without downtime and without loss of decryptability for historical records Given any client/service connects to the ledger or verification API When using TLS Then only TLS 1.2+ with modern ciphers is accepted and lower versions are rejected And key usage (encrypt/decrypt) and admin actions are logged and exportable for audit
Legacy Consent Backfill and Migration
Given legacy consent records exist outside the ledger When the backfill job runs Then each legacy record is mapped to required metadata, marked origin=legacy, assigned a ConsentEventID, appended to the ledger, and included in the day’s Merkle root And the job is idempotent: reruns produce no duplicate ledger entries (same idempotency key → same ConsentEventID) And throughput is ≥ 10,000 events/hour with ≥ 99.9% success rate, producing a completion report with counts and failures And a random 1% sample verified via the verification service returns Verified
One-Click Evidence Pack Export
"As a compliance lead, I want to export a complete evidence pack with one click so that I can respond to auditor requests within minutes."
Description

Generate an audit-ready evidence pack for any consent event with a single action. The pack includes a human-readable summary and a machine-readable JSON bundle containing: consent text snapshot (rendered message), language/locale, template version, timestamp, channel, user/source, IP/caller ID, hash-chain proofs, delivery receipts, patient responses/branching transcript, and policy/version references. Export formats: PDF (watermarked, paginated, sealed with timestamp) and JSON (schema-versioned). Include a QR/code link to a verification endpoint to validate integrity. Support batch export for multiple events, and allow inclusion/exclusion of PHI per role policy. Integrate with RBAC and audit logging; all exports are recorded with user, time, and reason codes. Outcome: rapid, consistent auditor-ready documentation.

Acceptance Criteria
Single Event One-Click Export Generates Complete Pack
Given a user with Export Evidence permission views a consent event When they click "Export Evidence Pack" Then two files are generated: a watermarked, paginated PDF sealed with a UTC timestamp and a schema-versioned JSON bundle And the pack includes: consent text snapshot (rendered message), language/locale, template version, event timestamp (ISO 8601, UTC), channel, initiating user/source, IP address and/or caller ID (where applicable), hash-chain proofs, delivery receipts, patient responses and branching transcript, and policy/version references And the PDF contains a scannable QR code and short code link to the verification endpoint And the JSON bundle includes a schemaVersion field and validates against the current published schema And the export completes within 3 seconds at p95 for a single event ≤ 2 MB
Role-Based PHI Inclusion/Exclusion Controls
Given RBAC policies define that Compliance Leads may include PHI and Front Desk users may not When a Compliance Lead exports an evidence pack Then the UI presents an "Include PHI" toggle (default Off) And enabling the toggle includes PHI fields; disabling redacts PHI fields (e.g., name, DOB, phone, email, MRN) with clear redaction markers in both PDF and JSON When a Front Desk user exports Then the "Include PHI" control is hidden or disabled and PHI is always excluded And the export metadata records whether PHI was included And automated tests verify no PHI tokens appear in outputs when PHI is excluded
Batch Export for Multiple Consent Events
Given a user selects 10–500 consent events across patients and channels When they choose "Export Evidence Pack (Batch)" Then the system generates a ZIP containing per-event files {eventId}.pdf and {eventId}.json and a manifest.json And the manifest lists eventId, file checksums (SHA-256), schemaVersion, PHI inclusion flag, start/end timestamps, and success/error status per event And per-event failures do not abort the batch; failures are captured with error codes and messages in the manifest And the batch completes within 2 minutes at p95 for 500 events with average pack size ≤ 2 MB And all processed events (success and failure) are written to the audit log with the selected reason code
Export Audit Logging with Reason Codes
Given export reason codes are configured (Audit, Carrier Inquiry, Legal, Other + free text) When any export (single or batch) is initiated Then the user must select a reason code (and provide notes if Other) And an immutable audit log entry is created containing: exportId, userId, role, timestamp (UTC), source IP, reason code and notes, eventIds, PHI inclusion flag, item counts, and outcome (success/failure) And admins can retrieve the audit record by exportId via UI and API And attempts without a reason code are blocked with a validation error and no files are generated
Verification Endpoint and Tamper Detection via QR/Link
Given a verifier scans the PDF QR code or opens the printed short link When the verification endpoint is requested with the pack’s token Then the service returns integrity status (Valid/Invalid), eventId, pack timestamp, and a hash that matches the embedded hash-chain proofs And if the PDF or JSON has been altered, the status is Invalid with a specific reason code (e.g., HASH_MISMATCH) And the verification response never returns PHI And the endpoint meets p95 latency < 500 ms and monthly availability ≥ 99.9%
Multichannel Multilingual Fidelity in Evidence Pack
Given consent events were sent via SMS, Email, and Voice/IVR in English and Spanish When an evidence pack is exported Then the PDF renders the consent text snapshot exactly as sent (including line breaks, emojis, and directionality), and shows channel, template version, and language/locale (BCP 47) And the JSON includes channel, templateVersion, language/locale, and delivery artifacts And SMS entries include carrier delivery receipts when available; Email includes provider delivery status; Voice includes caller ID and call SID; missing receipts are marked Not Available with provider reason And special characters are preserved in both PDF and JSON without substitution
Unauthorized Export Attempts Are Prevented
Given a user without Export Evidence permission attempts to export (UI or API) When they submit an export request (single or batch) Then the request is denied with HTTP 403 and a user-facing message indicating insufficient permissions And no PDF/JSON files are generated and no download links are created And the denial is recorded in the audit log with userId, time, IP, and denial reason
Role-Based Access & Least-Privilege Controls
"As a practice owner, I want role-based controls on evidence access so that only authorized users can view or export sensitive records."
Description

Introduce RBAC tailored to the Evidence Vault with predefined roles (e.g., Compliance Admin, Staff Viewer, External Auditor—Read Only) and granular permissions for view, export, share, and redact. Enforce MFA and support organization SSO/SAML/SCIM for user lifecycle. Scope access by location/provider and patient to minimize PHI exposure. Provide admin UI and APIs to assign roles, define approval workflows for external sharing, and apply policy-based redactions by role. Integrate with existing SmileCue org/tenant model and propagate permissions to export and share flows. Outcome: controlled, auditable access aligned with HIPAA minimum necessary standard.

Acceptance Criteria
Compliance Admin Assigns Roles via Admin UI
- Given an org tenant with predefined roles, when a Compliance Admin assigns the "Staff Viewer" role to user U with scope Location=A and Provider=X in the Admin UI, then U can access Evidence Vault with view-only permissions limited to that scope within 60 seconds. - Given role assignment or removal occurs, when the change is saved, then an immutable audit log entry is recorded with orgId, actorId, targetUserId, roles added/removed, scopes, timestamp (UTC), and source IP. - Given a user has no explicit permission for an action, when they attempt view/export/share/redact, then the system enforces least-privilege (deny by default), returns 403, and logs the attempt. - Given a Compliance Admin removes all roles from U, when U attempts to access Evidence Vault, then access is blocked and any active session is revoked within 1 minute.
Scoped Access by Location/Provider/Patient
- Given user U has Staff Viewer role scoped to Location=A only, when U lists or searches Evidence Vault items, then only evidence for Location=A is returned and counts exclude out-of-scope items. - Given U attempts to open an out-of-scope evidence record via direct URL or API ID, when the record belongs to Location≠A or a different provider/patient scope, then the response is 404 Not Found and an access-denied audit event is recorded. - Given U is additionally scoped to a patient list [P1, P2], when U queries Evidence Vault, then only evidence for P1 and P2 at Location=A is visible; all others are hidden.
External Auditor Read-Only with Time-Bound Access
- Given a Compliance Admin creates an External Auditor invitation with scope (locations/providers/date range) and expiry T, when the auditor accepts the invite and completes authentication, then the auditor can view only in-scope evidence and cannot export, share, or redact (UI controls hidden; API returns 403 for those endpoints). - Given the invitation expires at T, when the auditor attempts access after T, then access is revoked (401/expired) and the event is logged. - Given the Compliance Admin revokes the invitation prior to T, when the auditor attempts to use the link, then access is immediately invalid (410 Gone) and an audit entry is recorded.
MFA Enforcement and Sensitive-Action Step-Up
- Given any user attempts to access Evidence Vault and is not enrolled in MFA, when they sign in, then the system requires MFA enrollment (TOTP primary; SMS fallback if enabled by org policy) before granting access. - Given a user with permission initiates export, redact, or external share, when the user has not completed MFA within the last 5 minutes, then a step-up MFA challenge is required and failure denies the action. - Given org policy disables SMS fallback, when a user attempts to enroll via SMS, then the option is unavailable and only approved methods are offered.
SSO/SAML Authentication and SCIM Lifecycle
- Given SAML SSO is configured, when a user authenticates via the IdP, then SmileCue establishes a session mapped to the correct org/tenant and applies Just-In-Time role/scoping mappings from SAML attributes if configured; otherwise the user has no roles (no access). - Given SCIM creates/updates user U with roles and scopes, when the SCIM call succeeds (2xx), then the changes take effect within 5 minutes and are reflected in the Admin UI and permission checks. - Given SCIM deprovisions user U, when the deprovision call succeeds, then new logins are blocked immediately and existing sessions lose Evidence Vault access within 5 minutes; attempts are logged as deprovisioned.
Policy-Based Redaction by Role Across UI, API, and Exports
- Given a role lacks permission view_full_phi, when viewing evidence details, then PHI fields (e.g., phone numbers masked to last 4, IP/caller ID hidden or tokenized) are redacted per policy version V. - Given an export (CSV/PDF/JSON) is generated by a user without view_full_phi, when the file is produced, then the same redactions are applied and the export includes a redaction manifest noting fields redacted and policy version V. - Given a share link is created for a recipient role lacking view_full_phi, when the recipient accesses the data, then redactions are enforced server-side and are non-reversible because underlying values are omitted from payloads. - Given policies are updated to V+1, when a user requests data thereafter, then redactions reflect V+1 and the audit log records policy version applied.
Permission Propagation to Export/Share with Approval Workflow
- Given a user with share permission initiates an external share for a defined scope, when org policy requires 1 Compliance Admin approval, then the request enters Pending and no link is issued until approval is granted. - Given an approver approves the request, when approval is recorded, then a time-bound, scope-limited link is generated with enforced redaction based on recipient role, watermarking (org, requester, timestamp), and all events are audited. - Given the request is rejected or expires before approval, when the requester checks status, then the request is closed with no link ever created and the outcome is logged. - Given an approved link is revoked by an admin, when a recipient attempts to access it, then the link is invalid within 1 minute and returns 410 Gone; revocation is logged.
Comprehensive Access and Export Audit Logging
"As a security officer, I want detailed access logs for the Evidence Vault so that I can demonstrate compliance and detect misuse."
Description

Capture immutable logs for all Evidence Vault interactions, including searches, views, exports, shares, downloads, and revocations with actor identity, timestamp, IP/device, reason code, and target resource. Store logs in append-only storage with retention and tamper-evidence. Provide filtering, reporting, and export to CSV/JSON. Emit webhook/SIEM integrations for real-time monitoring and anomaly detection (e.g., unusual export volume). Include auditor-ready reports summarizing access over a time window per patient, user, or practice. Outcome: complete traceability to demonstrate compliance and detect misuse.

Acceptance Criteria
Immutable Logging of Evidence Vault Interactions
Given an authenticated actor performs search, view, export, share, download, and revocation on Evidence Vault resources When each action completes (success or failure) Then one audit event per action is persisted containing: event_id (UUIDv4), action_type, actor_user_id, actor_role, actor_practice_id, timestamp (UTC ISO-8601 with ms), ip_address or caller_id, user_agent/device_id (if available), reason_code (required for view/export/share/download/revoke), target_resource_type, target_resource_id, patient_id, consent_id, channel, template_version, request_id, outcome, and error_code (if any) And the event is queryable within 5 seconds of action completion (p95) And API-initiated actions include client_id and service principal identity in actor context And voice events include caller_id; SMS/Email include originating_ip when available And revocation events reference the prior share/export event_id
Append-Only Tamper-Evident Storage and Retention
Given the audit log datastore is operational When events are written Then events are append-only with no update/delete capability via UI/API And any attempt to modify/delete is blocked and produces a blocked_tamper_attempt audit event with actor identity and reason "immutable" And each event includes hash and prev_hash forming a verifiable chain; daily verification scans 100% of events and reports mismatches=0 And retention is configurable per practice (default 7 years, minimum 6); post-retention purge uses append-only tombstones preserving chain verifiability And storage maintains at least 3 replicas across 2 fault domains; recovery time objective <= 1 hour for audit data
Reason Code Enforcement for Sensitive Actions
Given a user initiates view, export, share, download, or revoke of an evidence pack When the request is submitted via UI or API Then reason_code is mandatory and must match an admin-managed allowlist; optional free-text note <= 500 chars may be provided And requests missing/invalid reason_code are rejected (HTTP 400/UI validation) and no target action occurs And both reason_code and note are persisted in the corresponding audit event And the UI clearly displays the captured reason on subsequent audit event views
Audit Log Filtering and Search Performance
Given a compliance user opens the Audit Log UI When filters are applied by time range, action_type, actor_user_id, actor_role, practice_id, patient_id, target_resource_id, channel, outcome, and reason_code Then the result set contains only matching events and displays total_count and unique_actor_count And sorting by timestamp (asc/desc) and by actor_user_id is supported; results are stable across pages (cursor-based pagination) And for up to 1,000,000 matching events, first page latency <= 3s p95 and subsequent pages <= 2s p95 And the UI renders a volume-over-time sparkline for the selected window
Audit Log Export to CSV and JSON
Given a permitted user selects Export for the current filtered audit log When CSV is chosen Then the file includes header row and one row per event with exactly the visible columns plus mandatory event_id,timestamp,action_type; values match on-screen data When JSON is chosen Then the file is a newline-delimited JSON stream of full event objects And the export metadata includes export_time_utc, filter_summary, total_rows, and SHA-256 checksum; checksum is displayed and stored And exports up to 5,000,000 events begin streaming within 10s and complete without server timeouts; partial exports are resumable via download tokens And the export action is itself audited with download_url (time-limited) and requestor identity
Real-Time Webhook/SIEM Streaming and Anomaly Detection
Given at least one webhook/SIEM destination is configured and active When an audit event is created Then a notification is delivered within 10 seconds p95, signed with HMAC-SHA256, including idempotency key; non-2xx responses are retried with exponential backoff for 24h And payload conforms to published JSON schema; optional syslog RFC5424 formatting is available for SIEM And anomaly detection evaluates per-actor and per-practice hourly export counts; if current hour > 3x 30-day moving average or > 200 exports, an anomaly_export_volume alert is generated, delivered to configured channels, and audited And alerts support acknowledge/resolve; all alert lifecycle changes are audited
Auditor-Ready Access Summary Reports
Given an auditor requests a summary for a defined window and scope (patient, user, or practice) When a compliance user generates the report Then the report includes totals, breakdown by action_type, unique actors, top 10 actors, timeline histogram, and an appendix listing event_ids with links And the report is produced within 60 seconds for up to 100,000 events and is available as PDF and CSV; report_id, generation_time_utc, filters, and integrity hash/signature are embedded And access to generate/download reports is restricted to Compliance Lead and Practice Admin; unauthorized attempts are blocked and audited
Secure Time-Bound Share Links for Auditors/Carriers
"As a compliance lead, I want to share an evidence pack securely with a carrier or auditor so that they can review it without creating an account or accessing other data."
Description

Enable generation of signed, revocable share links to specific evidence packs for external reviewers. Configurable expiration, single/multi-use tokens, optional IP allowlists, and maximum download/view limits. Support identity challenge (email OTP or delegated SSO) and watermarking with recipient info and timestamp. Provide a read-only web viewer with redaction modes to suppress non-essential PHI while preserving evidentiary value. All accesses are logged; links can be paused or revoked at any time. Integrate with email delivery for invitations and with RBAC for approval workflows. Outcome: fast, secure external review without provisioning full accounts.

Acceptance Criteria
Signed, Configurable Share Link Creation for a Single Evidence Pack
Given an internal user with ShareLink.Create permission and a target evidence pack ID When they configure expiration T, usage mode (single- or multi-use), view_limit V, and download_limit D, and click Generate Then the system creates a signed URL scoped only to that evidence pack with the configured constraints persisted And the link metadata includes issuer user ID, role, creation timestamp (UTC), expiration timestamp, token ID, and cryptographic signature And accessing any other evidence ID with the link returns 403 with reason "scope_mismatch" And when the view or download counts reach their limits, subsequent attempts return 403 with reason "limit_exceeded" And when the current time exceeds expiration, attempts return 410 with reason "expired" And the link appears in the pack’s Share Links list with status Active and accurate counters
Identity Challenge via Email OTP or Delegated SSO
Given a generated link requiring identity challenge via email OTP When the recipient enters the designated email and requests a code Then a 6-digit OTP is sent to that address and the OTP expires in 10 minutes And after 5 consecutive incorrect OTP attempts, the link is locked for 15 minutes and an audit event is recorded Given a link configured for delegated SSO (SAML/OIDC) to org X When the recipient authenticates successfully with org X Then access is granted and the asserted identifier (email/nameID) is bound to the session And all successful identity challenges record recipient identifier, method (OTP/SSO), timestamp, and IP in the audit log
Optional IP Allowlists and Network Enforcement
Given a link with an IP allowlist of one or more IPv4/IPv6 CIDR ranges When a request originates from an IP not in the allowlist Then access is denied with 403 and reason "ip_blocked" and a non-disclosing error page is shown And all denied and allowed attempts log source IP, matched rule decision, token ID, and outcome Given no allowlist is configured When the link is accessed from any IP Then evaluation passes and other controls apply
Read-Only Web Viewer with Redaction Modes
Given an external reviewer with valid access When they open the viewer Then the evidence pack renders in read-only mode with edit/delete actions disabled And a Redaction toggle presents at least two modes: Minimal PHI and Maximum PHI Suppression And switching modes updates the view within 1 second and shows a persistent banner of the active mode And redaction masks non-essential PHI while preserving consent text, timestamps, channel, template version, and identifiers needed for audit And copied text and printed/exported views reflect the currently active redaction mode
Watermarking of Views and Exports
Given reviewer identity is established for the session When the pack is viewed or exported Then a visible watermark shows recipient identifier (email/SSO ID), current timestamp (UTC), token ID, and "SmileCue Evidence Vault" on all pages And the watermark appears on-screen and in downloaded PDFs/images with consistent placement and 10–20% opacity And export actions are disabled until identity is bound; anonymous export is not permitted And the watermark persists after rasterizing the downloaded document to 300 DPI and re-inspecting
Pause/Revocation and Real-Time Access Control
Given an active link When an internal user pauses it Then new access attempts are denied with 403 reason "paused" within 60 seconds and existing sessions terminate on next request within 60 seconds When the link is revoked Then the token becomes unusable immediately, counters stop incrementing, and status shows Revoked And all pause/revoke events are recorded with actor, timestamp, reason, and previous state as append-only audit entries
Email Invitation Delivery and RBAC Approval Workflow
Given RBAC requires approval for external sharing When a creator submits a share link request Then an approver receives a workflow task and the link remains inaccessible until approved And only users with ShareLink.Approve can approve; approval captures approver ID, timestamp, and comments When approved Then an email invitation is sent to the recipient including the secure link, expiration date/time, and identity challenge instructions, with no PHI beyond patient initials and appointment date And delivery events (sent, bounced, opened) are recorded and visible in share link activity And if delivery fails permanently, the link remains inactive and the creator is notified
Template Snapshot & Localization Capture
"As a compliance analyst, I want the evidence to include the exact content the patient saw or heard so that I can prove the consent language matched our approved templates and the patient’s language."
Description

Capture and store the exact consent content presented at the time of consent, including language/locale, template version ID, merge-field resolutions, conditional branching taken, and rendering channel. For voice consents, store audio snippets or transcripts with timestamps; for SMS/email, store the original payload and a normalized, human-readable snapshot. Link snapshots to template change history and include them in evidence packs. Validate presence of snapshots at write time and flag any missing artifacts. Ensure proper encoding and storage to accurately reproduce content during audits. Outcome: verifiable proof that the patient saw or heard the approved consent language in the correct language.

Acceptance Criteria
SMS Consent Snapshot Capture
Given an approved consent template version exists in locale L and is sent via SMS with merge fields resolved for patient P When patient P responds with a valid affirmative keyword to grant consent Then the system stores the exact outbound SMS payload as sent and a normalized, human-readable snapshot with all merge fields resolved And the snapshot metadata includes: templateVersionId, locale, channel='SMS', consentEventId, patientId, sentTimestampUTC, receivedTimestampUTC, senderE164, recipientE164, providerMessageId And the snapshot is immutable and retrievable by consentEventId And retrieving the snapshot reproduces the exact text shown to the patient without re-evaluating the live template
Email Consent Snapshot Capture
Given an approved consent template version exists in locale L and is sent via Email with merge fields resolved for patient P When the consent email is delivered and patient P provides consent through the defined mechanism (e.g., reply or click capture is recorded) Then the system stores the original email payload (subject, from/to, body parts) and a normalized, human-readable snapshot with all merge fields resolved And the snapshot metadata includes: templateVersionId, locale, channel='Email', consentEventId, patientId, sentTimestampUTC, messageId And embedded links and placeholders in the snapshot reflect the exact resolved values at send time And the snapshot is immutable and retrievable by consentEventId
Voice Consent Audio/Transcript Capture
Given a voice consent flow using template version V is presented in language/locale L via phone call When the patient gives verbal consent during the call Then the system stores at least one of: (a) audio snippet(s) covering the consent language and the patient’s confirmation, or (b) a transcript with per-utterance timestamps And the snapshot metadata includes: templateVersionId, locale, channel='Voice', consentEventId, patientId, callStartTimestampUTC, callEndTimestampUTC, callerId, calleeId And if audio is stored, each snippet has start/end offsets; if a transcript is stored, each utterance has a timestamp And the snapshot is immutable and retrievable by consentEventId
Conditional Branch Path Recording
Given the consent template contains conditional branches that vary content based on patient/context data When the patient proceeds through the consent flow Then the system records the exact branch path taken, including branch identifiers and evaluation outcomes that led to each decision And the normalized snapshot contains only the content actually presented along that path And the recorded branch path is linked to the snapshot and visible in evidence retrieval
Template Version Linking to Change History
Given a consent snapshot is created for template version V When a user views the snapshot details Then the snapshot references templateVersionId=V and is linked to the template change history at version V And subsequent edits to the template create new versions without altering the existing snapshot And retrieving change history from the snapshot shows the diff/metadata applicable at version V
Audit Reproduction & Evidence Pack Inclusion
Given a compliance lead exports an evidence pack for a specific consent event When the pack is generated Then it includes the exact snapshot(s) tied to that event (SMS/email normalized snapshot and payload; voice audio/transcript), along with required metadata (locale, channel, templateVersionId, timestamps) And the textual snapshots are stored and rendered in a consistent encoding that preserves the original characters and directionality for the locale And opening the evidence pack reproduces the content exactly as presented/heard without contacting live template services
Write-Time Validation & Missing Artifact Flagging
Given the system attempts to persist a consent event When required snapshot artifacts for the channel are missing (e.g., no SMS/email payload + normalized snapshot, or neither audio nor transcript for voice) Then the write is rejected with a specific error code indicating missing artifacts And a compliance alert is logged with consentEventId and deficiency details And no consent record is marked as confirmed until required artifacts are present

Consent Pulse

Real-time dashboards and alerts that track opt-ins/opt-outs, consent decay, and carrier feedback. Automatically launches re-permission campaigns when consent nears expiration and suggests the best channel and language to recover opt-ins, keeping outreach compliant and lists healthy.

Requirements

Unified Consent Event Stream
"As an office manager, I want all consent activity consolidated per patient and channel so that outreach rules apply correctly and we have a single source of truth for compliance."
Description

Implement a real-time ingestion and normalization pipeline that consolidates consent events (opt-in, opt-out, revocation, double opt-in, consent purpose changes) from SMS, email, voice, web forms, and connected practice systems into a single patient profile. Maintain channel- and purpose-specific consent states with timestamps, provenance (source system, campaign, IP/device where applicable), and geolocation/time zone context for compliant outreach. Provide idempotent processing, de-duplication, and reconciliation logic to ensure a canonical consent record. Secure data with encryption in transit/at rest and role-based access controls aligned to HIPAA. Expose the unified consent state to SmileCue messaging, scheduling, segmentation, and reporting services via internal APIs and webhooks to enable downstream automation and accurate compliance checks.

Acceptance Criteria
Ingest and Normalize Consent Events From All Channels
Given valid consent events from SMS, email, voice, web forms, and connected practice systems with heterogeneous schemas When the pipeline ingests these events Then each event is normalized to the canonical schema with fields: patient_id, channel, consent_action (opt_in|opt_out|revoke|double_opt_in|purpose_change), consent_purpose, event_timestamp (UTC), provenance.source_system, provenance.campaign_id (nullable), provenance.ip (nullable), provenance.device_fingerprint (nullable), geo.country, geo.region, time_zone, validation_status=valid And normalized events are persisted to an append-only event store with acknowledgment from ≥2 replicas Given an event missing required fields or failing signature/CRC validation When processed Then it is rejected to a dead-letter queue with error_code and error_reason, and no state mutation occurs Given sustained load of 1000 events/minute When processed Then p95 end-to-end normalization latency ≤ 5 seconds and processing error rate ≤ 0.5% (excluding DLQ-intended rejects)
Maintain Channel- and Purpose-Specific Consent State
Given an existing patient consent state When a new consent_action for a specific channel and purpose is received Then the state is updated atomically with last_updated (UTC) and previous_state captured in audit metadata Given multiple events for the same patient/channel/purpose arrive out of order within 10 minutes When processed Then events are ordered by event_timestamp and applied deterministically using precedence: revoke > opt_out > opt_in > double_opt_in > purpose_change And only one final state mutation occurs Given a consent purpose_change event When applied Then the new purpose mapping is reflected in state and the prior purpose is retained in audit history Given consents subject to expiry policy When stored Then expiry_at is calculated and persisted And when current_time > expiry_at Then state transitions to expired and outreach checks return non-permissible
Idempotent Processing and De-duplication
Given duplicate deliveries of the same event (same idempotency_key or event_id+source_system) When processed multiple times Then only the first delivery mutates state and subsequent deliveries are recorded as duplicates without changing state Given retries due to transient failures When events are replayed Then processing remains idempotent and produces a single canonical state change in the audit trail Given a batch replay of historical events When processed Then de-duplication prevents double application while preserving chronological ordering Given system metrics When observed over 24 hours Then duplicate_detected_count and duplicate_block_rate are emitted and visible on the monitoring dashboard
Provenance and Audit Trail Completeness
Given any consent state change When persisted Then an immutable audit event is recorded with: event_id, patient_id, channel, consent_action, consent_purpose, event_timestamp (UTC), received_at, source_system, campaign_id (nullable), ip/device_fingerprint (nullable), sms_short_code or voice_call_sid (nullable), operator_user_id (nullable), geo, time_zone, and hash_chain Given an authorized compliance user queries audit for a patient over a date range ≤ 1000 events When executed Then results return within 3 seconds and include verification to detect tampering via hash_chain continuity Given any attempt to modify or delete an audit event When attempted Then the operation is blocked and a security event is logged with actor, action, timestamp, and reason
Security and HIPAA-Aligned Access Controls
Given PHI stored at rest When persisted Then AES-256 encryption is used with KMS-managed keys rotated at least every 90 days Given service-to-service communication When transmitting data Then TLS 1.2+ with mutual TLS is enforced and legacy ciphers are disabled Given a user with role Receptionist requests audit details When authorized Then access is denied (HTTP 403) and the attempt is logged; Given a user with role Compliance_Officer requests audit details When authorized Then access is granted and the access is logged with user, purpose, timestamp, and patient_id Given application and pipeline logs When generated Then PHI fields are redacted or tokenized and log access is restricted by role Given 5 failed access attempts within 10 minutes for an account When detected Then the account is temporarily locked and a security alert is issued
Expose Unified Consent via Internal APIs and Webhooks
Given an internal service requests consent state via GET /consents?patient_id=...&channel=...&purpose=... When the request includes a valid service token Then the API returns the canonical state with timestamps, provenance summary, and expiry_at with p95 latency ≤ 200 ms Given a consent state change is committed When webhooks are enabled for subscribers Then a signed (HMAC-SHA256) webhook is delivered within 3 seconds and retried with exponential backoff for up to 24 hours on failure Given duplicate webhook deliveries When received by subscribers Then each payload includes an idempotency_key to enable safe deduplication downstream Given an API request without valid authentication When processed Then the API returns 401 and no consent data is leaked
Reconciliation Across Channels and Providers
Given nightly reconciliation with carrier/ESP/voice provider suppression lists and connected practice systems When executed Then discrepancies in opt-in/opt-out/revocation states are identified, a reconciliation report is stored, and canonical state is corrected within 24 hours per policy Given conflicting states among systems When policy is applied Then precedence is: explicit patient opt-out in any channel > revocation > explicit opt-in with double opt-in > explicit opt-in > implicit/inferred, and the chosen resolution is recorded in audit Given reconciliation changes are made When completed Then downstream provider suppression lists are updated via APIs with confirmation; transient failures trigger retries with exponential backoff up to 48 hours Given reconciliation job failures When they occur Then on-call alerts are emitted with job_id, scope, error_summary, and next recommended action
Consent Decay Scoring & Thresholds
"As a compliance officer, I want visibility into when consent will become stale so that we can re-permission proactively and avoid non-compliant outreach."
Description

Create a rules-driven engine that calculates consent freshness for each patient by channel and purpose using regulatory guidance (e.g., TCPA/CTIA inactivity windows), carrier best practices, and configurable business policies. Compute decay scores and predicted expiration dates based on last interaction, engagement frequency, campaign type, and carrier feedback. Allow administrators to configure thresholds that trigger warnings and re-permission workflows, with support for practice- and location-level overrides. Handle special cases for transactional vs. marketing messages, quiet-hour constraints, and upcoming-appointment exemptions. Surface decay state to dashboards, alerts, and segmentation filters to proactively preserve list health.

Acceptance Criteria
Decay Score Computation by Channel & Purpose
Given a patient has consent records for SMS, Email, and Voice with purposes (marketing, transactional) And regulatory inactivity windows and business policy weights are configured When the decay engine runs for the patient Then a decay_score in [0,100] is produced per channel-purpose And the score incorporates last_interaction_at, engagement_frequency (configurable window), campaign_type, and latest carrier_feedback And identical inputs and configuration produce identical scores (idempotent) And missing non-critical inputs use configured defaults without failing processing
Predicted Expiration Date Calculation
Given a channel-purpose consent with a recorded last_interaction_at And an applicable inactivity window derived from regulatory/carrier rules and policy adjustments When the engine computes predicted_expiration_at Then predicted_expiration_at = last_interaction_at + applicable_window adjusted by configured engagement and carrier feedback modifiers And predicted_expiration_at is recalculated within 5 minutes of a new qualifying interaction And timestamps are stored and returned in ISO 8601 with patient timezone applied or clearly indicated
Admin Thresholds with Practice/Location Overrides
Given global thresholds (e.g., Healthy, Warning, At-Risk, Expired) are defined per channel-purpose And practice-level and location-level overrides may be configured When resolving thresholds for a patient at a specific location Then precedence is location override > practice override > global And any threshold change is versioned with actor, timestamp, scope (global/practice/location), and change details And crossing a threshold emits a single event per channel-purpose and updates consent_decay_state accordingly
Auto-Launch Re-Permission Workflows
Given a patient’s decay_score crosses a configured threshold or predicted_expiration_at is within a configurable X days window When evaluated by the engine Then a re-permission workflow is created once per patient per channel-purpose within a configurable suppression window And the recommended outreach channel and language are selected based on historical engagement, stated preferences, and carrier feedback constraints And no workflow is created if the patient is opted out for that channel, on a do-not-contact list, or has an active appointment-based exemption And each workflow launch is logged with correlation ID, triggering threshold, channel-purpose, and selected template
Transactional vs Marketing Handling & Appointment Exemptions
Given transactional and marketing consents are tracked separately When marketing consent decays or expires Then transactional messaging remains permitted where legally allowed and configured And if the patient has an upcoming appointment within a configurable N-day window and is not opted-out Then re-permission prompts are deferred until after the appointment window while transactional reminders continue And decay scoring proceeds but does not block transactional messages during the exemption
Quiet Hours & Timezone Compliance
Given quiet hours are configured per practice/location and carrier guidelines apply And the patient’s timezone is known or inferred When scheduling re-permission outreach Then messages are sent only within permitted hours in the patient’s local timezone And if outside permitted hours, outreach is queued for the next permitted window And time-critical transactional messages are exempt from quiet hours only if explicitly configured
Dashboards, Alerts, and Segmentation Surfacing
Given decay_score, predicted_expiration_at, and consent_decay_state are computed When users view dashboards Then aggregated counts by state and by channel-purpose are displayed with data freshness p95 ≤ 5 minutes And drilling into a segment reveals patient-level details including current values and last_updated_at And alerts are sent to configured channels when thresholds are crossed, containing counts, affected channel-purpose, and links to segments And segmentation supports filters by state, expires_within (days), channel-purpose, practice/location, and carrier feedback flags And the public API returns decay_score, predicted_expiration_at, consent_decay_state, and threshold metadata per channel-purpose
Auto Re-permission Campaign Orchestration
"As an office manager, I want re-permission to run automatically before consent expires so that our contact lists stay usable without manual outreach."
Description

Enable event-driven re-permission journeys that launch automatically as consent approaches configured decay thresholds. Provide pre-approved, compliant templates per channel with dynamic inclusion of required disclosures and opt-out instructions. Select the best channel, send time, and tone based on historical engagement, language preference, and carrier feedback, with safeguards for quiet hours, frequency caps, and PHI scrubbing. Support double opt-in where required, capture and reconcile new consent with full provenance, and gracefully handle STOP/HELP keywords. Include throttling, cohort-level A/B testing, and fallbacks across SMS, email, and voice. Write successful re-permissions back to the unified consent record and notify downstream systems via webhooks.

Acceptance Criteria
Event-Driven Launch at Consent Decay Thresholds
Given a patient consent record with a decay threshold configured (e.g., 30 days before expiration) And the patient is eligible based on jurisdictional rules and current consent status When the system detects the record crossing the threshold via real-time event or scheduled sweep Then a re-permission journey is automatically created within 60 seconds And the patient is enrolled into a cohort according to segmentation rules (e.g., channel eligibility, language, risk tier) And campaign throughput is throttled according to global and cohort rate limits (configurable) And no journey is launched for patients currently opted-out or with active legal holds
Compliant Templates with Dynamic Disclosures and Opt-Out
Given pre-approved templates exist for SMS, email, and voice in English and Spanish And regulatory disclosures and opt-out instructions are defined per channel and jurisdiction When a re-permission message is generated for an eligible patient Then the message uses a pre-approved template matching the patient’s preferred language And dynamically inserts required disclosures and opt-out instructions for the patient’s jurisdiction and carrier guidelines And includes practice identity and contact information And the rendered content passes compliance validation with zero errors prior to send
Adaptive Channel, Send Time, and Tone Selection with Safeguards
Given historical engagement data, carrier feedback, and language preferences are available And quiet hours and frequency caps are configured at global and practice levels When the system selects channel, send time, and tone for a patient’s journey step Then it chooses the highest-probability channel based on past engagement and carrier deliverability And schedules within the patient’s local timezone avoiding quiet hours And enforces frequency caps across all channels (e.g., per-day and per-week) And if the selected channel is disallowed by carrier feedback, the next best eligible channel is chosen
Double Opt-In Orchestration Where Required
Given a jurisdiction or carrier requires double opt-in for SMS And the patient is targeted via SMS in that jurisdiction When the first consent request is delivered Then the system waits for an affirmative keyword (e.g., YES) within the configured timeout window And upon receiving the keyword, sends a confirmation message containing disclosures and opt-out instructions And records both steps with timestamps, message IDs, and content hashes And if no affirmative response is received before timeout, the journey proceeds to configured fallback steps without marking consent as renewed
PHI Scrubbing and Content Safety
Given PHI scrubbing rules are configured (e.g., no diagnosis codes, no treatment details in outbound re-permission content) When any outbound content (SMS, email, voice transcript) is rendered Then the content is scanned and redacted according to rules prior to send And any message failing scrubbing is blocked, logged with reason, and retried with a safe template variant And audit logs capture pre/post-scrub checksums without storing raw PHI
Consent Capture, Reconciliation, and Keyword Handling
Given a patient responds with consent-related keywords (YES/STOP/HELP) or clicks consent links When the system receives the response via SMS, email, or voice IVR input Then the unified consent record is updated in real time with the new consent state, channel scope, timestamp, source message ID, and provenance (IP, user agent if web, carrier metadata if SMS) And STOP immediately updates opt-out across all applicable channels and halts active journeys And HELP returns a compliant assistance message without altering consent And conflicting signals within a 24-hour window are resolved per precedence rules with a full audit trail
Fallbacks, A/B Testing, Write-Back, and Webhooks
Given cohort-level A/B test variants are defined for templates, channel order, or send times And fallback rules across SMS→email→voice are configured When a journey executes for a patient Then the assigned variant is persisted and respected across all steps And on failure or non-response within SLA, the next fallback channel is attempted according to rules and caps And upon successful re-permission, the unified consent record is written with final state and provenance within 5 seconds And a webhook is delivered to registered downstream systems with a signed payload including consent state, scope, timestamps, and journey metadata; retries occur with exponential backoff until acknowledged
Carrier Feedback Ingestion & Block Alerts
"As a marketing coordinator, I want to know when carriers are filtering our messages and how to fix it so that re-permission and reminders reliably reach patients."
Description

Integrate carrier and aggregator delivery receipts, error codes, and 10DLC campaign status to classify filtering events, suspected spam blocks, and registration issues. Map error codes to actionable categories and recommended remediation steps (e.g., content changes, pacing adjustments, registration updates). Correlate feedback with consent decay, template content, and send patterns to identify root causes. Generate real-time alerts when thresholds are exceeded (per campaign, clinic, or channel) and surface a remediation checklist. Persist carrier insights in the consent record to inform channel selection and re-permission strategies.

Acceptance Criteria
Real-Time Carrier Feedback Ingestion and Normalization
Given a valid signed webhook from a carrier or aggregator containing a delivery receipt with provider_event_id, message_id, timestamp, and error code When the webhook is received Then the signature and IP allowlist are validated, the payload is normalized to the internal schema, and the event is stored within 60 seconds in 99% of cases Given duplicate webhook deliveries for the same provider_event_id When processed Then ingestion is idempotent and results in a single stored event with a deduplicated count incremented Given an invalid signature or malformed payload When received Then the event is rejected with HTTP 401 or 400 respectively, no data is persisted, and an error metric with reason code is recorded Given a delivery receipt referencing an unknown message_id When processed Then the event is placed in a reconciliation queue and is linked to the message record within 15 minutes if it arrives; otherwise it is marked Unreconciled with reason after 60 minutes Given multi-tenant traffic When events are stored Then data is partitioned by tenant (clinic) and channel, and no cross-tenant access is possible in queries or UI
Error Code Mapping to Actionable Categories and Remediation
Given a set of known carrier and aggregator error codes (e.g., 30007, 30006, 605) and 10DLC campaign statuses (e.g., Pending, Approved, Suspended, Rejected) When events are processed Then each is mapped to a normalized category from the taxonomy: Filtering suspected spam, Consent required/opt-out, Registration/10DLC issue, Number blocked/blacklisted, Throughput/rate limited, Destination unreachable, Content violation, Unknown Given an error code not present in the mapping When processed Then it is labeled Unknown, escalated to a review queue, and appears in the Mapping Coverage report; overall mapping coverage over the last 30 days is >= 95% Given a normalized category for an event When stored Then a remediation playbook is attached including 3–7 actionable steps specific to the provider and category Given a 10DLC campaign status webhook of Suspended or Rejected When ingested Then the campaign entity reflects the new status within 5 minutes and subsequent messages for that campaign are flagged Registration/10DLC issue with send blocked until status resolves
Correlation of Filtering with Consent Decay, Templates, and Send Patterns
Given delivery feedback from the last 14 days When the hourly correlation job runs Then per campaign and per clinic filtering rates are computed and correlated with consent age, template ID, send hour, and send velocity (messages per minute) Given any driver with a correlation score >= 0.30 and p-value < 0.05 When results are generated Then the top 3 drivers are surfaced with effect size, confidence, and example evidence (template IDs, time windows) Given a template with filtering rate >= 1.5x its campaign baseline and N>=200 sends When analyzed Then a root-cause card attributes elevated filtering to that template with relative risk and recommended actions Given a cohort with consents older than 12 months showing filtering rate >= 2x fresh consents When analyzed Then the system flags consent freshness as a likely driver and links to re-permission campaign setup
Threshold-Based Real-Time Alerts per Campaign, Clinic, and Channel
Given a configurable alert policy with default threshold filtering_rate > 5% and minimum volume N >= 200 in a 60-minute sliding window When any campaign, clinic, or channel breaches the threshold Then an incident is created within 2 minutes containing entity, window metrics, top suspected categories, top templates, and recent consent trends Given additional threshold breaches for the same entity within a suppression window of 30 minutes When detected Then duplicate alerts are suppressed and appended as updates to the open incident with updated metrics Given alert delivery channels configured (in-app, email, Slack) When an incident is created Then notifications are sent to all channels with retry up to 3 times on failure and final failure logged Given a user acknowledges an incident When acknowledged Then incident status changes to Acknowledged and subsequent notifications follow the suppression policy until Resolved Given the filtering rate falls below 80% of the threshold for two consecutive windows When evaluated Then the incident auto-resolves with reason Restored below threshold
Remediation Checklist Surfaced in Alerts and Dashboard
Given an incident categorized as Filtering suspected spam When the incident is opened Then a remediation checklist is displayed with actionable items: edit content (remove high-risk keywords, add brand intro), adjust pacing (reduce TPS), verify registration/10DLC, rotate sender if applicable, and trigger re-permission; each item has a one-click action or deep link Given a user executes an action from the checklist (e.g., reduce TPS, pause campaign, edit template) When completed Then the checklist updates with completion status, and an audit log is written with user, timestamp, action, and previous/new values Given role-based access control When an action requires elevated permission (e.g., pausing a campaign) Then only authorized roles can complete it; unauthorized attempts are blocked and logged Given remediation steps are applied When 24 hours elapse Then the system displays before/after KPIs for filtering rate, delivery rate, and confirmation rate on the incident timeline
Persist Carrier Insights on Consent Record and Inform Channel Selection
Given a patient consent record When new carrier feedback is received for that patient and channel Then the record is updated with last_blocked_at, last_category, provider, and a channel health score computed from the last 30 days of events Given an outbound message decision with multiple eligible channels When selecting a channel Then the selector avoids any channel with a Filtering suspected spam event within the last 72 hours unless an authorized user overrides with reason; if all channels are impaired, a re-permission attempt is queued instead Given consent expiration within 14 days and recent SMS filtering When launching a re-permission campaign Then the system recommends and defaults to the best alternate channel (email or voice) and language based on past recovery success for that patient cohort, and logs the rationale on the consent record Given channel health improves (filtering rate < 2% for 3 consecutive days with N >= 100 per day) When evaluated nightly Then the channel health score is upgraded and the channel becomes eligible again for selection
Consent Health Dashboard & Drilldowns
"As a practice owner, I want a clear view of our consent health and risks so that I can make informed decisions and keep outreach compliant."
Description

Deliver real-time dashboards that visualize opt-in rates, opt-out trends, consent decay pipeline, re-permission performance, and carrier filtering rates, sliceable by location, provider, channel, campaign, and time. Provide benchmarks, goal tracking, and anomaly detection with in-app and email/SMS alerts for threshold breaches. Enable drilldown to patient-level audit views showing the full consent timeline, message samples, and provenance. Support export (CSV) and API access for reporting, and embed key widgets on the SmileCue home page for quick status checks.

Acceptance Criteria
Real-Time Consent Health Dashboard Rendering
- Given the user opens the Consent Health Dashboard, When the page loads, Then KPI tiles for Opt-in Rate, Opt-out Trend, Consent Decay Pipeline, Re-permission Performance, and Carrier Filtering Rate are visible with labels and units. - Given a cold start, When the dashboard loads on a standard broadband connection, Then time-to-first-interaction is ≤2.5s at p95 and ≤4.0s at p99. - Given a new source event (opt-in, opt-out, carrier feedback, re-permission response), When it is ingested, Then the impacted metrics refresh within 60 seconds and show a “Last updated” timestamp to the minute. - Given today’s source-of-truth logs, When comparing sampled aggregates (n≥100 per metric), Then dashboard values deviate by ≤0.5% from source totals. - Given an upstream data outage, When the dashboard cannot fetch data, Then a non-blocking error banner displays with retry and status link, and cached metrics from ≤15 minutes ago are shown labeled as “stale.”
Slicing by Location, Provider, Channel, Campaign, and Time
- Given the dashboard is open, When the user expands the filter panel, Then multi-select controls for Location, Provider, Channel (SMS/Email/Voice), Campaign, and Time (Last 7/30/90 days, MTD, QTD, YTD, Custom Range) are available. - Given any combination of filters (≤50 selected values total), When Apply is clicked, Then all widgets refresh consistently to the same scope within 500ms after data return and the active filters appear as chips. - Given filtered state, When the user copies the URL or bookmarks the page, Then the full filter state is encoded in the URL and restored on revisit. - Given role-based access, When a user lacks access to a location or provider, Then those options are hidden and cannot be applied via URL. - Given a filter set that yields no results, When the dashboard refreshes, Then widgets display “No data in selected range” without errors and offer Clear Filters.
Benchmarks and Goal Tracking
- Given a metric tile, When the user toggles Benchmarks, Then the practice value, peer percentile band, and industry median display with tooltips citing the benchmark cohort and effective date. - Given edit permissions, When the user sets a goal target per metric (by global or per Location/Provider/Channel) and saves, Then the goal persists, is versioned with timestamp and editor, and renders progress (color-coded) on tiles and trends. - Given goals exist, When actuals cross warning (amber) or target (green) thresholds, Then tile colors update within 60 seconds of the underlying metric refresh. - Given read-only permissions, When viewing goals, Then inputs are disabled and an explanatory tooltip appears. - Given an audit review, When goals history is opened, Then prior values, editors, timestamps, and scope are listed chronologically.
Anomaly Detection and Threshold Alerts
- Given anomaly detection is enabled, When a metric deviates beyond configured rules (e.g., >2σ or >50% day-over-day for ≥3 hours), Then an anomaly badge appears on the metric and an incident is created. - Given alert channels are configured, When a threshold breach or anomaly is detected, Then an in-app notification, email, and optional SMS are sent with metric, scope, time window, baseline, and link to drilldown. - Given quiet hours are set, When a breach occurs during quiet hours, Then alerts are queued and summarized at quiet-hours end unless marked as critical. - Given repeated breaches of the same metric and scope, When multiple detections occur within 24 hours, Then alerts are deduplicated to one thread with updates appended. - Given a received alert, When the user clicks the link, Then they land on the pre-filtered dashboard/drilldown reflecting the alert context.
Drilldown to Patient-Level Consent Audit
- Given a metric widget, When the user clicks View Details, Then a drilldown table lists underlying patient events scoped to the selected filters with sortable columns and pagination. - Given a patient row is selected, When opening the audit view, Then the full consent timeline displays (timestamps, channel, campaign, consent text/version, event type, and status changes) with message samples and carrier feedback, including provenance (source system, user/API key, and IP/device for web submissions). - Given HIPAA access controls, When the user lacks permission for PHI, Then patient identifiers are masked in lists and details are inaccessible; access attempts are logged. - Given an audit view, When the user navigates back, Then breadcrumbs return them to the originating widget and filter context. - Given data retention policies, When viewing events older than retention limits, Then redacted placeholders appear with retained metadata (date, type) and a retention tooltip.
CSV Export and Reporting API
- Given the dashboard or drilldown is scoped, When the user clicks Export CSV, Then a UTF-8 CSV with headers reflecting the applied filters is generated server-side and downloaded or made available via a link for files >25MB. - Given large exports (>100k rows), When requested, Then export is chunked/streamed and a completion notification is sent; the file is available for ≥7 days with signed URL. - Given the Reporting API, When an authenticated client (OAuth2) requests the metrics endpoint with pagination and filters, Then the response includes totals, dimensions, and timestamps matching the data dictionary and dashboard values (±0.5%). - Given rate limits (e.g., 600 requests/min per tenant), When the limit is exceeded, Then 429 with retry-after is returned and logged. - Given an export or API access, When completed, Then an audit log entry is recorded with user/client, scope, timestamp, and record count.
Homepage Key Widgets Embedding
- Given the SmileCue home page loads, When widgets are enabled, Then key metrics (Opt-in Rate, Opt-out Trend sparkline, Consents expiring next 30 days, Carrier Filtering Rate, Open Alerts count) render above the fold. - Given a widget click, When the user selects a widget, Then they are deep-linked to the full dashboard with the corresponding filters applied. - Given configurable layout, When an admin reorders or toggles widgets, Then the layout persists per user and device (desktop/tablet/mobile) and reflows responsively. - Given data updates, When the home page is in focus, Then widgets refresh at least every 60 seconds and display a last-updated timestamp. - Given permission constraints, When a user lacks access to a metric’s scope, Then the widget is hidden or shows a masked state with a permission tooltip.
Compliance Guardrails & Audit Trail
"As a compliance officer, I want enforced guardrails and a provable audit trail so that we can demonstrate compliance and avoid penalties."
Description

Enforce HIPAA, TCPA, CTIA, and CAN-SPAM guardrails across Consent Pulse flows, including PHI redaction in re-permission outreach, required disclosures, opt-out keywords handling, quiet hours, and frequency caps. Maintain immutable, exportable audit logs of consent changes, message content hashes, delivery outcomes, and user/admin actions with timestamps and actor identity. Provide configurable retention policies, legal hold, and subject-access/deletion support. Block sends that violate rules and present actionable error messages with links to remediation. Generate audit-ready reports for regulators and carriers on demand.

Acceptance Criteria
Block Non-Compliant Sends in Real Time
Given a send is initiated for a recipient without active, channel-specific consent When the message is queued Then the system blocks the send, logs violated rule_id, and displays an error with remediation_url and API error code CP-401. Given message content lacks required channel disclosures When validation runs Then the send is blocked and the template editor highlights missing elements with a one-click Add Disclosure action. Given quiet hours or frequency caps would be violated When attempting to schedule Then the action is rejected and the UI suggests the next allowable send time in the recipient’s local timezone. Given carrier feedback flags a recipient as spam (e.g., 7726) within the last 30 days When any outreach is attempted Then the send is blocked and the recipient is marked Carrier-Blocked with reason_code and an appeal link. Given an opt-out keyword was received on the same channel within the last 24 hours When attempting to send Then the system blocks the send and references the opt-out timestamp in the error details.
PHI Redaction in Re-Permission Outreach
Given a re-permission campaign template contains PHI placeholders (e.g., appointment time, treatment) When a message is generated Then PHI tokens are replaced with generic placeholders and a PHI Redacted badge appears in preview. Given free-text content includes PHI per configured patterns or classifier confidence > 0.90 When saving the template Then the save is rejected with a list of flagged phrases and suggested safe rewrites. Given a user with override privilege attempts to bypass redaction When authorizing the send Then MFA is required and a policy_override event with justification is logged before the send can proceed. Given a voice re-permission script When generated Then the audio contains no PHI and uses only general language per policy.
Required Disclosures and Opt-Out Keyword Handling
Given SMS templates When previewed or sent Then "Reply STOP to opt out" and the practice name are appended; emails include physical address and unsubscribe link; voice calls include a spoken opt-out instruction. Given an inbound message matches STOP/END/CANCEL/UNSUBSCRIBE/QUIT (any case, with punctuation or emoji) When received Then channel consent is set to Opted-Out within 1 second, a confirmation is sent, and an audit entry is created. Given an inbound HELP keyword When received Then a CTIA-compliant help message with support contact is sent and logged. Given a previously opted-out recipient replies START/UNSTOP/YES to SMS or clicks a re-subscribe email link When processed Then consent changes to Opted-In with timestamp, source, and double opt-in if required by carrier.
Quiet Hours and Frequency Caps Enforcement
Given default quiet hours 8pm–8am recipient local time or practice-configured windows When scheduling or sending Then the system prevents delivery within the window unless marked Urgent under an approved policy with justification. Given per-recipient caps of max 3 SMS/week, 2 emails/week, 1 voice/week and max 1 message/day cross-channel When a send would exceed a cap Then the send is blocked and the UI shows remaining quota and next available slot. Given only a ZIP code is available to infer timezone When confidence < 0.70 Then stricter quiet hours (7pm–9am) are applied and the user is prompted to confirm or correct timezone. Given a DST transition occurs in the target timezone When scheduling sends That cross the transition Then delivery times are converted correctly and do not fall within quiet hours.
Immutable Audit Log of Consent and Messaging
Given any consent change, send attempt/outcome, content hash, templating variables, or user/admin action When it occurs Then an append-only audit entry with ISO-8601 UTC timestamp, actor_id, ip_address, rule_id, and SHA-256 content_hash is written within 2 seconds. Given an export request with filters (date range, patient, channel, action type, actor) When executed Then CSV and JSON exports for up to 1,000,000 records complete within 60 seconds; larger exports stream with progress. Given any attempt to alter or delete past audit entries When performed by any role Then the operation is denied and an integrity endpoint exposes a verifiable hash chain/Merkle root for immutability checks. Given carrier delivery receipts or spam feedback are received When processed Then they are linked to the original message audit entry with standardized reason codes and surfaced in the UI.
Retention Policies, Legal Hold, and DSAR Support
Given retention policies per data class (messages, audit logs, consent) When the policy job runs Then records older than the threshold are purged within 24 hours except those on legal hold, and a purge summary is logged. Given a legal hold is applied to a patient or matter When enabled Then all related records are exempt from purge until the hold is lifted, and hold status is visible in UI and audit logs. Given a Data Subject Access Request for a patient When initiated Then all relevant records are compiled and exported within 7 days with third-party identifiers redacted and an audit entry created. Given a deletion request compliant with policy When executed Then personal data is deleted except what is required for compliance, tokens are revoked, and a deletion receipt is logged.
Audit-Ready Reports for Regulators and Carriers
Given a regulator report request for a date range (HIPAA/TCPA/CTIA/CAN-SPAM) When generated Then PDF and CSV are produced within 5 minutes including consent changes, message volumes by channel, opt-outs, quiet-hour violations (0 allowed), frequency-cap blocks, and policy overrides. Given a carrier investigation requires message samples When requested Then the system provides content hashes, reconstructed redacted message bodies, disclosure evidence, and audit chain proofs linking events. Given an admin downloads a report When completed Then access is role-gated, the file is watermarked with requester identity, and the download is logged with timestamp and ip_address.
Multilingual & Accessible Consent Prompting
"As a hygienist, I want consent prompts to match a patient’s language and accessibility needs so that patients clearly understand and respond."
Description

Offer a library of consent and re-permission templates localized for common patient languages (e.g., English, Spanish) with automatic selection based on stored preference, device locale, or clinic defaults. Ensure templates meet readability targets and are optimized per channel (SMS character limits, email preheaders, voice scripts), with Unicode support and graceful fallbacks. Provide accessible web consent pages that meet WCAG guidelines, including screen-reader compatibility and clear opt-in/opt-out controls. Store language and accessibility context with consent records to personalize future outreach and improve opt-in recovery rates.

Acceptance Criteria
Auto Language Selection Based on Preference, Locale, and Clinic Default
Given a patient has a stored language preference, When a consent or re-permission message is generated, Then the template in that language is selected and rendered and language_used and selection_reason are recorded on the consent record. Given no stored language preference and a known device locale, When a message is generated, Then the template for the locale language (e.g., es-MX -> es) is selected and selection_reason = "device_locale" is recorded. Given neither stored preference nor device locale are available, When a message is generated, Then the clinic default language template is selected and selection_reason = "clinic_default" is recorded. Given the chosen language has no template for the selected channel, When a message is generated, Then the system falls back to English and selection_reason = "fallback_to_english_missing_template" is recorded.
Channel-Optimized Consent Templates (SMS, Email, Voice)
Given a default SMS consent template contains only GSM-7 characters, When rendered including required compliance text, Then the total length is <= 160 characters and is sent as 1 segment. Given an SMS render includes non–GSM-7 characters, When sending, Then UCS-2 encoding is used and the total length does not exceed 2 segments; encoding_used = "UCS-2" is recorded on the consent record. Given an email consent template, When rendered, Then the subject length is <= 60 characters, a preheader of 40–100 characters is present, all images have alt text, and the primary CTA is visible without scrolling on a 360x640 viewport. Given a voice consent script, When synthesized at 150 wpm, Then total duration is <= 30 seconds, includes an opt-out instruction (e.g., "Press 2 to opt out"), and DTMF capture for 1/2 is logged.
Unicode Handling and Graceful Fallbacks
Given a template includes characters outside GSM-7 (e.g., á, ñ, emoji), When sending via SMS, Then UCS-2 is used and no character is replaced with "?" or removed. Given UCS-2 encoding would produce more than 2 SMS segments, When rendering the message, Then the system switches to a pre-approved short localized template variant that preserves meaning and reduces length to <= 2 segments and records template_variant = "short". Given the channel cannot represent a character (e.g., voice TTS for emoji), When rendering, Then the system substitutes a localized textual equivalent and preserves sentence grammar. Given common email clients (Gmail, Outlook, Apple Mail), When the email is rendered, Then Unicode text displays correctly using fallback fonts without mojibake in each client.
Readability Targets for Localized Templates
Given an English consent or re-permission template is created or updated, When analyzed by the CI readability check, Then the Flesch–Kincaid Grade Level is <= 8.0 and failing templates are blocked from publishing. Given a Spanish template is created or updated, When analyzed by the readability check, Then the INFLESZ score is >= 55 (Normal or easier) and failing templates are blocked from publishing. Given any template for SMS, When reviewed, Then the message contains <= 3 sentences, avoids terms from the banned_terms list, and uses active-voice phrasing per the style linter rules. Given any template for email, When reviewed, Then the body contains <= 6 sentences above the fold, avoids banned_terms, and passes the style linter rules for clarity.
WCAG 2.1 AA Accessible Web Consent Page
Given the web consent page, When scanned with axe-core against WCAG 2.1 A/AA, Then there are 0 violations. Given keyboard-only navigation, When tabbing through the page, Then all interactive elements (including opt-in and opt-out controls) are reachable in logical order with a visible focus indicator. Given a screen reader (NVDA on Windows and VoiceOver on iOS), When the page loads, Then landmarks, labels, and instructions are announced correctly and the opt-in and opt-out controls expose proper accessible names and states. Given the page is zoomed to 200% and viewed at a 320px width, When interacting, Then content reflows without horizontal scrolling and all functionality remains available. Given the color scheme, When measured, Then text and interactive elements meet a contrast ratio of >= 4.5:1 and error messages are programmatically associated to inputs via aria-describedby. Given localized rendering in Spanish, When the page loads, Then the html lang attribute is set to "es" and all visible strings are translated with no mixed-language artifacts.
Persist Language and Accessibility Context with Consent Records
Given a user responds to a consent prompt via the web page, When the consent is recorded, Then the record includes language_used, selection_reason, channel, template_id, encoding_used (for SMS), accessibility_mode_enabled (true/false), and device_locale (if provided). Given authorized API access, When querying consent records by patient ID, Then the response includes the above fields and supports filtering by language_used and channel. Given a re-permission campaign is launched, When selecting recipients, Then the system uses language_used and accessibility_mode_enabled to select the localized template and enable the accessible page variant by default. Given configured data export, When exporting consent logs, Then language and accessibility context fields are included and redacted per HIPAA configuration policies.

Guardian Link

Links guardian permissions to dependents for pediatric and family accounts. Supports family-wide opt-in/out with per-child overrides and channel-level preferences, reducing confusion and ensuring the right caregiver receives the right message every time.

Requirements

Family Linkage & Guardian Verification
"As an office manager, I want to link guardians to child patients and verify their identity so that messages route only to authorized caregivers."
Description

Establish a robust family data model that links guardians to dependent patient records with verified identity and role-based permissions. Support multiple guardians per child (e.g., primary, secondary, legal, temporary/emergency) with configurable custody flags and notification eligibility. Implement secure verification flows (SMS/email OTP; staff-verified in-office capture) to confirm guardian ownership of contact channels before activation. Handle lifecycle events such as age-of-majority transitions (automatic transfer of communication rights to the patient, with notification to guardians) and guardian changes (add/remove/temporarily suspend). Provide safeguards against duplicate guardians and cross-practice conflicts by using deterministic matching and merge rules. This foundation ensures only authorized caregivers receive communications, improving accuracy and compliance while reducing misrouted messages.

Acceptance Criteria
Link multiple guardians with roles and custody flags
Given a dependent patient record exists, When staff links a guardian, Then a role must be selected from [primary, secondary, legal, temporary/emergency] and is stored with timestamp and staff ID. Given a guardian is linked to a child, When custody flags are set, Then flags must be chosen from a predefined set [sole, joint, restricted, supervised] and persisted atomically with the guardian link. Given existing guardian links, When viewing a child's guardians, Then the list displays unique guardians (no duplicates) ordered by role precedence [primary > legal > secondary > temporary/emergency] with custody flags visible. Given a guardian is already linked to a child, When staff attempts to link the same guardian again, Then the system prevents duplication and suggests editing the existing link. Given audit requirements, When any guardian role or custody flag is created or changed, Then an immutable audit record is captured (who, what, when, before/after values).
Verify guardian contact channels via OTP before activation
Given a guardian phone or email is unverified, When an OTP is requested, Then generate a single-use 6-digit OTP that expires in 10 minutes and limit validation attempts to 5 per channel per 24 hours. Given an OTP is sent, When composing the message, Then exclude PHI and include practice name and a unique request ID. Given the correct OTP is submitted before expiry and within attempt limits, When validation succeeds, Then mark the channel Verified with method=OTP, channel type, timestamp, and verifier ID and make it eligible for notifications. Given an OTP is incorrect or expired, When validation fails, Then keep the channel Unverified and ineligible for notifications and display a non-PII error. Given repeated failures exceed limits, When lockout is triggered, Then block further OTP requests for that channel for 24 hours and record an audit event with reason=rate_limited.
Staff-verified in-office guardian verification capture
Given a staff user has Verification permission, When they capture in-office verification, Then they must attest to verifying identity and relationship, record document type, last 4 of ID, and consent for channels selected. Given in-office verification is saved, When storing sensitive fields, Then values are encrypted at rest and redacted in standard UI/logs; only authorized roles can view minimal metadata (method=Staff, verifier, timestamp). Given a guardian's phone/email is verified in-office, When saved, Then set Verified with method=Staff and make the channel eligible for notifications without sending an OTP. Given a staff user lacks Verification permission, When attempting in-office verification, Then the action is blocked with an authorization error and no data is stored. Given compliance requirements, When in-office verification is completed, Then an audit record is created with who, what, when, and evidence references (no images inline if policy disallows).
Notification eligibility with family-wide opt-in/out, per-child overrides, and channel preferences
Given a family-wide opt-in/out setting exists, When toggled, Then all dependents inherit the setting by default and the change is logged with reason. Given a per-child override is set, When eligibility is evaluated, Then the per-child setting supersedes the family-wide setting for that child only. Given channel-level preferences per guardian per child (SMS, Email, Voice), When generating reminders, Then only enabled and verified channels are queued. Given custody flags affect eligibility, When evaluating recipients, Then guardians marked restricted are excluded from appointment and reminder communications; temporary/emergency receive only emergency templates; legal receive legal/policy notices; primary receive all appointment communications unless explicitly opted-out. Given a guardian is suspended, When eligibility is evaluated, Then no communications are queued for that guardian across all children during the suspension window. Given traceability needs, When eligibility is computed, Then store a decision log with template ID, evaluated rules, and reason codes per included/excluded recipient.
Age-of-majority auto-transfer of communication rights
Given a dependent has a configured age-of-majority (default 18), When the birthday threshold is reached at 00:00 local practice time, Then communication rights transfer from guardians to the patient record. Given rights have transferred, When eligibility is next evaluated, Then guardians are excluded from appointment communications for that patient, and the patient is included only on verified channels. Given the transfer occurs, When notifications are dispatched, Then send a rights-change notice to the patient and all linked guardians via their verified channels without PHI content. Given audit requirements, When the transfer is executed, Then create an immutable audit record including prior and new rights, executor=system, and timestamps. Given patient channels are unverified at transfer, When composing messages, Then suppress outbound communications until at least one patient channel is verified, and surface a task for staff follow-up.
Guardian change management: add, remove, temporarily suspend
Given a child record, When adding a guardian, Then run duplicate detection before creation and prevent creating a new record if a confident match exists; instead link the existing guardian. Given a guardian is removed, When the change is saved, Then cancel pending messages for that guardian related to that child and retain historical audit without deleting past communication logs. Given a guardian is temporarily suspended with start/end dates, When eligibility is evaluated within the window, Then exclude the guardian from all communications and automatically restore eligibility after the end date. Given any change (add/remove/suspend), When saved, Then a reason code is required and an audit entry is created with who, what, when, and affected entities. Given changes affect stakeholders, When add/remove/suspend is finalized, Then send non-PHI notifications to the affected guardian and optionally to the primary guardian per practice policy.
Duplicate guardian detection, merge, and cross-practice conflict handling
Given a new guardian is being created, When deterministic matching runs, Then match on normalized name + DOB + hashed phone/email; if a high-confidence match is found in the same practice, block creation and prompt to link. Given potential duplicates exist across practices, When a match is found, Then do not auto-merge; instead create a cross-practice review task and prevent cross-practice data/consent leakage until resolved. Given two guardian records are merged, When merge completes, Then consolidate links per child without creating duplicates, preserve the most recent verification status per channel, and require manual resolution for conflicting roles/custody flags. Given merge or conflict operations occur, When finalized, Then generate a comprehensive audit trail including match criteria, decisions, and user approvals. Given a merge would expand notification eligibility, When rules are applied, Then do not elevate permissions by default; only previously verified channels remain eligible and restricted custody flags remain restrictive.
Hierarchical Consent & Channel Preferences
"As a guardian, I want to set family-wide preferences with per-child and per-channel overrides so that I receive the right messages the right way."
Description

Create a hierarchical preference and consent model that supports family-wide opt-in/out with per-child overrides and channel-level granularity (SMS, email, voice). Allow configuration by message category (appointments, recalls, billing, pre/post-op, marketing) with quiet hours, language preferences, and escalation rules. Implement inheritance logic where family defaults apply unless a child-level override exists, with clear conflict resolution and visibility of the effective state. Capture consent provenance (who, when, how, source, IP/device) and map STOP/START/HELP keywords to the appropriate scope (family vs. child vs. channel). Store revocation history and honor compliance requirements (TCPA/HIPAA) while enabling re-consent flows. This model reduces confusion, respects caregiver preferences, and enables precise, compliant outreach.

Acceptance Criteria
Effective Preference Inheritance Across Family and Child Overrides
Given a family default opt-in for SMS, email, and voice across all categories and a child-level override opting Child B out of SMS only When the system computes effective preferences for Child A and Child B Then Child A remains opted-in for SMS, email, and voice; Child B is opted-out of SMS but remains opted-in for email and voice; and the effective-state API returns per-child, per-channel status with source-of-truth (family vs. child) and last-updated timestamps Given conflicting child-level settings for the same channel and category at different times When the system determines the effective state Then the most recent timestamp at the same scope wins and the conflict resolution reason is included in the effective-state response
Category-Specific Channel Preferences Per Dependent
Given family-level preferences of marketing SMS = opt-out, appointment SMS = opt-in, and no child overrides When messages are generated for all dependents Then marketing SMS are suppressed for all dependents, appointment SMS are delivered to all dependents, and other categories are unaffected Given a child-level override for Child B setting marketing email = opt-in, marketing SMS = opt-out When marketing messages are generated Then Child B receives marketing email only; all dependents continue to not receive marketing SMS; audit entries record scope, channel, category, and timestamps Given categories appointments, recalls, billing, pre/post-op, and marketing are configured When retrieving preferences via API for a child Then the response includes channel-level status per category with inheritance indicators
Quiet Hours and Escalation Respecting Hierarchy
Given family-level quiet hours set to 20:00–08:00 for all channels and a child-level override for Child B setting voice quiet hours to 21:00–07:00 When an appointment reminder is scheduled at 21:30 Then SMS and email are queued until 08:00 for all dependents; voice for Child B is queued until 07:00; voice for other dependents is queued until 08:00 Given an escalation rule "if SMS blocked by quiet hours, send email immediately if permitted" When SMS is blocked by quiet hours and email is permitted for the guardian and category Then the system sends email immediately and records the escalation event with reason and target Given multiple guardians where Guardian 1 (primary) is opted-out of SMS for appointments and Guardian 2 is opted-in When an appointment SMS is generated during allowed hours Then the system sends the SMS to Guardian 2 only if an escalation rule "notify alternate opted-in guardian" is enabled; otherwise the message is suppressed
Consent Provenance Capture and Auditability
Given a guardian updates preferences via the patient portal When the change is saved Then the system records provenance including guardianId, timestamp (UTC), action (opt-in/opt-out/update), scope (family/child), channel, category, source = portal, IP/device/user-agent, and retains an immutable audit entry Given staff updates preferences in the admin console on behalf of a guardian When the change is saved Then provenance records staffId, acting-on-behalf-of guardianId (if available), timestamp, scope, channel, category, source = admin, and location/IP Given a keyword-triggered change (e.g., STOP/START) When the keyword is processed Then provenance records originating phone number, resolved guardianId, timestamp, messageId, detected scope, and parsing outcome; audit retrieval returns a complete ordered history for family and per-child queries
Keyword Mapping (STOP/START/HELP) to Correct Scope
Given a guardian replies STOP to an SMS that is tagged to Child A’s appointment thread When the keyword is processed Then SMS is opted-out at child scope for Child A only; a confirmation SMS is sent with compliant content; provenance and effective state are updated immediately Given a guardian sends STOP to the practice long code outside of a child-tagged thread When the keyword is processed Then SMS is opted-out at family scope for all dependents; a confirmation SMS is sent; future START must be at family scope unless a child-specific thread is used Given a guardian sends START after a prior STOP at channel scope When the keyword is processed Then the prior opt-out is lifted at the same scope and channel; for marketing SMS a double opt-in confirmation (e.g., reply YES) is required before messages resume Given a guardian sends HELP When the keyword is processed Then the system returns support instructions without changing consent and logs the interaction
Revocation History and Re-Consent Flow Compliance
Given consent was previously revoked at any scope/channel/category When generating messages covered by that revocation Then no messages are sent until consent is re-established at the required scope; the decision and revocation reference are logged Given a guardian initiates re-consent via portal for marketing SMS When they opt-in Then the system requires explicit consent plus a double opt-in confirmation SMS before setting marketing SMS = opt-in; timestamps and provenance are recorded; history retains prior revocations Given a data export of consent history is requested for compliance When the export is generated Then it includes a complete, immutable timeline of consents/revocations with who, when, how, scope, and channel, suitable for TCPA/HIPAA audit
Language Preferences and Fallback Behavior
Given the family language is Spanish and Child B has a child-level language override to English When generating appointment, recall, billing, pre/post-op, and marketing messages across channels Then messages for Child B and their guardians are rendered in English; messages for other dependents are rendered in Spanish; the effective-state API reflects language source (family vs. child) Given a template translation is unavailable in the preferred language When a message is generated Then the system falls back to English, records a localization gap event, and does not block delivery Given different language preferences per guardian When a category allows guardian-specific language rendering Then the system uses the guardian’s language setting where available; otherwise it uses the child’s, then the family default
Rules-Based Message Routing Engine
"As a scheduler, I want the system to automatically choose the correct recipient(s) for each message based on permissions and preferences so that confirmations are timely and compliant."
Description

Implement a real-time routing engine that determines the correct recipient(s) for each outbound message based on permissions, verified channels, and effective preferences for the message category. Apply precedence: child-level overrides first, then family-level defaults, while honoring custody restrictions and channel availability. Support multi-guardian delivery when allowed (e.g., joint custody) and single-primary routing when mandated. Include fallbacks when no eligible channels exist (e.g., alternate channel, staff task creation) and guardrails against over-communication. Handle age-of-majority and temporary guardianship windows dynamically at send time. Provide deterministic outcomes with reason codes, idempotency, and API hooks for previewing routing decisions. Ensures the right caregiver receives the right message every time, boosting confirmations and reducing no-shows.

Acceptance Criteria
Child Override Precedence for Appointment Reminder (Per-Child SMS Opt-Out)
Given a family default opt-in for SMS on category "Appointment Reminder" And child A has a child-level override to opt-out of SMS but opt-in to Email for "Appointment Reminder" And guardian G1 is permitted for child A with verified Email and verified SMS And guardian G2 is permitted for child A with no verified channels When the engine routes an "Appointment Reminder" for child A Then no SMS is sent for child A to any guardian And an Email is sent to G1 only And no message is sent to G2 And reason_codes include CHILD_OVERRIDE_APPLIED and CHANNEL_UNVERIFIED for excluded channels And the precedence applied is child-level override over family default
Sole Custody: Single-Primary Guardian Routing (Email)
Given child B has custody = "sole" with primary guardian P1 and secondary guardian S1 without permission And family default allows multi-guardian delivery And P1 has verified Email and SMS, with Email preferred for "Appointment Reminder" When the engine routes an "Appointment Reminder" for child B Then exactly one message is delivered to P1 via Email only And no message is delivered to S1 on any channel And reason_codes include CUSTODY_SOLE_PRIMARY and CHANNEL_PREFERENCE_APPLIED
Joint Custody: Multi-Guardian Delivery with Channel Verification (SMS + Voice)
Given child C has joint custody permitting delivery to both guardians G1 and G2 And G1 has verified SMS and opts in to SMS for "Appointment Reminder" And G2 has unverified SMS but verified Voice and opts in to Voice for "Appointment Reminder" When the engine routes an "Appointment Reminder" for child C Then an SMS is sent to G1 and a Voice call is scheduled to G2 And no unverified channel is used And reason_codes include MULTI_GUARDIAN_ALLOWED and CHANNEL_VERIFICATION_ENFORCED
No Eligible Channels: Alternate Channel Fallback and Staff Task Creation
Given child D has guardians G1 and G2 with all channels either unverified or opted-out for "Billing Notice" And the fallback order for "Billing Notice" is Email, then Voice, then Staff Task When the engine routes a "Billing Notice" for child D Then no delivery is attempted on any ineligible channel And if no verified opt-in channel exists, a Staff Task is created with task_type = "RoutingFallback" and reason_codes include NO_ELIGIBLE_CHANNEL And the task references the patient/dependent, guardians evaluated, category, and decision timestamp
Dynamic Eligibility Windows: Age of Majority and Temporary Guardianship
Given child E turns 18 at 2025-10-01T12:00:00Z and the practice age_of_majority is 18 And a temporary guardian TG is permitted for child E from 2025-09-15T00:00:00Z to 2025-09-20T23:59:59Z And the patient has verified Email When the engine routes messages at: - 2025-09-16T10:00:00Z (within temporary guardianship window) - 2025-09-25T10:00:00Z (minor, outside temporary guardianship window) - 2025-10-02T10:00:00Z (post-majority) Then respectively: - Delivery goes to TG per preferences and permissions; other guardians outside the window are excluded - Delivery goes to the standard permitted guardian(s) per preferences - Delivery goes to the patient; guardians are excluded unless explicit post-majority consent exists And reason_codes include TEMP_GUARDIAN_ACTIVE, TEMP_GUARDIAN_EXPIRED, and AGE_OF_MAJORITY_REACHED as applicable
Over-Communication Guardrails: Category and Global Frequency Caps
Given frequency caps are configured as: - max 1 "Appointment Reminder" per recipient per 24h - max 3 total outbound messages per recipient per 24h across categories And guardian G1 already received 1 "Appointment Reminder" and 2 other messages in the last 24h When the engine attempts to route another "Appointment Reminder" to G1 Then the message to G1 is suppressed And reason_codes include SUPPRESSED_FREQUENCY_CAP with details of the violated cap And other eligible recipients not exceeding caps still receive their messages
Deterministic Outcomes, Idempotency, and Preview API Consistency
Given a routing payload for child F with idempotency_key = "IK-123" and inputs unchanged And a preview endpoint is available at POST /routing/preview When: - The preview endpoint is called with the payload - The send endpoint is then called with the same payload and idempotency_key - The send endpoint is called again with the same idempotency_key Then: - The preview response returns the exact recipients, channels, and reason_codes that the send endpoint will produce - The first send executes delivery exactly once and returns a decision_id and deterministic hash - The second send returns success with no duplicate deliveries and the same decision_id and hash And P95 routing decision latency is <= 200 ms And all decisions are audit-logged with input snapshot and reason_codes
HIPAA Audit Trail & Consent Evidence
"As a compliance officer, I want a complete audit trail and consent evidence so that we can prove compliance and resolve disputes quickly."
Description

Record an immutable, time-stamped audit trail for all guardian links, preference changes, consent events, and routing decisions. Store consent artifacts (e-signature, timestamp, IP/device metadata, source document snapshot) and STOP/START keyword logs with scope. Provide exportable reports (CSV/PDF) and verifiable event chains for audits and disputes. Enforce role-based access controls, PHI minimization in logs, and retention policies aligned with regulatory requirements. Surface an audit viewer in-app with filters by patient, guardian, event type, and date range. This capability underpins HIPAA/TCPA compliance, enables rapid investigation, and builds trust with practices and caregivers.

Acceptance Criteria
Record Immutable Guardian Links, Preference Changes, and Routing Decisions
Given any guardian link, preference change, consent event, or routing decision occurs When the event is committed Then an append-only event record is written within 2 seconds with fields: event_id (UUID), event_type, occurred_at (UTC ISO 8601), actor_id, actor_role, patient_id, guardian_id (if applicable), channel, scope, correlation_id, previous_event_hash, event_hash Given an existing event When a user or service attempts to modify or delete it Then the system prevents mutation and writes a new corrective event referencing prior event_id and reason; both remain visible in chronological sequence Given concurrent events for the same patient or guardian When they are saved Then ordering is deterministic by occurred_at and a per-entity monotonic sequence number; no events are dropped or reordered Given PHI minimization requirements When the event is stored Then only minimal identifiers (pseudonymous patient_id/guardian_id) are stored; no message body or clinical content is persisted in the audit trail Given normal operating conditions When events occur Then p95 persistence latency <= 2s and p99 <= 5s; failures retry 3 times with exponential backoff and generate an ops alert if not persisted
Store and Retrieve Consent Evidence Artifacts
Given a caregiver grants consent via e-signature form When consent is captured Then the system stores artifacts: signature_binary_or_hash, occurred_at UTC, IP address, user_agent, device_id (if available), geo_country (derived), form_version, and a PDF snapshot of the signed document linked to the consent event_id Given a stored consent event When viewing consent evidence in the audit viewer Then all artifacts render within 3 seconds and checksums (SHA-256) validate integrity; any missing artifact is flagged with a remediation status Given export of consent events is requested When CSV/PDF export is generated Then artifacts are included as signed links with integrity hashes; PDFs are watermarked with case metadata and exclude unnecessary PHI Given a consent revocation occurs When the revocation is recorded Then a consent_revoked event links to the original consent_granted event_id with reason and actor; downstream routing respects revocation immediately (<= 1 minute)
STOP/START Keyword Logging with Scoped Preferences
Given an inbound STOP/UNSTOP/START keyword is received on SMS or other channel When it is processed Then an opt_event is recorded with fields: keyword, channel, originator_address, patient_id (resolved or null), guardian_id (resolved or null), scope (family-wide or per-child), effective_targets (child IDs), occurred_at UTC, and processor_id Given conflicting preferences exist (family-wide opt-out with per-child opt-in) When routing a message Then the per-child override takes precedence and a routing_decision event records evaluated rules and final recipients Given TCPA compliance requirements When keyword events occur Then future outbound messages to the scoped target(s) on that channel are blocked/allowed accordingly within 1 minute, and the audit trail shows the governing opt event reference Given STOP is received from an unknown contact When attribution cannot be resolved Then an opt_event with status=unattributed is logged, no outbound messaging occurs to that contact until resolved, and support is alerted
Audit Viewer Filtering and Access Controls
Given an authorized role (e.g., Compliance Officer or Practice Admin) is logged in When they open the audit viewer Then they can filter by patient, guardian, event_type, date range, channel, and correlation_id; results for up to 10,000 records load within 3 seconds with pagination and export actions enabled Given an unauthorized role (e.g., Clinician, Scheduler, External) When attempting to access the audit viewer or export Then access is denied with HTTP 403, no data is leaked, and the attempt is logged as a security_event with actor_id and occurred_at Given redaction rules When events are displayed Then PHI beyond minimum identifiers is masked (e.g., phone/email partially masked) and no message bodies or clinical notes appear Given timestamp display requirements When viewing events Then timestamps show in practice local time with hover/secondary display of UTC; exports remain UTC-only
Export Audit Report as CSV/PDF with PHI Minimization
Given current filtered audit results When the user clicks Export CSV Then a UTF-8 RFC 4180 CSV with headers and UTC timestamps is generated within 60 seconds (p95) and row counts match on-screen results exactly Given datasets exceeding 100,000 rows When export is requested Then a background job produces the file and a secure expiring download link (valid 24h) is delivered to the requester; progress status is visible; failures retry up to 3 times and are surfaced to the user and ops Given a PDF export is requested When generated Then it includes a cover page with filter criteria, generation timestamp, requester identity, and a verification footer with a SHA-256 digest of contents Given PHI minimization requirements When exporting Then only minimal identifiers (pseudonymous patient_id/guardian_id and masked contacts) are included; message content is excluded; the export action itself is logged as an audit event
Verifiable Event Chain and Tamper Detection
Given a sequence of events for a patient or guardian When integrity verification is run Then each event_hash equals SHA-256(serialized_event) and previous_event_hash matches the prior event_hash, yielding an unbroken chain Given tampering or a missing event is detected When verification fails Then a high-severity alert is raised, the affected chain is flagged in the UI, and exports from that range cannot claim verified status; the verification report identifies the exact break point Given an auditor receives a CSV/PDF export When they use the published verification endpoint or offline script with the included digest Then they can validate integrity without access to internal systems and receive a Pass/Fail result with details
Retention Policy Enforcement and Legal Hold
Given a configured retention of 6 years from event occurred_at or last activity (whichever is later) When an event surpasses retention and is not on legal hold Then it is purged within 30 days from primary storage and backups per policy, and a non-PHI tombstone metadata record (event_id, type, purge_date) is kept Given a legal hold is applied to a patient, guardian, or case When retention jobs run Then events under hold are preserved until the hold is lifted, with hold reasons, approver, and applied_at recorded; purge is deferred Given purge execution completes When the cycle finishes Then a purge_report is generated with counts and date ranges, signed by the service, visible to authorized roles; attempts to access purged content return not_found and are logged Given encryption requirements When events are stored or exported Then AES-256 at rest and TLS 1.2+ in transit are enforced; key rotations follow policy and do not expose PHI
Family Management Admin UI
"As front-desk staff, I want an easy UI to manage families and preferences so that I can make accurate updates quickly with fewer errors."
Description

Deliver an intuitive SmileCue portal experience to create and manage family groups, assign dependents, designate primary/secondary guardians, and configure preferences at family, child, and channel levels. Provide clear indicators of effective preferences and custody constraints, inline validation, and conflict alerts. Include a routing preview/simulator for any message template to show who will receive it and why, plus bulk actions (e.g., apply quiet hours across all children). Ensure accessibility (WCAG 2.1 AA), localization, and mobile-responsive design. Reduce staff workload and errors by enabling fast, accurate updates and giving immediate feedback on the impact of changes.

Acceptance Criteria
Create Family Group with Guardians and Dependents
Given I have Family Management access When I create a new family with a name, at least one primary guardian (with valid email or mobile), and at least one dependent Then the family is saved and displayed in the list within 1 second And the family detail view shows assigned dependents and guardian roles exactly as entered And inline validation blocks save if any required field is missing or invalid and highlights the field with an error message And changes are persisted and visible after a full page reload
Guardian Roles and Custody Constraints Enforcement
Given an existing family with two guardians and at least one dependent When I set Guardian A as Primary and Guardian B as Secondary and apply a custody constraint that restricts Guardian B from SMS for Child X Then the UI displays a custody restriction badge for Guardian B on Child X and disables SMS toggle for that pairing And attempts to enable a restricted channel show a non-blocking tooltip explaining the restriction and a blocking error on save And removing the custody constraint re-enables the channel toggle immediately
Preference Hierarchy and Effective Preference Indicator
Given a family-level preference of SMS = Opted Out and Email = Opted In When I override Child A to SMS = Opted In and Voice = Opted Out Then the effective preference indicator for Child A shows SMS = Opted In (override), Email = Opted In (family), Voice = Opted Out (child) And Child B (no overrides) shows SMS = Opted Out (family), Email = Opted In (family), Voice = Disabled or Inherited per configuration And updating any preference recomputes the effective indicators within 500 ms and persists after reload
Message Routing Preview and Explanation
Given a selected message template and a family with mixed preferences, custody constraints, and quiet hours When I open the routing preview for send time S in timezone Z Then the preview lists each intended recipient by child and channel with a clear "why" explanation referencing the applicable rules And non-recipients are listed with a single primary reason (e.g., Opted Out, Quiet Hours, Custody Restriction, No Valid Contact) And the preview completes in under 2 seconds for families up to 10 dependents and 4 guardians And changing send time or preferences updates the preview within 1 second
Bulk Quiet Hours Across All Children
Given a family with multiple dependents When I apply quiet hours 8pm–8am to all children and confirm the bulk action Then the system applies the setting to each child and reports the count of updated records in a success message And any children already matching the setting are skipped and included in the summary as unchanged And effective preference indicators update within 500 ms to reflect quiet hours impact
Inline Validation and Conflict Alerts
Given I edit a guardian’s contact methods and child-level preferences When I enter an invalid phone number or email or attempt to duplicate a contact already used by another guardian in the same family Then the field is flagged inline with a specific error message and save is blocked until corrected And if guardian-level opt-out conflicts with a child-level attempt to enable a channel, a conflict banner explains the issue and the conflicting toggle is auto-disabled And resolving the conflict clears the banner immediately
Accessibility, Localization, and Responsive Behavior
Given I navigate the Family Management Admin UI with keyboard only When I tab through interactive elements Then focus order follows visual order, focus is visible, and all actions are operable without a mouse And all interactive controls have accessible names/labels announced by screen readers, error messages are programmatically associated, and color contrast is at least 4.5:1 And switching locale to Spanish localizes static UI text and date/time formats without truncation or overlap And on a 320px-wide viewport, create family, assign dependents, set preferences, and open preview are usable without horizontal scrolling; touch targets are at least 44x44px
PMS Family Sync & Mapping
"As an IT admin, I want SmileCue to sync family and responsible-party data from our PMS so that data stays accurate without double entry."
Description

Integrate with leading dental PMS systems (e.g., Dentrix, Eaglesoft, Open Dental) to import and synchronize family relationships, responsible parties, and contact channels. Implement field mapping, incremental sync, deduplication, and idempotent upserts to maintain a single source of truth. Detect and resolve conflicts between PMS data and in-app edits using precedence rules and review queues. Support webhooks for near-real-time updates and monitoring dashboards for sync health and error remediation. Reliable sync minimizes double entry, keeps guardian links current, and ensures routing decisions are based on accurate data.

Acceptance Criteria
Initial Family Import and Field Mapping from PMS
Given a PMS provides a family with 1–10 members including guardian(s), dependents, responsible party, phones, and emails When the initial sync runs for the practice Then SmileCue creates one Family record with PMS family_id preserved and links all members using PMS patient_ids And maps relationships (guardian/dependent/responsible_party) exactly as in PMS And creates contact channels for each member with type (SMS, Email, Voice), normalized phone (E.164), and email lowercased And sets consent flags and preferred channel from PMS where available; otherwise defaults to practice settings And writes an audit log entry per created/updated entity with correlation_id of the sync job And completes processing within 5 minutes for families up to 10 members with zero mapping errors
Incremental Sync with Idempotent Upserts
Given a PMS updates a member's attribute and emits a change with PMS patient_id and updated_at When the incremental sync processes the change Then only the changed fields are updated in SmileCue; unchanged fields remain intact And repeating the same change (same payload and updated_at) results in no additional write operations And no duplicate Family, Guardian, or ContactChannel records are created And the change is visible in SmileCue within 30 seconds of receipt And an audit log records before/after values and idempotency status
Deduplication of Guardians and Contact Channels
Given two guardian records refer to the same person (same PMS person_id or matching normalized phone and email) When the sync runs Then the records are merged into a single Guardian in SmileCue And duplicate contact channels (same normalized phone/email and channel type) are collapsed to one And message history and consents are preserved and combined with latest-updated values taking precedence And a merge log entry records source record IDs, retained target ID, and fields resolved And no more than one Guardian per unique PMS person_id exists after sync
Conflict Detection, Precedence Rules, and Review Queue
Given a field is edited in SmileCue and the same field is later changed in the PMS with a conflicting value When the sync processes the PMS update Then precedence rules apply: PMS overrides for legal_name, date_of_birth, relationship; SmileCue overrides for channel consents, opt-in/opt-out, channel preferences And conflicts that cannot be auto-resolved are placed in the Review Queue with the field, old value, PMS value, in-app value, and recommended action And the affected record is marked as "needs_review" without losing current effective values And the conflict appears on the dashboard within 60 seconds with assign/resolve actions available And resolving in the queue applies the chosen value and clears the flag with an audit entry
Webhook Processing and Reliability for Near-Real-Time Updates
Given a signed webhook from a connected PMS with event_type in {family.updated, patient.updated, contact.updated} When SmileCue receives the webhook Then the signature is validated, the payload schema is verified, and an idempotency key is extracted And events are processed in family order with at-least-once delivery and idempotent upserts preventing duplicates And transient failures are retried up to 5 times with exponential backoff; after that the event is moved to a dead-letter queue And the 99th percentile end-to-end processing latency is under 10 seconds during normal load And all outcomes (success, retry, dead-letter) are observable in monitoring with correlation_id
Sync Health Dashboard, Alerts, and Remediation
Given a practice admin opens the PMS Sync dashboard When viewing sync health Then they can see last successful sync time, current sync lag (minutes), success/error rates (24h), in-flight job count, and top 5 error types And they can filter by practice location and time window (last hour, 24h, 7d) And they can download a CSV of failed items with record IDs and error messages And alert rules can be configured (e.g., error_rate > 2% for 15 minutes, lag > 10 minutes) with notifications via email and Slack And remediation actions are available per item: retry, requeue family, re-run mapping, or dismiss with reason
Accurate Routing Using Guardian Link After Sync
Given a dependent has guardian links and channel-level preferences synced from the PMS and/or edited in SmileCue When an appointment reminder is generated for the dependent Then messages are routed only to guardians permitted for that child and channel, honoring family-wide opt-in/opt-out with per-child overrides And no message is sent to any guardian or channel that is opted out or lacks consent And if multiple guardians are eligible, the preferred guardian is selected based on responsible_party first, then most recently confirmed contact And the routing decision, eligible set, and exclusion reasons are logged on the message event And end-to-end tests across 20 canonical family patterns achieve 100% routing accuracy

Universal Suppression

Propagates opt-outs and consent changes across all connected systems (PMS, email platforms, dialers) via APIs and webhooks, and blocks outbound sends at preflight from any source that checks the Lockbox. Prevents accidental noncompliant outreach and keeps every tool in sync.

Requirements

Consent Lockbox Registry
"As a compliance officer, I want a centralized, HIPAA-safe consent registry so that all systems reference a single source of truth and avoid noncompliant outreach."
Description

Build a centralized, HIPAA-compliant consent and suppression store that serves as the single source of truth across SMS, email, and voice. Model patient-level identities and channel-specific preferences (transactional vs. marketing; purpose-based consent) with timestamps, source-of-truth, and reason codes. Enforce immutability of historical events with append-only event streams and maintain current-state projections for low-latency reads. Provide encrypted at-rest/in-transit storage, PHI minimization, tenant isolation, and RBAC. Expose idempotent read/write APIs for recording opt-outs/consent updates and retrieving effective send eligibility per patient and channel. Ensure sub-100ms p95 read latency and horizontal scalability to support preflight checks at campaign scale.

Acceptance Criteria
Preflight Eligibility Check at Campaign Scale
- Given a tenant with an existing consent dataset and indexing ready, When the Effective Eligibility Read API is exercised at 5,000 RPS for 5 minutes across mixed SMS/Email/Voice and purposes, Then p95 latency is < 100 ms and error rate < 0.1%. - Given a request specifying patientId, channel, and purpose, When the API responds, Then it returns eligible (boolean), reasonCode (enum), evaluatedAt (ISO-8601), and sourceOfTruth (string). - Given an opt-out event appended at time T, When a read occurs after the projection lag threshold (<= 1 second), Then eligibility reflects the new state for that channel/purpose. - Given multiple concurrent reads for the same patient/channel/purpose, When served from the current-state projection, Then all responses within a 100 ms window are consistent (no oscillation). - Given batch mode with up to 1,000 patient/channel/purpose tuples, When called, Then p95 latency per tuple remains < 100 ms and overall response returns a result per tuple with no omissions.
Idempotent Consent Update via API
- Given a well-formed consent update payload and X-Idempotency-Key, When POST /consents is called twice with the same key within 24 hours, Then only one event is stored and both calls return 200 with the same eventId. - Given a payload with channel in {SMS, EMAIL, VOICE} and purpose specified, When validation runs, Then unknown channels/purposes are rejected with 400 and no event is stored. - Given two valid updates for the same patient/channel/purpose arriving within 50 ms, When processed, Then both events are appended and the effective state reflects the event with the later eventTime; ties break by serverReceivedAt. - Given a successful write, When the response is returned, Then it includes eventId, eventTime (server), effectiveState (OptedIn/OptedOut), sourceOfTruth, and reasonCode. - Given a successful write, When the projection is queried after <= 1 second, Then the effective state reflects the new event.
Historical Consent Event Immutability
- Given an existing eventId, When a client attempts PUT/PATCH/DELETE on that event resource, Then the service returns 405 Method Not Allowed (or 409 Conflict) and the event stream length remains unchanged. - Given an existing eventId, When a second POST attempts to overwrite the same eventId, Then the service rejects the request with 409 Conflict and no mutation occurs. - Given the event stream for a patient, When events are listed, Then each event is read-only with immutable fields (eventId, eventTime, sourceOfTruth, reasonCode, payload) and no field differs from its stored checksum. - Given append-only semantics, When new information is received, Then the system records it as a new event without altering prior events.
Channel and Purpose-Specific Eligibility Resolution
- Given a patient with SMS:MARKETING=OptedOut and SMS:TRANSACTIONAL=OptedIn, When eligibility is requested for SMS:MARKETING, Then eligible=false with reasonCode=ExplicitOptOut; and for SMS:TRANSACTIONAL, Then eligible=true with reasonCode=ExplicitOptIn. - Given a patient with EMAIL:MARKETING=OptedIn and VOICE:MARKETING=OptedOut, When eligibility is requested, Then EMAIL:MARKETING returns eligible=true and VOICE:MARKETING returns eligible=false with their respective reason codes. - Given no prior events for a patient/channel/purpose, When eligibility is requested, Then the API returns eligible=false with reasonCode=NoRecord. - Given multiple historical events, When eligibility is requested, Then the result reflects the latest applicable event by eventTime for that channel/purpose and includes the sourceOfTruth of that event. - Given a batch request mixing channels and purposes, When processed, Then each tuple returns an independent result with its correct reasonCode and no cross-channel leakage.
Security: Encryption, PHI Minimization, Tenant Isolation, and RBAC
- Given data at rest in all persistence layers, When inspected, Then patient identifiers and consent records are encrypted with AES-256 (or stronger) keys managed by KMS and key rotation is configured at least annually. - Given API traffic, When observed, Then TLS 1.2+ is enforced with modern ciphers; plaintext HTTP requests are redirected or rejected. - Given the consent data model, When fields are enumerated, Then no PHI beyond patientId (or surrogate), channel, purpose, eventTime, reasonCode, sourceOfTruth, and minimal metadata is stored; message content and diagnosis data are absent. - Given role-based access, When a user with Reader role calls GET, Then access is allowed within their tenant; When a user without Writer role calls POST, Then 403 is returned; cross-tenant access attempts return 403 and are audited. - Given multi-tenant storage, When querying by tenantId, Then results never include records from other tenants as verified by isolation tests and attempted SQL injection returns no cross-tenant data. - Given audit requirements, When any read/write occurs, Then an audit log captures who, what, when, tenantId, patientId, and outcome, and logs are immutable and exportable.
Consent Change Event Publishing to Integrations
- Given a successful consent event append, When publishing, Then a change notification (webhook or event stream) is emitted within 3 seconds p95 containing eventId, tenantId, patientId, channel, purpose, newEffectiveState, and reasonCode. - Given transient delivery failures, When retrying, Then the system retries with exponential backoff for up to 24 hours with at-least-once delivery semantics. - Given idempotent consumers, When the same eventId is delivered more than once, Then receivers can deduplicate using eventId and a stable signature header (HMAC-SHA256) over the payload. - Given integration outage, When delivery ultimately fails, Then events are retained for replay and producers surface operational alerts without blocking writes to the registry.
Patient Identity Merge and Effective State Reprojection
- Given two patientIds A and B with independent consent histories, When a merge event aliases B to A, Then the system reprojects A’s effective states using the union of events from A and B, preserving all historical events with their original patientId. - Given a post-merge read using B, When eligibility is requested, Then the service resolves B to the canonical A and returns eligibility for A within <= 2 seconds of the merge event. - Given an unmerge event, When processed, Then aliasing is removed, A and B regain independent effective states, and subsequent reads reflect the separation within <= 2 seconds. - Given merge/unmerge operations, When listing the event stream, Then merge/unmerge are represented as append-only identity events; no historical consent events are altered or deleted.
Preflight Send Gatekeeper
"As a platform engineer, I want a preflight API to allow-or-deny sends so that no message is transmitted to suppressed contacts from any source."
Description

Provide a synchronous preflight decision service and SDKs that intercept all outbound sends from SmileCue and connected systems to allow or deny delivery based on the Consent Lockbox. Support single and bulk checks, return structured reason codes (e.g., OptedOut, NoConsentPurpose, JurisdictionBlock), and include TTL-based caching for resilience without risking stale consent usage. Offer lightweight language-specific middleware and REST/gRPC endpoints to make integration trivial for third parties. Enforce mandatory preflight for all outbound pathways within SmileCue’s orchestrators and expose auditable decision logs. Target <100ms p95 decision latency and transparent circuit-breaker behavior under dependency degradation.

Acceptance Criteria
Synchronous Preflight Decision Latency
Given a valid preflight request via REST or gRPC containing recipientId, channel, purpose, and sourceSystem When the gatekeeper evaluates consent against the Consent Lockbox Then it returns HTTP 200 (or gRPC OK) with decision in {Allow, Deny} and reasonCode within 100ms for at least 95% of 10,000 consecutive requests per environment And the response includes traceId, policyVersion, cacheStatus, and latencyMs fields And requests that exceed 2s are treated as Deny with reasonCode=Timeout and are logged
Structured Reason Codes in Responses
Given a recipient is globally opted out When a preflight check is requested for any channel or purpose Then decision=Deny and reasonCode=OptedOut Given a recipient lacks consent for the requested purpose but is not opted out When a preflight check is requested Then decision=Deny and reasonCode=NoConsentPurpose Given the recipient’s jurisdiction prohibits outreach for the requested channel/purpose When a preflight check is requested Then decision=Deny and reasonCode=JurisdictionBlock Given all applicable checks pass When a preflight check is requested Then decision=Allow and reasonCode=OK And all endpoints (REST/gRPC) and SDKs return the same reasonCode values and schema
Bulk Preflight with Per-Item Results
Given a bulk preflight request containing 1..1000 items with recipientId, channel, purpose, and correlationId per item When the bulk endpoint (/preflight/bulk or gRPC BulkCheck) is called Then the response returns an array of results matching the request order and count And each item includes decision, reasonCode, correlationId, and per-item traceId (or batchTraceId+index) And invalid items return decision=Deny with reasonCode=ValidationError without preventing evaluation of other items And per-item p95 latency within a batch is ≤100ms measured over 100 batches of mixed decisions
Safe TTL Caching and Immediate Invalidation
Given caching is enabled with a configurable TTL not exceeding 30 seconds When a decision result is cached as Allow for a recipient/channel/purpose Then subsequent identical preflight checks within TTL may return cacheStatus=HIT with the same decision Given the recipient’s consent changes (e.g., opt-out or consent revoked) after a cached Allow When the change event is processed Then the corresponding cache entry is invalidated within 1 second of event receipt And the next preflight for that tuple returns decision=Deny and cacheStatus=MISS (or INVALIDATED) regardless of remaining TTL Given the cache store is unavailable When a preflight check is requested Then the service bypasses cache (cacheStatus=BYPASS) and evaluates against the source of truth without using stale data
Mandatory Preflight Enforcement in SmileCue Orchestrators
Given an outbound SMS, email, or voice send is initiated by any SmileCue orchestrator When the orchestrator prepares to dispatch the message Then it must perform a synchronous preflight check for the exact recipientId, channel, and purpose immediately prior to send And dispatch proceeds only if decision=Allow And if decision=Deny or the preflight call errors or times out, the send is blocked and no outbound message is emitted And the block is recorded in orchestration logs and in the decision log with the associated traceId
Auditable and Immutable Decision Logs
Given any preflight decision is evaluated (single or bulk) When the decision is produced Then an immutable audit log entry is written containing timestamp, recipientId, channel, purpose, decision, reasonCode, policyVersion, sourceSystem, traceId, cacheStatus, and latencyMs And message content or PHI is not stored in the log And authorized admins can query logs by time range, recipientId, decision, reasonCode, and export results via API And the preflight response includes a decisionLogId to correlate runtime behavior with audit records
Transparent Circuit-Breaker Fail-Safe Behavior
Given the Consent Lockbox or critical dependency is intentionally degraded or unavailable (simulated via a chaos toggle or actual outage) When preflight checks are invoked during the open-circuit window Then decisions return Deny with reasonCode=CircuitOpen and circuitState=OPEN within 50ms p95 And metrics expose circuit state transitions (CLOSED → OPEN → HALF_OPEN → CLOSED) and error rates And upon recovery, the circuit transitions through HALF_OPEN to CLOSED using the configured cool-down policy And all circuit-related Deny decisions are logged with dependency error details in the audit log
Real-time Opt-out Ingestion
"As a patient, I want my STOP or unsubscribe to take effect immediately across all channels so that I stop receiving unwanted communications."
Description

Ingest opt-out and consent-change signals in real time from all channels and partners via secure webhooks and listeners (SMS STOP keywords, email unsubscribe clicks/headers, IVR DTMF opt-out, PMS flags). Validate signatures, normalize to a canonical event schema, deduplicate via idempotency keys, and apply ordering guarantees per patient. Process events within seconds to update the Lockbox and trigger propagation to connected systems. Provide backpressure handling, retry with exponential backoff, and dead-letter queues for failed events. Emit operational metrics and alerts for anomaly detection (e.g., spike in opt-outs) without logging PHI.

Acceptance Criteria
Real-time Channel-Agnostic Opt-out Ingestion
Given a valid opt-out or consent-change event from SMS, email, IVR, or PMS with required fields and a verified signature When the event is received Then it is normalized to the canonical schema and applied to the Lockbox, and the ingestion endpoint returns HTTP 2xx within 1 second And p95 end-to-end time from receipt to Lockbox update is <= 5 seconds; p99 <= 10 seconds And upon successful update, propagation notifications to connected systems are enqueued within 2 seconds
Webhook Signature Verification and Replay Protection
Given a webhook request with an invalid or missing signature When received Then the system returns HTTP 401/403, does not normalize or apply the event, and records a security audit entry without PHI Given a webhook request with a valid signature within ±5 minutes clock skew and a nonce/idempotency_key not seen in the previous 24 hours When received Then the request is accepted for processing
Idempotency and Duplicate Event Suppression
Given one or more duplicate deliveries sharing the same idempotency_key and source_system within 24 hours When processed Then only the first delivery mutates state and subsequent deliveries return HTTP 200 with an idempotent result and no additional state changes And the duplicate_events_count metric increments for each suppressed duplicate
Per-Patient Ordering Guarantee
Given multiple valid events for the same patient_id that arrive out of order When processed Then the Lockbox reflects the consent_state of the event with the latest event_time, and older events do not overwrite newer state And an immutable audit record captures applied order (by event_time and receive_time) and the final decision
Resilience—Retry, Backoff, and Dead-letter Queue
Given a transient failure when applying an event (e.g., database timeout) When the operation fails Then the system retries with exponential backoff starting at 1s, doubling up to 5 attempts over <= 15 minutes before declaring failure Given an event that still fails after max retries When exhausted Then the event is routed to a dead-letter queue with error metadata (no PHI) and an alert is emitted; a replay endpoint/process can requeue DLQ events and preserves original ordering per patient on replay Given sustained inbound rate exceeding processing capacity When backpressure engages Then the system sheds load using 429 with Retry-After or internal queueing without data loss, while maintaining per-patient ordering
Canonical Schema Validation and PHI Safeguards
Given an incoming event When validated Then required fields (patient_id, source_system, channel, event_type, event_time, consent_state, idempotency_key, signature_verified) must be present and correctly typed; otherwise return HTTP 422 and do not update the Lockbox And any extraneous PHI fields in the payload are ignored/not persisted; logs contain only non-PHI identifiers (e.g., hashed patient_id, event_id)
Operational Metrics and Anomaly Alerting
Given normal processing When events flow Then the system emits metrics: processed_events_count by channel/source, error_rate, retry_count, dedup_rate, DLQ_depth, and latency (p50/p95/p99) without PHI Given opt-out rate for any channel exceeds 3x the 7-day moving average for 5 consecutive minutes When detected Then an alert is sent to on-call within 2 minutes containing counts, affected sources, and links to dashboards; no PHI is included
Bi-directional System Connectors
"As an office manager, I want SmileCue to sync opt-out status with our PMS, email, and dialer so that staff and tools stay aligned without manual updates."
Description

Deliver prebuilt, configurable connectors for leading PMS (e.g., Dentrix, Eaglesoft, Open Dental), email platforms (e.g., SendGrid, Mailgun), and dialers (e.g., Twilio, Plivo) to propagate consent changes both ways. Map identities across systems using deterministic keys (MRN, phone, email) with configurable match rules and hashing where needed. Subscribe to partner webhooks/APIs for inbound updates and publish suppression updates out with retries, rate-limit handling, and change batching. Provide connector health dashboards, per-tenant isolation, and self-service credentials via OAuth/API keys. Ensure that external systems’ suppression lists reflect Lockbox decisions within minutes and reconcile conflicts via defined precedence rules.

Acceptance Criteria
Real-time Bi-Directional Consent Sync Across PMS, Email, and Dialer Connectors
Given a consent change (opt-in/opt-out/channel-specific) in a connected external system (Dentrix, Eaglesoft, Open Dental, SendGrid, Mailgun, Twilio, Plivo), When the connector receives the event, Then Lockbox reflects the change and publishes resulting suppression/consent updates to other connected systems within 5 minutes P95 and 10 minutes P99. Given a consent change entered in Lockbox, When connectors push updates out, Then each target system’s suppression list or equivalent reflects the change within 5 minutes P95 and 10 minutes P99. Given transient partner or network errors, When retries are triggered, Then delivery is attempted with exponential backoff up to 6 retries over 30 minutes and succeeds without duplicate side effects due to idempotency keys. Given a connectivity outage lasting up to 1 hour, When connectivity is restored, Then the backlog is drained and the system returns to within-SLA latency within 15 minutes without data loss.
Deterministic Identity Mapping With Configurable Match Rules and Hashing
Given configured match precedence MRN > phone > email, When events contain multiple identifiers, Then the highest-precedence deterministic key is used to link records. Given partners requiring hashed identifiers, When phone/email must be hashed, Then SHA-256 with a tenant-specific salt is applied and mapping succeeds against stored hashed values; plaintext is not persisted. Given incomplete identifiers (no MRN/phone/email), When an event arrives, Then it is not auto-linked; it is routed to an exceptions queue with reason code IDENTITY_INSUFFICIENT and visible in the dashboard. Given conflicting matches (e.g., two patients share a phone), When mapping is attempted, Then tie-break uses configured secondary attributes (e.g., DOB, last name) and if still ambiguous the event is quarantined with reason code IDENTITY_AMBIGUOUS.
Inbound Webhook and API Subscriptions With Idempotency and Signature Validation
Given partner webhooks are configured, When events are received, Then HMAC/signature validation per partner (e.g., Twilio X-Twilio-Signature, SendGrid/Mailgun signatures) passes or the event is rejected with 401 and not processed. Given duplicate or out-of-order events, When processing occurs, Then idempotency keys (eventId + tenant + source) ensure no duplicate mutations for a 24-hour window. Given a webhook delivery failure, When the partner retries, Then the endpoint responds 2xx only after the event is durably recorded; otherwise returns 5xx and logs correlation IDs. Given a partner without webhook support, When polling is enabled, Then polling respects partner rate limits and detects changes within a 10-minute interval P95.
Outbound Suppression Publishing With Retries, Rate-Limit Handling, and Batching
Given partner API rate limits, When publishing updates, Then the connector never exceeds configured limits and applies leaky-bucket scheduling to spread requests. Given a burst of 5,000 suppression changes, When publishing, Then changes are batched up to 500 items or 2 seconds per batch (whichever comes first) without exceeding the end-to-end latency SLA (5 minutes P95, 10 minutes P99). Given persistent delivery failures, When retries exceed 6 attempts over 30 minutes, Then the change is moved to a dead-letter queue with error details and alerts are raised. Given idempotent partner endpoints, When publishing, Then the connector includes an idempotency key to prevent duplicate side effects.
Conflict Reconciliation Using Defined Precedence and Timestamps
Given conflicting consent states across systems, When reconciliation runs, Then explicit opt-out always overrides opt-in regardless of timestamp. Given same-type events (e.g., opt-in vs opt-in) with different timestamps, When resolving, Then the latest timestamp prevails. Given a Lockbox decision and a newer external decision with higher precedence, When both are present, Then the defined precedence matrix is applied and the resulting unified state is written to Lockbox and propagated to all connectors. Given reconciliation, When a decision is made, Then an audit record is written capturing sources, timestamps, applied rule, and resulting state.
Per-Tenant Isolation and Self-Service Credential Management
Given multiple tenants, When connectors process events, Then data paths, queues, rate limits, logs, and credentials are isolated per tenant and attempts at cross-tenant access are denied with 403 and logged. Given a tenant admin, When connecting a partner via OAuth (e.g., SendGrid) or API key (e.g., Mailgun), Then the flow is self-service, secrets are stored encrypted at rest with KMS, and secrets are redacted in logs. Given credential rotation, When old credentials are revoked and new ones are provided, Then the connector re-authenticates within 2 minutes without losing queued changes. Given a tenant offboards a connector, When disconnect is initiated, Then credentials are revoked, webhooks removed, and publishing ceases within 5 minutes.
Connector Health Dashboard With SLA Metrics and Alerting
Given an active connector, When viewing the dashboard, Then it displays per-tenant status (Healthy/Degraded/Down), last sync time, backlog depth, 24h success rate, P95/P99 latency, error rate, and DLQ size with 1-minute refresh. Given thresholds are breached (P95 latency > 5 minutes for 10 minutes, or error rate > 1% for 5 minutes, or status Down > 5 minutes), When monitoring, Then alerts are sent to configured channels and are visible in the dashboard. Given an error, When drilling down, Then the dashboard shows recent failures with partner response codes, correlation IDs, and payload IDs to enable remediation. Given historical analysis, When querying metrics, Then at least 30 days of connector health and throughput metrics are available.
Granular Consent & Compliance Rules
"As a legal/compliance lead, I want consent tracked by channel and purpose with jurisdictional rules so that we meet HIPAA/TCPA and state requirements."
Description

Implement a policy engine that evaluates send eligibility by channel, content type, and purpose with jurisdiction-aware rules (HIPAA, TCPA, state consent and quiet hours). Distinguish transactional vs. marketing communications, support minors/guardianship, and capture consent provenance (how, when, where). Version policies and allow safe rollout with canarying and auditability. Default to deny on ambiguity and provide human-readable explanations for blocked sends. Enable configurable quiet hours and frequency caps where required by law or practice policy.

Acceptance Criteria
Jurisdiction-Aware Eligibility by Channel and Purpose
Given a patient jurisdiction and practice jurisdiction are resolvable and a policy set is active When a Marketing SMS is queued during configured quiet hours for the patient’s jurisdiction Then the preflight decision returns decision=Deny, reason_code=QUIET_HOURS, references the governing rule and jurisdiction, and no outbound is dispatched Given a patient lacks Marketing consent for Email and purpose=Marketing When a Marketing Email is queued Then the preflight decision returns decision=Deny, reason_code=CONSENT_REQUIRED, includes policy_version and channel, and the send is blocked Given content_type=ContainsPHI and channel=Email (unencrypted) When preflight is evaluated Then the decision returns decision=Deny, reason_code=HIPAA_CHANNEL_RESTRICTION, cites the applicable HIPAA policy, and the send is blocked
Transactional vs Marketing Enforcement
Given purpose=AppointmentReminder and content_type=Transactional and channel=SMS and no Marketing consent exists When preflight is evaluated Then the decision returns decision=Allow, reason_code=TRANSACTIONAL_ALLOWED, and the send proceeds Given purpose=Promotion and content_type=Marketing and only Transactional consent exists When preflight is evaluated Then the decision returns decision=Deny, reason_code=CONSENT_REQUIRED, with a link/reference to consent provenance needed Given purpose is missing or conflicting with content_type When preflight is evaluated Then the decision returns decision=Deny, reason_code=AMBIGUOUS_PURPOSE, lists the missing/conflicting fields, and no send occurs
Consent Provenance Capture and Retrieval
Given a patient opts in to SMS Marketing via web form When consent is saved Then the system persists channel=SMS, purposes=[Marketing], timestamp_utc, source_type=WebForm, source_ref, legal_text_version, jurisdiction_basis, and signature_artifact (if collected) Given a patient replies STOP to an SMS When the event is processed Then the system records consent_revoked with timestamp and origin=SMS_STOP, updates effective consent state, and marks Marketing SMS as ineligible Given an auditor requests consent provenance via the audit API for a patient and channel When the request is made Then the API returns the latest effective consent state, full provenance history, and policy_version used to determine state
Minors and Guardianship Compliance
Given patient_age is below the configured minor threshold for the jurisdiction and no guardian consent exists When a Marketing SMS is queued to the minor’s number Then the decision returns decision=Deny, reason_code=MINOR_GUARDIAN_REQUIRED, and the send is blocked Given a verified guardian with Marketing SMS consent and recipient is the guardian’s number When a Marketing SMS about the minor’s care is queued Then the decision returns decision=Allow, reason_code=GUARDIAN_CONSENT_VALID, and proceeds Given a Transactional AppointmentReminder for a minor When recipient is the minor’s number and guardian preference requires proxy delivery Then the decision returns decision=Deny, reason_code=RECIPIENT_NOT_AUTHORIZED, and includes remediation=UseGuardianRecipient
Default-Deny with Human-Readable Explanation
Given required inputs (purpose, channel, consent state, jurisdiction) are incomplete When preflight is called Then the decision returns decision=Deny, reason_code=INSUFFICIENT_DATA, and explanation is a human-readable message <=500 characters listing missing fields and next steps Given a rule evaluation results in multiple conflicting outcomes When preflight is called Then the decision returns decision=Deny, reason_code=CONFLICTING_RULES, and explanation references the exact rules by id/version that conflict
Configurable Quiet Hours and Frequency Caps
Given quiet_hours for SMS Marketing are configured for the patient’s jurisdiction and tenant When a Marketing SMS is attempted within quiet hours Then the decision returns decision=Deny, reason_code=QUIET_HOURS, includes the effective quiet hour window, and blocks the send Given a frequency cap of 2 Marketing SMS per 7-day rolling window is configured When the 3rd Marketing SMS is queued within the window Then the decision returns decision=Deny, reason_code=FREQUENCY_CAP, includes window_start/window_end and current_count, and blocks the send Given the same caps exist When a Transactional SMS is queued Then the decision returns decision=Allow, reason_code=TRANSACTIONAL_EXEMPT_FROM_CAPS, and proceeds
Policy Versioning, Canary Rollout, and Auditability
Given policy version v2 is created and canary_percent=10% is enabled When preflight requests are evaluated Then exactly ~10% of tenant-scoped traffic is evaluated under v2 using a deterministic hashing strategy, the remainder use v1, and each decision payload includes policy_version Given v2 is rolled back When subsequent preflight requests are evaluated Then 100% of decisions reference v1 and no requests are evaluated under v2 Given any policy change (create, update, rollout, rollback) When the change is saved Then an immutable audit record is written containing actor, timestamp, change diff, scope, and justification
Drift Detection & Reconciliation
"As a data steward, I want automated reconciliation to detect and fix drift so that suppression states remain consistent across systems."
Description

Schedule periodic reconciliation jobs that compare Lockbox state with each connected system’s suppression records to detect drift. Compute diffs, auto-correct according to precedence policy, and open review tasks for irreconcilable conflicts. Produce reconciliation reports, per-connector drift KPIs, and notify admins when drift exceeds thresholds. Support backfill of historical consents during onboarding to rapidly align legacy systems without manual effort.

Acceptance Criteria
Nightly Drift Reconciliation Job Execution
Given a practice with at least two connected systems and a daily reconciliation schedule at 02:00 local time When the scheduled time is reached Then the job starts within ±5 minutes and assigns a unique run_id And for each connector, all suppression records are fetched until pagination is exhausted or the API indicates completion And the system computes two sets per connector: lockbox_minus_connector and connector_minus_lockbox And run metrics include per-connector: total_records, in_sync_count, lockbox_minus_connector_count, connector_minus_lockbox_count, fetch_duration_ms, diff_duration_ms And the run status is "Complete" if 100% of connectors fetched successfully; otherwise "Partial" with per-connector error codes logged
Threshold-Based Drift Alerts to Admins
Given a drift alert threshold configured per connector (percentage or absolute) and at least one connector exceeding it When a reconciliation run completes Then for any connector whose drift exceeds its threshold, an in-app alert and email notification are sent within 2 minutes And each connector generates at most one alert per run_id; duplicates are suppressed And the alert includes run_id, connector_id, drift_counts, drift_percent, and a deep link to the reconciliation report And alerts are not sent if drift is below threshold
Auto-Correction via Precedence Policy
Given a precedence policy where the most recent consent_timestamp wins; on ties, Lockbox suppression state prevails When diffs are detected for a connector Then for each record where Lockbox is the winner, the connector is updated to suppressed/unsuppressed accordingly via its API And for each record where the connector is the winner, Lockbox is updated accordingly And corrections are attempted up to 3 retries with exponential backoff; successes and failures are counted And the system emits corrections_applied_count and corrections_failed_count per connector And no outbound correction is attempted if the connector capability for that action is disabled
Irreconcilable Conflicts Create Review Tasks
Given a correction fails after max retries, or identity resolution is ambiguous (no exact match by patient_id or verified contact), or the connector API returns 4xx authorization errors When the reconciliation run completes Then a review task is created per affected record, assigned to the Admin role, with status "Open" And the task contains: run_id, connector_id, masked patient identifiers, conflicting states, attempted actions, error codes, and suggested next steps And tasks are de-duplicated per record per run_id and are auditable (created_at, updated_at, actor_id) And closing a task requires a resolution action that updates the underlying state or explicitly marks as "Won’t Fix"
Reconciliation Report Generation and Retention
Given a reconciliation run_id When the run finishes (Complete or Partial) Then a report is generated within 2 minutes and stored with 365-day retention And the report is available in CSV and JSON via UI and API with Admin-only access And the report includes run metadata, per-connector metrics, lists of diffs, corrections attempted, failures, and tasks created And all PII fields are masked according to policy (e.g., emails masked, phone last 4 visible)
Per-Connector Drift KPIs and Trends
Given at least five reconciliation runs have occurred When viewing the Drift dashboard or querying the KPIs API Then the system exposes, per connector: drift_percent, drift_count, corrections_applied_count, corrections_failed_rate, mean_time_to_consistency, and 7/30/90-day trends And KPI calculations are consistent across UI and API and documented And data refreshes within 5 minutes of a run completing
Onboarding Backfill of Historical Consents
Given a new connector configured with backfill enabled and a backfill_lookback window (e.g., 24 months) When onboarding starts Then the system imports historical consent events up to the lookback window, deduplicates by patient + channel, and normalizes timestamps to UTC And the merged state is applied to Lockbox and propagated to connectors using the precedence policy And progress is visible (percent complete, records processed) and the job is idempotent on re-run And completion occurs without manual intervention unless irreconcilable conflicts arise, which create review tasks
Admin Console & Immutable Audit
"As an administrator, I want a secure UI and audit trail for consent changes so that we can review who changed what and why for audits."
Description

Provide a secure admin UI to search patients, view effective consent state, and submit changes with justification and dual-control approvals where required. Enforce RBAC, field-level masking, and granular permissions for PHI. Maintain an immutable, append-only audit trail of every consent-related event and preflight decision with timestamps, actor, and source, exportable for eDiscovery and compliance reviews. Offer alerts for attempted bypasses or unusual activity and self-service exports without exposing raw PHI unnecessarily.

Acceptance Criteria
Patient Search & Effective Consent View
Given an authenticated user with Role: FrontDesk and permission patient.read when they search by exact phone number, email, MRN, or full name then results return within 2 seconds for datasets up to 50k records and show no more than 25 records per page by default. Given a matching patient when results render then the patient card displays effective consent state per channel (SMS, Email, Voice) with source of truth, last updated timestamp (UTC ISO8601), and decision reason. Given field-level masking is enabled when the page loads then phone and email are masked (showing last 2 digits/characters) until the user clicks Reveal and provides a just-in-time reason which is logged to the audit trail. Given the Lockbox contains a suppression for any channel when the patient card is viewed then the channel is labeled Suppressed and the action buttons to send outreach are disabled. Given no results are found when a search executes then the UI displays a zero-results state without exposing any PHI and records the search event in the audit trail.
Consent Change Submission with Justification & Dual Control
Given a user with patient.consent.write permission when they initiate a consent change then the form requires a justification of at least 15 characters and a reason code from a controlled list. Given the change would override a prior opt-out or create a new opt-in for SMS or Voice then a second approver with Role: Compliance (not the requester) must approve within 24 hours; otherwise the change auto-expires and no propagation occurs. Given both approvals are completed then the Lockbox and suppression lists are updated atomically within 30 seconds and a webhook with event type consent.updated is delivered to subscribed systems with retries using exponential backoff for up to 24 hours on non-2xx responses. Given a consent change is pending approval then preflight continues to enforce the prior effective state and all attempted sends that would conflict are blocked. Given an approver reviews a request then old value, proposed value, requester, timestamps, and diff are displayed while masking non-essential PHI; approval or rejection writes a discrete audit record.
RBAC & Field-Level Masking Enforcement
Given a user without patient.read permission when they attempt to access the Admin Console then access is denied with HTTP 403 and no PHI is returned. Given a user with Role: FrontDesk when they view patient details then SSN and insurance IDs are fully redacted; phone and email remain masked by default and require a Reveal action with justification; export controls are hidden. Given a user with Role: Compliance when they view patient details then they may Reveal masked fields with justification and may export audit data but cannot export raw message bodies by default. Given any user session is idle for 15 minutes then the session is terminated and re-authentication is required; unsaved consent changes are discarded. Given 5 consecutive failed login attempts for an account then the account is locked for 15 minutes and a security event is logged to the audit trail.
Immutable Audit Trail Completeness & Integrity
Given any of the following events occur (search, view, reveal, consent.change.requested, consent.change.approved, consent.change.rejected, preflight.decision, webhook.delivery, export.started, export.completed) then an append-only audit record is created with event_id (UUIDv4), timestamp (UTC ISO8601 ms), actor_id, role, patient_id, channel, request_id, source_ip, old_value, new_value, justification, and content_hash. Given an audit record is written then it cannot be updated or deleted via any API/UI; modification attempts return HTTP 405 and are logged as security events. Given daily audit finalization runs then a Merkle root over that day’s records is computed and stored; integrity verification detects any tampering and raises an alert on mismatch. Given a compliance user queries the audit trail with filters (date range up to 31 days, actor, patient, event type) then results return within 5 seconds for up to 10 million records with pagination of 1,000 records per page.
Preflight Decision Capture & Blocking of Noncompliant Sends
Given any connected system calls the preflight endpoint with patient/contact and channel when the Lockbox indicates suppression or missing consent then the endpoint responds 403 with error_code PREVENTED_BY_SUPPRESSION and the outbound is blocked. Given a preflight check succeeds then the decision is logged to the audit trail with decision=allow, evaluated_ruleset_version, and inputs used; the API responds in under 200 ms at p95 under normal load. Given a request includes override=true then only tokens with scope outreach.override and role=Compliance are accepted; otherwise respond 403 with error_code UNAUTHORIZED_OVERRIDE and log as bypass_attempt. Given a previously allowed contact becomes suppressed then subsequent preflights reflect the new state within 30 seconds across all connected systems.
Anomaly Detection & Alerting for Bypass Attempts and Unusual Activity
Given more than 10 blocked preflight decisions for the same practice occur within 1 minute or more than 3 override attempts by non-compliance users occur within 5 minutes then a High severity alert is created and sent via email and webhook to the Compliance Alerts destination within 60 seconds. Given an approval occurs outside business hours (local 19:00–07:00) or from a new device/IP then a Medium severity alert is created requiring acknowledgment by a Compliance user within 24 hours. Given an alert is created then it appears in the Admin Console Alerts tab with timestamp, severity, rule_id, practice_id, and linked evidence; acknowledgment and resolution actions are required fields and are written to the audit trail.
Self-Service Compliance Export (PHI-Minimized)
Given a user with role=Compliance and permission=audit.export when they request an export for a date range (max 31 days) and selected filters then a PHI-minimized dataset (no raw message bodies, masked contact info) is prepared within 15 minutes for up to 5 million records and exposed as a download URL that expires in 24 hours. Given the user toggles Include PHI then a second approval by a different Compliance user is required before generation; without approval, the export is not produced. Given an export is generated then the file is encrypted at rest (AES-256) and in transit (TLS 1.2+), includes a data dictionary and schema version, and a SHA-256 checksum is provided for verification. Given an export is downloaded then the download event records actor_id, practice_id, IP address, checksum, and file size in the audit trail.

Voice Consent

Captures TCPA-compliant verbal consent via recorded IVR flows or staff-assisted calls with multi-language prompts. Auto-transcribes and time-stamps each recording into the ledger, making it easy to enroll patients who prefer calls or don’t use SMS while maintaining airtight proof.

Requirements

Immutable Consent Ledger
"As a compliance officer, I want irrefutable, time-stamped proof of each patient’s consent so that we can pass audits and defend against disputes with verifiable evidence."
Description

Create an append-only, time-stamped ledger that stores each voice consent event with cryptographic hashes of the audio file, transcript, and metadata (caller/callee IDs, staff ID when applicable, IVR flow version, language, geo/time data). Persist recordings and transcripts in encrypted storage with retention policies aligned to HIPAA and TCPA, and link ledger entries to patient records. Provide a verifiable consent certificate (JSON and PDF) per event, including hash chain proof and consent scope, accessible via RBAC-gated UI and API. Expose read-only audit APIs, immutable IDs, and integrity verification endpoints to satisfy legal discovery and audits. Integrate runtime checks so messaging workflows verify an active consent ledger entry before outreach, and automatically suppress communications when consent is revoked or expired.

Acceptance Criteria
Append-Only Ledger Entry Creation
Given a new voice consent is captured via IVR or staff-assisted call When the system writes the consent to the ledger Then it creates a new append-only entry with: - UTC ISO-8601 server timestamp and captured call timestamp - Immutable unique ID - Cryptographic hashes of the audio file, transcript, and metadata blob - Metadata including patient ID, caller ID, callee ID, staff ID (if applicable), IVR flow version, language, geo/time data, and consent scope And then the entry is linked to the corresponding patient record And then the ledger hash chain is updated to include the new entry
Immutability and Mutation Prevention
Given an existing consent ledger entry When any client attempts to update or delete the entry via UI, API, or storage Then the operation is rejected (HTTP 405 or 409) with an immutable-record error And then no stored data is altered And then only a new ledger entry may be appended to represent revocation or superseding events And then the ledger hash chain remains valid after the rejected attempt
Encrypted Storage and Retention Compliance
Given a consent recording and transcript are persisted Then they are encrypted at rest using a FIPS-validated cryptographic module with keys managed via KMS and access gated by RBAC And then all access is logged with user/role, timestamp, purpose, and outcome And then the tenant-configured retention policy is enforced for recordings and transcripts When the configured retention period elapses and no legal hold exists Then the media and transcripts are securely destroyed (e.g., crypto-shredded) while ledger hashes and metadata remain And then a deletion audit record is appended referencing the affected ledger entries
Consent Certificate Generation and Access
Given a consent ledger entry exists When an authorized role requests the consent certificate via UI or API Then the system returns both JSON and PDF certificates containing: event timestamp, immutable ID, consent scope, patient ID, caller/callee IDs, staff ID (if applicable), IVR flow version, language, geo/time data, and cryptographic hashes with hash chain proof And then the documents are downloadable and verifiable against the integrity endpoint And then unauthorized users receive HTTP 403 and no document content And then the access is logged with certificate type, user/role, timestamp, and entry ID
Audit and Integrity Verification APIs
Given a user with auditor permissions calls the read-only audit APIs When querying by patient ID, immutable entry ID, or time range with pagination and filters Then the API returns matching ledger entries and certificates without any mutation capability And then the integrity verification endpoint recomputes hashes and returns a deterministic result of "valid" or "invalid" with details And then any hash mismatch or missing artifact produces an "invalid" result with the failing component identified And then all audit API calls are logged with requester identity, parameters, and results
Runtime Consent Enforcement in Messaging
Given an outreach job (SMS, email, or voice) is initiated When the workflow checks the consent ledger for an active consent matching the channel and scope Then the message is sent only if a valid, unexpired, unrevoked consent exists whose effective time is <= now And then the send decision records the referenced consent immutable ID in the message metadata And then if no valid consent exists, the message is automatically suppressed and a suppression audit event is recorded
Revocation and Expiry Handling
Given a patient revokes consent or a consent reaches its configured expiration When the revocation/expiry event is processed Then a new ledger entry is appended referencing the original consent entry and recording timestamp, cause, and scope And then all subsequent outreach attempts within the affected scope are blocked within 60 seconds of the event And then UI and API surfaces show the consent status as revoked/expired with effective time and reference IDs And then the consent certificate reflects the revocation/expiry in its chain proof
Identity Verification & Consent Scope
"As a front-desk staff member, I want reliable identity checks and clear consent scope so that consent is attributed to the correct patient and used only for approved channels and purposes."
Description

Implement patient identity verification within voice flows and staff-assisted calls using multi-factor prompts (e.g., DOB + ZIP + last name) and caller ID matching to reduce false attribution. Support guardian/authorized representative flows with relationship capture and dual attestation where required. Capture explicit TCPA consent wording and bind it to a structured consent scope (channels allowed: SMS, email, voice; purposes: appointment reminders, marketing, recalls; duration/expiration; practice/location). Persist scope and identity evidence with the consent record, and surface scope checks to downstream messaging and campaign enrollment. Handle edge cases (name changes, minors turning 18, number re-assignment) with re-verification prompts and automated re-consent rules.

Acceptance Criteria
IVR Multi-Factor Identity Verification (Patient)
- Given a caller enters the voice consent IVR, When they provide DOB (MM/DD/YYYY), ZIP (5 digits), and last name via DTMF or speech, And the incoming caller ID matches a phone number on the patient record, Then verification passes only if all three fields match exactly and the caller ID match is confirmed. - Given verification attempts, When the caller fails verification 3 times in a session, Then the IVR ends the consent flow, does not record consent, and offers a callback option to staff. - Given a completed verification, When proceeding to consent capture, Then the system logs factor match results and caller ID match status in the audit trail.
Staff-Assisted Identity Verification (Patient)
- Given a staff-assisted call, When staff verifies DOB, ZIP, and last name with the caller, Then the system permits consent capture only if at least 2 of 3 factors match and either (a) caller ID matches a number on file or (b) staff records an attestation reason from a controlled picklist. - Given staff verification, When consent is attempted with fewer than 2 matching factors and no attestation reason, Then the system blocks consent capture and logs a failed verification event. - Given a successful verification, When saving the consent, Then the staff user ID, verification method, and factor outcomes are stored with the consent record.
Guardian/Authorized Representative Dual Attestation
- Given a consent call for a minor or dependent, When the caller identifies as a guardian/authorized representative, Then the system requires capture of representative name, relationship type (from list), and confirmation that they have legal authority. - Given a guardian flow, When using staff-assisted calls, Then dual attestation is required: (a) representative self-attestation and (b) staff attestation checkbox; consent is saved only when both are present. - Given a guardian flow via IVR, When no guardian flag exists on the patient record, Then the IVR routes to staff and no consent is recorded in IVR. - Given a guardian flow via IVR with guardian flag present, When the representative provides patient DOB and ZIP that match, Then consent is permitted and the representative’s details are stored with the consent scope.
Explicit TCPA Consent Capture with Structured Scope
- Given identity verified, When the system presents the consent prompt in the selected language (minimum: English, Spanish), Then the exact TCPA-compliant wording version ID is recorded with the consent. - Given consent capture, When the patient/representative says “Yes” or presses 1, Then the recording is saved, auto-transcribed, time-stamped, and a transcript confidence score is stored; ambiguous or “No” responses result in no consent. - Given positive consent, When saving the record, Then the structured scope is bound including channels (SMS/email/voice), purposes (reminders/marketing/recalls), duration start/end or expiration rule, and practice/location IDs. - Given transcript confidence below 0.9, When saving, Then the record is flagged for human review before activation; messages are blocked until review passes.
Scope Enforcement for Messaging and Enrollment
- Given a consent record, When enrolling a patient in a campaign or sending a message, Then the system allows action only if channel and purpose are within scope and the consent is active (not expired, not revoked). - Given an out-of-scope or expired consent, When an enrollment/send is attempted, Then the system blocks the action, logs a structured error with reason code, and surfaces the block in UI/API. - Given multiple consents, When evaluating scope, Then the most recent active consent per channel/purpose/practice is used; older conflicting consents are ignored for enforcement.
Automated Re-Verification and Re-Consent Triggers
- Given a name change on the patient record, When last name no longer matches during verification, Then the system prompts for re-verification and requires staff-assisted confirmation before updating identity evidence. - Given a minor turning 18, When the patient reaches their 18th birthday, Then marketing messages are blocked and the system triggers re-consent within 30 days or before next outreach, whichever occurs first. - Given phone number reassignment checks, When the Reassigned Numbers Database flags the number as reassigned, Then SMS/voice consent tied to that number is invalidated, and re-verification and re-consent are required before further outreach.
Auditability, Evidence Persistence, and Immutability
- Given any saved consent, When retrieving the record via UI/API, Then the system returns within 3 seconds the consent scope, identity factor outcomes, caller ID match status, recording file ID, transcript, language, timestamp with timezone, staff user (if any), and consent wording version ID. - Given a saved consent, When persisting to storage, Then the recording, transcript, and consent metadata are written to an append-only ledger with a cryptographic hash; updates create a new version linking to prior hash, and original records remain immutable. - Given a compliance audit, When exporting a consent, Then the system provides a downloadable package containing evidence artifacts and an integrity hash that validates successfully.
IVR Consent Flow Builder
"As an office manager, I want to design and publish compliant consent call flows in multiple languages so that patients can easily opt in without staff involvement."
Description

Provide a no-code/low-code builder for creating TCPA-compliant IVR consent flows with versioned scripts, multilingual prompts, and adaptive branching based on DTMF or speech responses. Support text-to-speech and pre-recorded prompts, barge-in, retries, and timeouts with configurable thresholds. Enforce inclusion of mandatory disclosures and capture of an affirmative opt-in, with automated recording start/stop cues and audible recording notices. Allow dynamic variables (practice name, clinician, appointment date) and embed identity verification steps. Offer simulation, test calls, and publishing workflows with version rollback. Emit structured outcomes and metadata to the consent ledger and trigger next steps (e.g., confirmation SMS disabled/enabled based on scope).

Acceptance Criteria
Mandatory TCPA Disclosures Enforcement
Given a flow missing required TCPA disclosures, When a user attempts to publish, Then publish is blocked and the validator lists each missing/invalid disclosure with a link to the offending node. Given disclosures are present, When compared to the approved templates, Then any unauthorized edits outside allowed variables are flagged and publish is blocked until resolved. Given multiple languages are configured, When running the pre-publish checklist, Then each language shows Disclosures=Pass or explicitly identifies missing translations as Fail. Rule: Publish is permitted only if audible recording notice, TCPA purpose, data use, and revocation method are present for all enabled languages.
Affirmative Opt-In Capture & Evidence
Given the consent prompt is played, When the patient presses 1 or says an affirmative phrase (e.g., "yes", locale-specific), Then an Opt-In outcome is recorded with timestamp, call_id, version_id, scope(s), language, ASR confidence, transcript excerpt, and recording URI. Given the patient presses 2 or says a negative phrase, When the flow completes, Then an Opt-Out/Declined outcome is recorded and no messaging scopes are enabled. Given speech input is ambiguous (ASR confidence < 0.85), When consent is attempted, Then the system re-prompts up to N configured retries before marking outcome=Inconclusive. Rule: The system shall not infer consent from silence, timeout, or failure to opt out.
Multilingual Prompts with TTS/Audio and Variables
Given English and Spanish are enabled, When language selection is Spanish, Then all prompts, disclosures, and summaries play in Spanish using the selected TTS voice or uploaded audio assets. Given prompts contain {practice_name}, {appointment_date}, {clinician}, When simulated or test-called, Then variables render with provided test values and SSML is respected by the TTS engine. Given an uploaded audio asset is missing for any enabled language, When attempting to publish, Then the validator requires either a TTS fallback or the missing asset to be supplied. Rule: Mixed TTS+audio prompts shall play with seamless transitions (<250 ms gap) and volume normalized within ±2 LUFS across segments.
Adaptive Branching & Identity Verification
Given DTMF mapping 1=Yes, 2=No, When the patient presses a key, Then the flow routes to the corresponding branch and logs the digit with timestamp. Given speech input is enabled, When the patient says "yes" or locale equivalent (e.g., "sí"), Then ASR resolves to the Yes intent using the correct language model. Given timeout=5s and retries=2, When no input is detected, Then the system re-prompts up to 2 times and then routes to the fallback branch. Given identity verification requires DOB and ZIP, When the patient provides values matching EHR records, Then the flow proceeds; otherwise after 3 failed attempts it routes to staff with verification_failed=true logged. Rule: If barge-in is enabled, speaking during a prompt stops playback and input is captured; if disabled, input is ignored until prompt completion.
Recording Notice and Start/Stop Automation
Given an IVR consent call begins, When the consent segment starts, Then an audible recording notice is played before recording initiates. Given the recording start cue (beep) is emitted, When recording starts, Then it begins within 200 ms after the beep and persists through consent capture. Given the outcome node is reached, When the stop cue triggers, Then recording stops within 500 ms and excludes post-consent routing audio. Rule: In two-party consent jurisdictions for staff-assisted calls, an explicit staff confirmation of notice is required before recording can start.
Versioning, Simulation/Test, Publish, Rollback, and Audit Controls
Given a draft is saved, When changes are committed, Then a new version is created with semantic version, author, timestamp, and a diff of nodes/edges/content. Given the simulation runner is executed, When validations complete, Then a pass/fail checklist is produced covering disclosures, assets, variables, branching, retries/timeouts, and error handlers. Given a test call is initiated to a configured test number, When executed, Then the call is placed within 30 seconds and attaches recording, transcript, and outcome to the version. Given a published version exists, When rollback is requested by an authorized user, Then the previous stable version becomes active within 1 minute and the audit log records actor, timestamp, and reason. Rule: Only users with publish permissions can publish or rollback; unauthorized attempts are denied and logged.
Structured Ledger Emission & Next-Step Triggers
Given a consent outcome (Opt-In/Opt-Out/Inconclusive) is reached, When the flow completes, Then a JSON payload containing patient_id, call_id, version_id, outcome, scope, timestamps, language, verification_status, transcript_uri, and recording_uri is emitted to the consent ledger within 5 seconds. Given the ledger API is unavailable, When emission fails, Then retries occur with exponential backoff for up to 24 hours and an operational alert is raised. Given outcome=Opt-In and scope includes SMS, When the ledger acknowledges the entry, Then SMS confirmation workflows are enabled for the patient within 1 minute; if Opt-Out, all messaging scopes are disabled. Rule: For scope-limited consent (e.g., voice-only), downstream triggers enable only the permitted channels and leave others disabled.
Staff-Assisted Consent Capture
"As a patient coordinator, I want a guided way to record and document verbal consent during calls so that I can enroll patients who prefer talking to a person."
Description

Enable staff to capture TCPA consent during live calls via an in-app guided script with mandatory disclosures, language selection, and automated recording with consent tone/announcement. Log agent identity, location, and script version; prevent progression until required statements are read and affirmative responses are captured. Support warm transfer from IVR to staff when callers need assistance, and attach both segments to a single consent event. Provide desktop and mobile interfaces, headset detection, and fallback methods (upload of compliant external recordings with metadata attestation) with validation checks. Automatically post the recording, transcript, and scope to the consent ledger and update the patient record.

Acceptance Criteria
Guided Script with Mandatory Disclosures Enforcement
Given a staff-initiated consent call using the in-app script When the agent starts the consent flow Then all mandatory disclosures are presented in order and progression controls are disabled until each is read/played and acknowledged Given a required statement in the script When the agent attempts to skip, edit, or reorder it Then the UI blocks progression and logs the attempt with timestamp and agent ID Given the consent prompt is reached When the caller provides an affirmative response (e.g., “Yes”, “I agree”, DTMF 1) Then the system records the response, marks consent as Granted, and enables completion Given the consent prompt is reached When the caller provides a negative or ambiguous response Then the system records the response, marks consent as Declined, blocks enrollment actions, and requires disposition entry
Language Selection and Multi-Language Prompting
Given a staff user opens the consent flow When a language is selected (minimum supported: English, Spanish) Then all prompts, disclosures, and confirmations are displayed and played in the selected language, and the transcript language is set accordingly Given the agent changes the language mid-flow When the selection is updated Then subsequent prompts switch immediately and the ledger records both languages with their change timestamps Given transcription is generated When the transcript completes Then the transcript language matches the selected language and per-segment ASR confidence is ≥ 0.85
Automated Recording with Consent Tone and Announcement
Given a consent call is initiated When recording starts Then a consent tone/beep and “This call is being recorded” announcement play before any disclosures and are captured in the file Given recording is paused and resumed When recording resumes Then the consent tone/announcement is replayed and captured Given the call ends When the recording is saved Then the file contains continuous audio from announcement through the caller’s response under a single call/session ID
IVR Warm Transfer Attachment to Single Consent Event
Given a caller is transferred from IVR to a staff agent for consent When the transfer completes Then the IVR segment and staff-assisted segment are attached under one consent event ID with chronological timestamps Given both segments exist When the consent ledger entry is created Then it includes start/end times per segment, transfer reason, and a combined transcript in correct order Given the transfer fails or drops before consent When the session is closed Then no consent is marked Granted; the event is stored as Incomplete with diagnostics and retry link
Ledger Posting and Patient Record Update with Transcript and Scope
Given a consent session completes with an affirmative response When the agent finishes the flow Then within 10 seconds a ledger entry is created containing: recording URL, full timestamped transcript, consent scope (voice/SMS/email as selected), patient ID, and call/session ID Given the ledger entry exists When viewed by an auditor Then it displays agent identity, geolocation (city/state or coordinates when available), and script version/hash Given the ledger is posted When the patient record is refreshed Then consent status and scope are updated and available to downstream messaging rules immediately (≤ 10 seconds)
External Recording Upload with Metadata Attestation and Validation Checks
Given a compliant consent recording was captured outside the app When a staff user uploads the file Then the system requires metadata attestation (patient ID, phone number dialed, date/time, agent, script version, scope) and validates file type (WAV/MP3/MP4), duration (15s–15m), and non-silence ≥ 90% Given the upload passes file validation When transcription and keyword checks run Then required disclosures and an affirmative response are detected with confidence ≥ 0.85; otherwise the upload is rejected with actionable errors Given the upload succeeds When posting completes Then a consent event is created in the ledger linked to the patient record with Source = External Upload
Cross-Platform Interfaces and Headset Detection
Given a staff user on desktop web (Chrome/Edge) or mobile app (iOS/Android) When opening the consent flow Then the UI renders responsively with required controls, and call controls are enabled only after microphone/headset permission is granted Given an audio device is connected or disconnected When device state changes Then the app detects the change within 3 seconds, prompts device confirmation, and blocks recording if no viable input is available Given a call starts with a selected device When the session is logged Then input/output device names and IDs are recorded in the consent event and a pre-call device check is captured (test tone playback success and mic level > -36 dBFS)
Multilingual Transcription & Redaction
"As a QA/compliance manager, I want accurate, redacted transcripts that highlight consent acceptance so that I can quickly verify compliance without exposing unnecessary PHI."
Description

Deliver high-accuracy, multilingual speech-to-text with speaker diarization, confidence scoring, and phrase spotting for key consent clauses. Auto-detect language and route to the appropriate ASR model; flag low-confidence segments for human QA review before finalization. Apply policy-driven redaction to mask sensitive data (payment info, SSNs) while preserving consent evidence, and store both full and redacted transcripts with proper access controls. Extract structured entities (yes/no intent, identity responses, scope selections) for downstream automation and include ASR metrics in the ledger. Ensure all processing is HIPAA-compliant with encryption in transit and at rest.

Acceptance Criteria
Language Auto-Detection and Model Routing
- Given an inbound consent call in any supported language (EN, ES, FR, ZH), When the audio is ingested, Then the system auto-detects the primary language with ≥95% accuracy on the validation set and routes to the corresponding ASR model within 3 seconds. - Given a mixed-language call, When the minority language segment duration is ≥15 seconds, Then the system segments and routes each segment to the appropriate model; otherwise it uses the primary language model. - Given language detection confidence <0.70, When routing, Then the system falls back to a multilingual ASR model and flags the session "Language Low Confidence" for QA.
High-Accuracy Transcription with Diarization and Phrase Spotting
- Given processed audio, When transcription completes, Then word-level timestamps and confidences are present for ≥99% of words. - Given a two-party call (patient and staff/IVR), When diarization runs, Then speaker attribution achieves DER ≤12% on the domain validation set and alternations are labeled consistently (Speaker A/B or Staff/Patient). - Given consent clause lexicon, When phrase spotting runs, Then recall ≥0.98 and precision ≥0.95 for required consent clauses, and each detected clause includes start/end offsets and speaker ID. - Given supported languages, When ASR runs, Then WER ≤12% (EN), ≤15% (ES, FR), ≤18% (ZH) on domain validation audio.
Low-Confidence Segment Flagging and Human QA Gate
- Given any contiguous 3-second span with mean word confidence <0.85 or any [inaudible]/[unclear] token, When transcription completes, Then a QA task is created within 30 seconds containing the audio snippet, transcript, and context. - Given outstanding QA tasks, When ledger finalization is attempted, Then finalization is blocked until all QA tasks are resolved or waived by a user with QA_Reviewer role. - Given a QA decision (approve/edit/reject), When applied, Then the final transcript version is updated, the decision is logged with user/time/IP, and the session status changes from "Pending QA" to "Finalized".
Policy-Driven Redaction of Sensitive Data
- Given a redaction policy including SSN, payment card (Luhn-valid 13–19 digits), CVV, bank account/routing, full DOB, and email, When applied to transcripts, Then all policy-matching entities are masked as [REDACTED:<TYPE>] with 100% recall on pattern-based entities and <1% false positives on a held-out set. - Given redaction, When generating outputs, Then both full and redacted transcripts are stored; timestamps and speaker labels remain identical between versions. - Given required consent evidence phrases, When redaction runs, Then consent clauses and answers remain unmasked. - Given audit, When a redaction occurs, Then the policy version, matcher IDs, and counts per type are recorded in the ledger.
Secure Storage, Access Controls, and Encryption
- Given audio, full transcript, and redacted transcript, When stored, Then data is encrypted at rest with AES-256 and in transit with TLS 1.2+; encryption keys are rotated at least every 90 days. - Given RBAC, When a user without PHI:View:Full scope requests the full transcript, Then access is denied with HTTP 403 and the attempt is logged with user ID, time, and resource ID. - Given an authorized user, When retrieving artifacts, Then retrieval succeeds within P95 ≤ 2 seconds and access is logged; retention follows policy default ≥6 years with immutable ledger records. - Given storage, When a patient requests export, Then a packaged bundle (audio + full/redacted transcripts + ledger summary) is generated within 5 minutes.
Structured Entity Extraction for Downstream Automation
- Given the final transcript, When entity extraction runs, Then the system outputs yes/no consent intent, identity verification responses (name, DOB, phone), and scope selections with per-entity confidence and timestamps. - Given curated test data, When evaluated, Then entity extraction achieves F1 ≥0.95 for consent intent and ≥0.90 for identity and scope entities. - Given API integration, When the session finalizes, Then extracted entities are posted to the automation bus within 10 seconds in JSON schema v1.0.
Ledger Recording of ASR and Processing Metrics
- Given a finalized session, When written to the ledger, Then the record includes ASR metrics (WER, avg confidence, DER, phrase spotting precision/recall), model IDs/versions, processing durations, and a SHA-256 checksum of artifacts. - Given an integrity check, When ledger records are audited, Then any tampering is detectable via checksum mismatch and append-only sequence numbers. - Given a report request, When querying metrics by date range, Then the system returns aggregated metrics within 10 seconds with filters for language, model, and clinic.
Consent Management Dashboard & Exports
"As an office manager, I want a centralized dashboard to view, revoke, or export consent records so that I can manage compliance across all patients and providers."
Description

Provide an RBAC-secured UI to search, filter, and review consent records by patient, practice, date, channel, language, scope, status, and confidence. Enable audio playback, transcript review, and one-click generation of a consent certificate suitable for audits. Support revocation, expiration, renewal prompts, and bulk actions with guardrails. Offer scheduled exports to secure storage (e.g., SFTP/S3) and on-demand API exports with pagination and hash verification. Include full audit logs of access and changes, configurable retention policies, and alerts for upcoming expirations or missing consent for active campaigns.

Acceptance Criteria
RBAC Access Controls and Audit Logging with Retention Policies
- Given a user with role Office Manager in Practice A When they access the Consent Dashboard Then they can view only consent records belonging to Practice A - Given a user lacks the Consent.View permission When they attempt to access any consent record or API Then the UI hides consent modules and the API returns HTTP 403 with error code CONSENT_FORBIDDEN - Given a user without Consent.Export permission When they attempt to configure or run exports Then export controls are disabled in UI and the export API returns HTTP 403 - Given any read, create, update, export, or delete action on a consent record When the action completes Then an immutable audit log entry is written with fields: timestamp (UTC ISO 8601, ms precision), userId, practiceId, action, resourceType, resourceId, before/after snapshot (for mutating actions), ip, userAgent, outcome - Given an organization retention policy of 7 years is configured When a consent record or audit entry reaches its retention end Then the item is purged within 24 hours and a purge event is logged and included in purge reports downloadable by Admins - Given system timestamps are displayed When shown in UI or exports Then they are in UTC ISO 8601 format with timezone offset Z
Advanced Search and Filter Across Consent Attributes
- Given filters for patient (name or ID), practice, date range, channel (voice/SMS/email), language, scope, status, and confidence range When the user applies the filters and runs search Then the result set includes only records matching all selected filters (logical AND) and displays total count - Given a date range filter When applied Then only records with consentDate within the inclusive range are returned - Given a confidence range filter (e.g., 0.85–1.0) When applied Then only records with transcriptConfidence within that numeric range are returned - Given no records match the filters When search executes Then zero results are returned and an empty-state message is shown - Given pagination controls (page size selectable: 25, 50, 100) When the user navigates pages Then the correct records are returned for the selected page and size and the current page is reflected in the URL query
Review Audio Playback and Transcript with Time-Stamped Ledger
- Given a consent record with an audio artifact When the user clicks Play in the Consent detail view Then the audio plays in-browser with seek, play/pause, and volume controls and displays current timestamp and total duration - Given a consent record with a transcript When viewed Then the transcript is displayed side-by-side with time-stamps at least at sentence level and the transcript confidence score is visible - Given the user toggles between languages When a multi-language prompt was used Then the transcript segments are labeled by language and time-aligned - Given the audio or transcript is unavailable due to retention expiration or missing artifact When the record is opened Then the UI displays a non-blocking warning with the reason and the retention policy reference - Given the consent record When the user clicks Download Transcript Then a .txt file downloads containing the transcript text, timestamps, and record ID
One-Click Audit-Ready Consent Certificate Generation
- Given a consent record in any status (Active, Revoked, Expired) When the user clicks Generate Certificate Then a PDF file is produced within 10 seconds containing: patient identifiers (name, DOB or patientId), practice identifiers, consent scope, channel, language, status, consent date/time (UTC), transcript excerpt or reference, audio file checksum (SHA-256), record ID, and certificate ID - Given the certificate is generated When viewed Then it includes a tamper-evident hash and a verification URL/QR that returns the same hash for the certificate ID - Given the certificate is generated When the user downloads it Then a corresponding audit log entry is recorded with action GenerateCertificate and certificateId
Consent Lifecycle Management: Revocation, Expiration, Renewal Prompts and Alerts
- Given an Active consent When an authorized user clicks Revoke and confirms with a reason Then the consent status changes to Revoked, the change is time-stamped and logged, and the consent is immediately excluded from all active campaigns - Given a consent with an expiration date configured by policy When it is 30 days before expiration Then the dashboard flags the record as Expiring Soon and sends a configurable alert (email/in-app) to practice admins once per day until renewal or expiration - Given a consent reaches its expiration date without renewal When the date passes Then the status changes to Expired automatically, logged in the audit trail, and the patient is queued for renewal prompts via the configured channel - Given a renewal prompt is sent When the patient completes the Voice Consent flow successfully Then a new Active consent record is created and linked to the prior record as a renewal, and the old record remains immutable - Given an active campaign targets patients without valid consent When the campaign is scheduled Then the system generates an alert listing missing-consent patients and blocks sending to those patients by default
Bulk Actions with Guardrails and Concurrency Safety
- Given a user selects multiple consent records (up to 10,000) When initiating a bulk action (Revoke, Expire, Send Renewal Prompt) Then a confirmation modal shows the action, count, and irreversible effects and requires typed confirmation for destructive actions - Given a bulk action is submitted When processing begins Then the job runs asynchronously with a progress indicator, per-record status, and a downloadable CSV of failures including error codes - Given role and scope constraints When a bulk action includes records outside the user’s practice or permissions Then those records are skipped with a clear error and no unauthorized changes are made - Given records are modified by another user or process during the bulk job When a conflict is detected Then the system uses optimistic concurrency to prevent stale updates and logs conflict errors without aborting the entire job - Given bulk actions that would violate policy (e.g., purge before retention end) When attempted Then the action is blocked with a policy violation message and no changes are committed
Scheduled SFTP/S3 and On-Demand API Exports with Pagination and Hash Verification
- Given a practice admin configures a scheduled export When a daily schedule to S3 or SFTP is saved with valid credentials and destination path Then the system delivers export files at the scheduled time with a manifest.json containing the file list and SHA-256 checksum for each file and an overall bundle checksum - Given a scheduled export runs When it completes successfully Then an audit log entry is recorded with counts exported, destination, checksums, duration, and the manifest is uploaded alongside the data files - Given an export fails due to connectivity or auth errors When the job runs Then the system retries up to 3 times with exponential backoff and sends an alert to admins on final failure with error details - Given an on-demand API export request When called with a pageSize and cursor token Then the API returns a page of results with a nextCursor (if more data), stable ordering by lastModified, and an integrity hash for the payload; pageSize is capped at 1000 - Given any export file When a consumer computes its checksum Then it matches the checksum provided in the manifest; otherwise the file is flagged as corrupt in the export status UI
EHR/PMS Sync & Auto-Enrollment
"As an operations lead, I want consent status to sync automatically with our scheduling systems so that patients receive only the communications they agreed to."
Description

Integrate consent outcomes with practice management/EHR systems to update patient communication preferences, flags, and consent timestamps via APIs, HL7, or FHIR where available. On successful consent, auto-enroll patients into the correct SMS/email/voice reminder programs per scope; on revocation or expiry, immediately suppress outreach and propagate changes to all downstream systems. Publish webhooks and events for real-time workflows, implement retry/idempotency for reliability, and provide mapping tools for multi-location practices. Monitor for number recycling signals and trigger re-consent flows when risk indicators appear.

Acceptance Criteria
Successful Consent Sync Updates EHR/PMS and SmileCue Enrollment
Given a patient completes Voice Consent with status = Consented, scope = [channels], and timestamp T When the consent outcome event is processed Then the linked EHR/PMS record is updated within 60 seconds to set preferences for the scoped channels to true and to persist consent_timestamp = T and consent_source = "Voice Consent" And the patient is auto-enrolled into the mapped reminder programs for the scoped channels with start state = Active And the operation is idempotent: reprocessing the same outcome (same externalPatientId + outcomeId/version) does not create duplicate enrollments or additional writes And an audit log entry is created with patient identifiers, previous values, new values, source, and correlationId
Immediate Suppression on Revocation or Expiry and Downstream Propagation
Given a patient’s consent status becomes Revoked or Expired When the consent change is processed Then all outbound SMS/email/voice outreach is suppressed within 60 seconds and any queued messages for the patient are canceled And the EHR/PMS preferences are updated to reflect opt-out for affected channels with consent_timestamp set to the revocation/expiry time And a suppression event is emitted to subscribers and an audit trail entry is recorded And re-enrollment requires a new positive consent event
HL7/FHIR/API Field Mapping Per Location with Validation
Given a practice has configured per-location field mappings for EHR/PMS integration (API/HL7/FHIR) When a consent outcome is generated for a patient at location L Then the system writes to the destination fields defined for L and does not write to fields configured for other locations And unmapped required fields are blocked with a validation error and do not attempt transmission And a mapping test mode allows sending a synthetic consent to verify writes before enabling production
Webhook Events with Real-Time Delivery, Retry, and Idempotency
Given a consent status changes for a patient When the event is published Then a webhook is delivered within 30 seconds containing eventId, version, patientId, status, scope, timestamp, and locationId And delivery is at-least-once with exponential backoff retries for up to 24 hours on 4xx/5xx configurable codes And receivers can deduplicate using eventId; duplicate deliveries contain identical payloads and signature And each webhook is HMAC-signed; signature verification passes with the shared secret
Number Recycling Risk Detection and Automated Re-Consent Flow
Given the system detects one or more number-recycling risk signals for a patient’s mobile (e.g., carrier recycle flag, line-type change, CNAM mismatch, 10DLC recycled/NACK code, or 90+ days inactivity) When the risk score exceeds the configured threshold Then SMS outreach is suppressed for that number and a re-consent Voice flow is triggered within 24 hours And the EHR/PMS is updated with a risk flag and last_verified timestamp And upon successful re-consent, suppression is lifted and the risk flag is cleared; upon failure or timeout, suppression remains
Conflict Resolution with Deterministic Precedence Rules
Given EHR/PMS and SmileCue contain conflicting consent states for the same patient When a new consent outcome with timestamp T is processed Then the configured precedence rule is applied (default: latest timestamp wins); the final state is written to both systems And the decision rationale (rule applied, sources, timestamps) is recorded in the audit log And the operation is idempotent and repeatable, producing the same final state on reprocessing
Operational Monitoring, SLAs, and Recovery for Sync Pipeline
Given the consent sync pipeline is operating under normal load When consent outcomes are processed Then p95 end-to-end propagation to EHR/PMS and enrollment/webhooks is ≤ 60 seconds and p99 is ≤ 5 minutes And failures > 1% over any 15-minute window trigger alerts to on-call with error samples and affected tenants And dead-letter queues capture unrecoverable messages with replay tooling to reprocess after fix And dashboards expose counts, latency percentiles, retry rates, and suppression/enrollment changes per location

Risk Heatmap

A color-coded schedule view that highlights predicted no-show risk by slot, provider, and location in real time. Quickly filter by appointment type or daypart and apply bulk actions (e.g., advance outreach, voice fallback) to protect vulnerable blocks. Staff instantly see where to focus to keep chairs full with less manual scanning.

Requirements

Real-time Risk Scoring Service
"As an office manager, I want live no-show risk scores on my schedule so that I can intervene early and keep chairs full."
Description

Computes and refreshes predicted no-show risk for each scheduled appointment in near real time, producing a 0–100 score and Low/Medium/High bands per appointment, provider, and location. Ingests appointment metadata, patient engagement signals (message opens, confirmations, prior attendance), practice constraints, and optional external signals (weather, traffic by ZIP). Exposes a read-optimized API and data stream consumed by the Heatmap view and automation services, with update latency under 5 seconds for changes like new confirmations, reschedules, or cancellations. Includes model versioning, feature gating, safe defaults when the model is unavailable, and HIPAA-compliant data handling with minimum necessary fields.

Acceptance Criteria
Sub-5s Update on Confirmation/Reschedule/Cancellation
Given an existing scheduled appointment with a current risk score When a patient confirmation, reschedule, or cancellation event is ingested by the service Then 99% of corresponding risk updates are computed and available via API and event stream within 5 seconds of event receipt, and 100% within 10 seconds And the updated score and band are persisted with a new updated_at timestamp and emitted exactly once per change (allowing at-least-once delivery with idempotent event_id) And downstream consumers (Heatmap, automation) can retrieve the new values without manual refresh
Score Range and Risk Band Mapping
Given band thresholds configured for the practice as Low: 0–39, Medium: 40–69, High: 70–100 (defaults) unless overridden When the service computes a score for any appointment Then the score is an integer between 0 and 100 inclusive And the band is assigned deterministically based on the configured thresholds And if custom thresholds are set (e.g., Low: 0–29, Medium: 30–74, High: 75–100), the band reflects the custom configuration within 1 minute of change And missing features default to neutral values that do not produce High risk by default
Read-Optimized Risk API Contract and Performance
Given a client requests GET /v1/risk/appointments/{appointment_id} When the appointment exists Then the API responds 200 within p95 ≤ 300 ms (payload ≤ 2 KB) under 100 RPS and returns: appointment_id, score, band, model_version, featureset_version, provider_id, location_id, updated_at, source={model|fallback} And when the appointment does not exist, the API responds 404 with no PHI in the body And when requesting a time-window query (provider_id, location_id, start_at, end_at), the API returns all matching appointments with pagination and p95 ≤ 500 ms for pages ≤ 200 items
Risk Event Stream for Heatmap and Automation
Given the risk event stream topic risk.scores.v1 is available When any appointment risk is created, updated, or deleted Then an event is published with type in {upsert, delete}, appointment_id, score, band, model_version, featureset_version, provider_id, location_id, updated_at, event_id, event_time And events for the same appointment_id are ordered by updated_at and carry a monotonically increasing sequence And delivery is at-least-once with consumer-deduplication via event_id And 99% of events are available to consumers within 5 seconds of source change, 100% within 10 seconds
Model Versioning and Practice-Level Feature Gating
Given multiple model versions are deployed and tagged (e.g., v1.3.0, v1.4.0) When a practice is assigned to a model_version via feature flag Then all scores produced for that practice include the assigned model_version and featureset_version in API and stream within 1 minute And rolling back to the prior version restores previous scoring behavior within 1 minute And feature gates allow enabling/disabling external signals (weather, traffic) per practice with changes taking effect within 5 minutes and reflected in featureset_version
Safe Defaults and Degradation on Model Unavailability
Given the scoring model is unreachable or unhealthy for more than 30 seconds When a risk computation is requested Then the service returns source=fallback with score=50 and band=Medium, and emits a fallback flag in API and stream And once the model is healthy, all affected appointments are recomputed within 60 seconds and fallback flags are cleared And no High band is produced from fallback mode And service uptime for fallback responses is ≥ 99.9% independent of model health
HIPAA Minimum Necessary and Security Controls
Given any API or stream response from the service When inspecting payloads and logs Then no PHI/PII such as patient name, phone, email, DOB, address, message body, or free-text notes is present And only minimum necessary identifiers are present: appointment_id, provider_id, location_id, time window metadata, and aggregated engagement signals (no message content) And all data in transit uses TLS 1.2+ and requests require service-to-service authentication with scoped tokens; unauthorized access returns 401/403 without leaking identifiers And audit logs record access without storing PHI and retain for ≥ 90 days
Heatmap Calendar Visualization
"As a scheduler, I want a color-coded schedule that highlights risky slots so that I can quickly see where to focus my outreach."
Description

Delivers a color-coded schedule view that maps risk scores to an accessible palette across day, week, and provider/location grids. Displays a legend, tooltips with score, band, top contributing factors, appointment details, and quick actions. Supports drill-down to the appointment record, responsive layout for desktop/tablet, and performant rendering for multi-location practices up to six weeks of data. Ensures WCAG 2.2 AA contrast and colorblind-safe palettes, with graceful degradation when scores are unavailable.

Acceptance Criteria
Risk Color Mapping Across Day/Week/Provider/Location Views
Given appointment slots have risk scores from 0–100 When the calendar is viewed in Day, Week, or Provider/Location grid views Then each slot’s background color corresponds to its risk band per the defined palette And the same color mapping and band thresholds are applied consistently across all views And the legend reflects the exact bands and colors shown on the calendar And updates to a slot’s risk score are reflected in the view within 60 seconds without requiring a full page reload
Legend, Tooltip, and Quick Actions Disclosure
Given a visible appointment slot in the heatmap When the user hovers with a mouse or focuses the slot via keyboard Then a tooltip appears within 300 ms and stays visible while the slot remains focused/hovered And the tooltip shows: numeric risk score, risk band label, top contributing factors (max 3), appointment details (time, type, provider, location) And the tooltip provides quick actions including Advance Outreach and Voice Fallback when those actions are enabled for the practice And selecting a quick action confirms initiation within 1 second and updates the UI state without navigating away
Drill-Down to Appointment Record
Given a user has permission to view appointment details When the user clicks a slot or presses Enter/Space on a focused slot Then the application navigates to the appointment record within the same app context in under 1 second on a broadband connection And returning to the calendar restores the prior view (date range and grid mode)
Responsive Layout for Desktop and Tablet
Given the app is viewed on desktop (≥1280px width) or tablet (768–1279px width) When the user loads the heatmap calendar Then the grid, legend, and tooltips render without horizontal scrolling in supported breakpoints And interactive targets in tablet view are at least 44x44 px and respond to touch And orientation changes (portrait/landscape) reflow content without truncating critical labels or overlapping cells
Performance at Six-Week Multi-Location Scale
Given up to six weeks of data across multiple locations and providers (up to 3,000 appointments in view) When the user loads the heatmap calendar Then the initial render completes in ≤2.5 seconds on a modern desktop over broadband And switching between Day/Week/Provider/Location views completes in ≤500 ms And memory usage for the calendar view remains under 400 MB during typical interaction
Accessibility: WCAG 2.2 AA and Colorblind-Safe Palette
Given WCAG 2.2 AA requirements When the heatmap calendar, legend, and tooltips are rendered Then all text meets ≥4.5:1 contrast ratio and interactive components meet ≥3:1 And color is not the sole means of conveying risk; band labels and patterns or icons are provided in tooltips/legend And the color palette remains distinguishable under Deuteranopia, Protanopia, and Tritanopia simulations And all slots, legend items, and quick actions are reachable via keyboard with visible focus and correct reading order for screen readers
Graceful Degradation for Missing or Stale Risk Scores
Given a slot has no available risk score or the score fetch fails When the calendar renders the slot Then the slot displays a neutral style distinct from risk bands and includes a tooltip message indicating 'Score unavailable' And the legend includes an entry for 'No score' And calendar performance and navigation are unaffected; other slots continue to display normally And quick actions that depend on a risk score are disabled with an explanatory message
Advanced Filters & Saved Views
"As a front desk coordinator, I want to filter the schedule by high-risk hygiene appointments this morning so that I can prioritize outreach efficiently."
Description

Enables filtering the heatmap by risk band, provider, location, appointment type, operatory, daypart, date range, and confirmation status, with multi-select and combinable criteria. Provides quick presets (Today, Next 3 Days, This Week), per-user saved views with default view settings, and role-based visibility of PHI in filter results. Includes fast counts per filter, keyboard navigation, and stateful URLs for shareable, permissioned links.

Acceptance Criteria
Multi-Select, Combinable Filters with Fast Counts
- Given a user on the Risk Heatmap, when they select multiple values within a single dimension (e.g., providers A and B), then the results include the union of those values for that dimension. - Given selections across multiple dimensions (e.g., provider, location, risk band), when filters are applied, then the results reflect the intersection across dimensions. - Given filter options display fast counts, when any filter selection changes, then option counts update to reflect the prospective result if that option is added, and counts match the actual results when applied. - Given a dataset of at least 5,000 future appointments, when a single filter is added, removed, or changed, then visible results and fast counts update within 1.0 seconds at the 95th percentile and within 300 ms at the median. - Given no results match the current filters, when the view renders, then a zero-state message is shown and a one-click "Clear all filters" action is available. - Given the user clicks "Clear all filters", when executed, then all filters reset to system defaults and full results are displayed.
Quick Presets for Date Range (Today, Next 3 Days, This Week)
- Given the user selects the Today preset, when applied, then appointments from 00:00 to 23:59 in the practice timezone for the current calendar day are included. - Given the user selects the Next 3 Days preset, when applied, then appointments from now through 23:59 three calendar days ahead in the practice timezone are included. - Given the user selects the This Week preset, when applied, then appointments from the practice-configured week start through the practice-configured week end of the current week are included (default Monday–Sunday). - Given any preset is selected, when combined with other filters (e.g., risk band, provider), then the preset acts as the date range dimension within the intersection logic. - Given a preset is active, when the URL is copied, then the active preset is encoded in the URL and restored when visited. - Given the calendar day changes (midnight local), when the page is reloaded, then the preset recomputes relative to the new current day.
Per-User Saved Views and Default View
- Given the user has an active filter configuration, when they save a view with a unique name, then the exact filter state (including presets and sort) is saved to their profile and visible only to that user. - Given multiple saved views exist, when the user selects a saved view, then the heatmap loads with the exact saved state and the view name is indicated as active. - Given a saved view is set as Default, when the user signs in or reloads the heatmap, then the default view loads automatically. - Given the user renames or deletes a saved view, when confirmed, then the change is persisted and reflected across sessions and devices; deleting the default view promotes the system default until another default is set. - Given a saved view includes filters for entities that no longer exist (e.g., a removed provider), when the view is loaded, then unavailable filters are ignored, remaining filters are applied, and the user is notified non-blockingly. - Given network loss during save, when connectivity returns, then the user can retry save and no duplicate views are created.
Keyboard Navigation of Filters and Saved Views
- Given focus starts in the filter panel, when the user presses Tab/Shift+Tab, then focus moves in a logical order matching the visual layout without trapping. - Given a multi-select list is open, when the user presses Arrow keys, then focus moves between options; Space toggles selection; Esc closes the list and returns focus to the trigger. - Given the user types characters while a list is open, when options exist, then typeahead focuses the next matching option by label. - Given an action is available (Apply/Clear/Save View), when focused, then Enter activates it. - Given any interactive element is focused, when rendered, then a visible focus indicator is present with at least 3:1 contrast. - Given all filter and saved view actions, when tested, then they are operable end-to-end using keyboard only (no mouse).
Stateful, Shareable URLs with Permissions
- Given a filter state is active, when the user copies the page URL, then the URL encodes the complete state (all selected filters, presets, sort) without including PHI values. - Given a recipient with sufficient permissions opens the URL, when loaded, then the heatmap restores to the exact encoded state. - Given a recipient lacks required permissions for any portion of the state (e.g., a location), when loaded, then restricted elements are omitted, a non-blocking access message is shown, and no PHI is revealed. - Given the URL query string is tampered (unknown/invalid values), when loaded, then the system validates inputs, ignores invalid keys, and safely falls back without error. - Given the URL is generated in one supported browser, when opened in another supported browser, then the state restoration behaves identically.
Role-Based PHI Visibility in Filter Results
- Given a user without PHI permission views the heatmap, when results are shown, then patient-identifying fields are masked or omitted while aggregate counts and risk coloring remain accurate. - Given a user with PHI permission views the same filtered results, when compared, then counts, risk bands, and placement are identical; only PHI visibility differs. - Given network responses powering the heatmap, when the requesting user lacks PHI permission, then PHI fields are not returned in the payload. - Given a shared stateful URL is opened by a user without PHI permission, when loaded, then PHI remains hidden regardless of the sharer’s permissions.
Accurate Filter Semantics (Risk Band, Confirmation Status, Daypart, Timezone)
- Given the risk band filter, when one or more bands (Low, Medium, High) are selected, then appointments in the selected bands are included (union within dimension). - Given the confirmation status filter, when statuses (e.g., Confirmed, Unconfirmed, Declined, Rescheduled, No Response) are selected, then appointments whose latest status matches any selected value are included. - Given daypart filters, when Morning, Afternoon, or Evening is selected, then appointments starting within 07:00–11:59, 12:00–16:59, or 17:00–20:59 respectively in the practice timezone are included. - Given any date range, when appointments fall on DST transition days, then inclusion is computed in the practice timezone with correct hour boundaries. - Given provider, location, and operatory filters, when opened, then all available options for the current date range are listed and searchable by name/label.
Bulk Risk Mitigation Actions
"As a practice manager, I want to apply proactive outreach to all high-risk slots tomorrow so that we reduce same-day no-shows without manual one-by-one work."
Description

Allows staff to select individual slots or filtered sets and apply predefined actions such as triggering advance outreach sequences, switching to voice fallback, increasing reminder cadence, requiring double-confirmation, or proposing controlled overbooking with guardrails. Integrates with SmileCue’s messaging workflows and templating, shows a preview of recipients and expected send volume, enforces rate limits and quiet hours, and supports undo/rollback. All actions respect permissions and are logged for compliance.

Acceptance Criteria
Bulk Actions on Filtered High-Risk Slots
Given I apply heatmap filters (risk ≥ 0.7, appointment type = Hygiene, location = Downtown, daypart = AM) and select all resulting slots, When I choose the "Advance Outreach Sequence A" bulk action, Then a confirmation modal displays selected slot count, unique patient count, and action summary. Given I confirm, When the action executes, Then 100% of eligible patients in selected slots are enqueued and ineligible patients are excluded with machine-readable reason codes (opt-out, invalid contact, quiet hours, permission). Given exclusions occur, When execution completes, Then success, skipped, and failed counts equal the number of targeted patients and are shown in the post-action report. Given I select "Switch to Voice Fallback", "Increase Reminder Cadence (+1/day)", or "Require Double-Confirmation", When I apply, Then the corresponding flags are persisted and visible in appointment details within 5 seconds.
Recipient Preview and Send Volume Estimation
Given I select any bulk action, When the preview panel opens, Then it lists recipient identifiers, channels to be used, per-channel counts, and estimated send volume by hour/day respecting current rate limits. Given I expand a recipient, When viewing the preview, Then I see the exact workflow steps and templates to be used with placeholders resolved using current data and PHI masked per my role. Given I change filters or selections, When the selection is updated, Then preview counts and recipient lists update within 2 seconds and final execution counts deviate by no more than 1% excluding last-minute eligibility changes.
Rate Limits and Quiet Hours Enforcement
Given org SMS rate limit = 600/hour and quiet hours = 20:00–08:00 local, When I initiate a bulk send of 900 SMS at 19:55, Then up to 50 SMS send before 20:00 and the remaining 850 are deferred and time-sliced to resume at 08:00, with planned send times displayed. Given multiple channels are included, When scheduling, Then per-channel limits are enforced independently and no channel exceeds its configured rate limit. Given any message would violate quiet hours without override, When scheduling, Then those messages are deferred with status "Deferred: Quiet Hours" and visible expected send time. Given I have override permission and provide a reason, When I enable quiet hours override, Then the system logs the override and still blocks sends where policy forbids overrides.
Permissions and Compliance Logging
Given my role lacks Bulk Mitigation permission, When I open the bulk actions menu, Then bulk actions are hidden or disabled with an "Insufficient permissions" tooltip. Given I have permission, When I execute any bulk action, Then an immutable audit log entry is created capturing actor, timestamp, source IP/device, filters, slot IDs, patient IDs, action parameters, template/workflow IDs, counts, overrides, and outcomes. Given I am an auditor, When I search audit logs by date range and actor, Then I can retrieve the specific bulk action entry and export a CSV that excludes PHI fields per policy. Given HIPAA security requirements, When logs are stored and transmitted, Then PHI is minimized and all records are encrypted in transit and at rest according to org standards.
Undo and Rollback of Bulk Actions
Given a bulk action completed within the last 15 minutes and messages remain in queued state, When I click Undo, Then queued messages are canceled, appointment flags are reverted, and outreach tasks removed with ≥99% success on eligible items. Given some messages were already delivered, When I Undo, Then delivered messages are not recalled; compensating notes are logged and follow-up workflows suppress duplicates. Given rollback completes, When I open the post-action report, Then I see counts of reverted, not reverted with reason codes, and items requiring manual follow-up.
Workflow and Template Validation
Given I select an Advance Outreach workflow, When I open the preview, Then the system validates that all steps reference active templates for each recipient's preferred language and channel; missing variants are flagged and block execution. Given templates include placeholders (e.g., {{provider_name}}, {{appointment_time}}), When I preview, Then all placeholders resolve without unresolved tokens; invalid tokens cause a blocking error with the exact template step identified. Given an SMS step contains disallowed PHI, When validation runs, Then that step is blocked for SMS with a warning and suggested compliant channel alternatives.
Controlled Overbooking with Guardrails
Given a time block has average no-show probability ≥ 0.35 and provider/resources allow, When I choose Propose Overbooking, Then the system suggests up to N additional holds such that expected utilization ≤ 100% at 95% confidence. Given scheduling constraints (provider, room, equipment, location) and policies, When I accept the proposal, Then holds/overbook flags are created without violating constraints and manager approval is required if policy dictates. Given double-confirmation is required for overbooked patients, When outreach is sent, Then appointments remain tentative until two distinct confirmations occur within the configured window; otherwise holds expire at the cutoff time. Given a proposal would breach capacity or clinical rules, When I attempt to proceed, Then the action is blocked and specific guardrail violations are displayed.
Threshold Alerts & Day-of Escalations
"As a lead hygienist, I want alerts when my afternoon block exceeds a high-risk threshold so that I can adjust staffing and start outreach immediately."
Description

Provides configurable alert thresholds by provider, location, and daypart that notify staff when risk density exceeds set levels. Delivers in-app badges, morning digests, and real-time alerts via email/push for urgent cases, with snooze, quiet hours, and escalation routing to on-call roles. Links alerts directly to the filtered Heatmap view and recommended next actions, with acknowledgement tracking.

Acceptance Criteria
Provider-Level Risk Threshold Alert
Given provider "Dr. Lee" has a risk threshold of 65% configured and monitoring is active And at least one upcoming slot within the next 48 hours for Dr. Lee has predicted no-show risk >= 65% When the first slot crosses the configured threshold Then an alert is generated within 60 seconds with an in-app badge and notifications via the configured channels (email, push) containing provider, time window, current risk value, and threshold And duplicate alerts for the same provider and threshold condition are suppressed for 10 minutes unless the risk increases by >= 10 percentage points And the in-app alert badge count increments by 1
Location-Level Morning Risk Digest
Given a daily digest time of 07:30 is configured for Location "Downtown" And location-level thresholds for risk density by daypart are configured When it is 07:30 on a working day in the location’s time zone Then a single email digest is sent to the "Front Desk" distribution containing only locations/dayparts where risk density exceeds thresholds And the digest lists up to the top 5 vulnerable blocks by start time with risk %, provider, chair count, and recommended next actions, excluding any patient PHI And if no thresholds are exceeded, the digest subject includes "No elevated risk today" and the body contains zero items
Daypart Quiet Hours Enforcement
Given quiet hours of 20:00–07:00 are configured for all non-urgent alerts And an alertable risk event occurs at 22:15 When the alert is generated Then delivery to email/push is suppressed and the event is queued with reason "Quiet Hours" And a summary notification is delivered at 07:00 listing the count of queued events and highest severity And alerts marked with "Override quiet hours" are delivered immediately despite quiet hours
Real-Time Escalation Routing to On-Call
Given escalation routing assigns "On-Call Coordinator" as primary and "Office Manager" as secondary for Location "Downtown" And a critical threshold of 85% is configured for the next-3-hours window When risk density >= 85% is detected for any block starting within the next 3 hours Then an urgent alert is sent to the primary via push and email simultaneously with an "Urgent" designation And if the alert is unacknowledged for 5 minutes, it escalates to the secondary with an escalation note referencing the primary And once any assignee acknowledges, further escalations for that event cease
Snooze and Re-notification Logic
Given a recipient opens an alert and selects Snooze for 30 minutes with reason "calling patients" When 30 minutes elapse And the underlying risk condition remains true Then the alert re-notifies the original recipients with the prior snooze reason preserved in alert history And no notifications are sent to those recipients during the snooze window for that alert And if the condition has cleared during the snooze, the alert auto-resolves with status "Cleared - no re-notify"
Alert Deep Link to Pre-Filtered Heatmap
Given an elevated risk alert exists for Provider "Dr. Lee" at Location "Downtown" during Daypart "AM" When the user clicks "View in Heatmap" from the alert Then the Heatmap loads within 2 seconds pre-filtered to Provider=Dr. Lee, Location=Downtown, Daypart=AM, Risk State=Elevated And the Recommended Actions panel opens with context-aware options enabled And using the browser/app back navigation returns the user to the prior alert list
Acknowledgement Tracking and Audit Log
Given an alert has multiple recipients When user "Sam" taps Acknowledge in-app Then the alert shows acknowledged=true with user, timestamp, and channel in alert details And the alert moves to the "Acknowledged" filter for all recipients and is removed from "Unacknowledged" And an exportable audit log entry is created capturing event ID, recipients, delivery channels, acknowledger, timestamps, and escalation hops
Role-Based Access & PHI Safeguards
"As a compliance-minded administrator, I want risk visibility tailored to staff roles so that we protect PHI while enabling effective action."
Description

Implements granular permissions controlling who can view risk scores, patient identifiers, and perform bulk actions, with role templates for dentist, hygienist, office manager, and front desk. Obfuscates PHI in the heatmap for limited roles (e.g., initials only) and reveals details on demand for authorized users. Enforces session timeouts, encryption in transit/at rest, minimum-necessary data exposure, and environment-specific configs to maintain HIPAA compliance.

Acceptance Criteria
Limited Role Sees Obfuscated PHI in Heatmap
- Given a user with Front Desk or Hygienist role viewing the Risk Heatmap, when the schedule loads, then patient identifiers are displayed as first-initial + last-initial only (e.g., "J D"). - Phone numbers, email addresses, DOB, and full names are not displayed or retrievable via UI elements, tooltips, or exports for these roles. - Risk scores, appointment time, provider name, location, and appointment type remain visible. - Network/API responses for these roles exclude full name, phone, email, DOB, and notes fields. - Attempting to access restricted fields returns HTTP 403 with no PHI in the response body.
Authorized Role Reveals Patient Details on Demand
- Only Dentist and Office Manager roles see the "Reveal Details" control on heatmap slots. - When an authorized user clicks "Reveal Details," full name, phone, email, and appointment notes are displayed in the slot panel. - Details auto-remask after 60 seconds of no interaction or immediately upon panel close or navigation away. - Non-authorized roles do not see the control and cannot reveal details; server responds 403 to reveal attempts from these roles.
Bulk Actions Restricted by Role and Scope
- Only Dentist and Office Manager roles see and can initiate bulk actions (e.g., advance outreach, voice fallback). - Bulk actions are limited to the user’s assigned locations and providers; attempts beyond scope are blocked with 403 and zero changes applied. - A pre-confirmation summary displays the count of impacted appointments and targeted criteria before execution. - Front Desk and Hygienist roles see controls disabled or hidden, and API denies bulk action requests with 403.
Session Timeout and Re-authentication
- User sessions auto-lock after 15 minutes of inactivity across the web app. - Accessing any PHI (e.g., using "Reveal Details") after auto-lock requires re-authentication via the configured IdP. - "Reveal Details" and bulk action endpoints require a session active within the last 5 minutes; otherwise respond 401 prompting re-login. - A visible 60-second countdown warning is shown before auto-lock on active PHI-capable views.
Encryption in Transit and at Rest
- All app endpoints enforce TLS 1.2+ with valid certificates; HSTS is enabled with a max-age ≥ 6 months and includeSubDomains. - Datastores containing PHI (primary DB, search indices, backups, snapshots) use AES-256 encryption at rest with managed KMS keys. - PHI is not written to client-side storage (localStorage, sessionStorage) or plaintext application logs; attempts to log PHI are blocked in CI. - TLS certificates and KMS keys are rotated at least every 90 days (certs) and per policy for keys; evidence of last rotation is recorded.
Minimum Necessary Data Exposure
- Heatmap API defaults to returning only risk score, slot start/end, provider name, location, appointment type, and patient initials. - Full patient identifiers and contact information are returned only when a valid, short-lived reveal token is presented by authorized roles. - Export/download endpoints omit PHI for limited roles and require explicit PHI scopes for authorized roles; over-broad field requests are rejected with 400. - UI prevents copying of PHI by limited roles (no copy affordance), and API enforces the same constraints irrespective of client behavior.
Environment-Specific PHI Configurations
- Production is the only environment permitted to process real PHI; staging/dev return synthetic or obfuscated values regardless of role. - Patient outreach (SMS/email/voice) bulk actions are disabled in non-production; attempts are blocked server-side. - Environment-specific settings are sourced from secure configuration (e.g., env vars, secrets manager); values cannot be overridden from the client. - Cross-environment calls from non-production frontends to production PHI APIs are blocked via CORS and network controls.
Audit Trail & Effectiveness Reporting
"As a practice owner, I want to see how interventions driven by the heatmap affected confirmations so that I can justify workflows and optimize staffing."
Description

Captures immutable logs of risk scores, model versions, bulk actions, automated outreach triggers, user acknowledgements, and resulting attendance outcomes with timestamps and actors. Provides exportable reports and dashboards showing confirmation rates, no-show reduction, intervention effectiveness by action type, and trends by provider/location. Supports retention policies, data subject requests, and reproducibility of what was seen and sent at any point in time.

Acceptance Criteria
Immutable Audit Log for Risk and Outreach Events
Given any of the following events occur: risk score calculated/updated, bulk action executed, automated outreach triggered, user acknowledgement recorded, or attendance outcome recorded When the event is committed Then an append-only audit entry is created with fields: event_type, event_id, appointment_id, patient_id_hash, provider_id, location_id, timestamp_utc (ISO 8601), actor_id, actor_type (system/user), model_version (if applicable), previous_value (if applicable), new_value (if applicable), parameters (JSON), correlation_id And the entry is tamper-evident via a hash chain linking to the previous entry And attempts to update or delete an existing entry are rejected and the attempt is logged as a separate audit event And the entry is retrievable by appointment_id and correlation_id via API and UI search within the same business day
Reconstruct Historical View and Messages at a Point in Time
Given a timestamp T and an appointment_id (or provider_id plus date/time slot) When a user with role Office Manager requests Reconstruct View for T Then the system returns the risk score, risk tier/color, thresholds, and model_version as of T And returns the heatmap cell state and any flags shown to staff as of T And returns the exact message templates, channels, personalization values, and bodies that were sent as of T And returns the outreach trigger reason and decision path And the response includes references to the underlying audit entry IDs used for reconstruction And replaying the same inputs through the reconstruction API yields identical outputs
Dashboard for Confirmation and No-Show Metrics by Provider/Location
Given a selectable date range and filters (provider, location, appointment type, daypart) When the dashboard is loaded Then it displays metrics: confirmation_rate (%), no_show_rate (%), show_rate (%), total_appointments (count) And it displays trend lines at daily or weekly granularity matching the selected range And it supports drill-down from any aggregate to a filtered appointment list with filters preserved And metric values match a reference SQL query against the reporting dataset within ±0.1 percentage points for the same filters
Intervention Effectiveness by Action Type with Control Comparison
Given action types (advance_sms, voice_fallback, email_second_touch, manual_call) and a designated control cohort for the date range When the effectiveness report is generated Then for each action type it computes: treated_confirmation_rate, control_confirmation_rate, lift_percentage = treated − control, treated_n, control_n And rows where treated_n < 30 or control_n < 30 are excluded or clearly flagged as insufficient sample And the report supports stratification by provider and location via filters And exported values for a validation dataset match hand-calculated results within rounding tolerance
Exportable Audit and Outcomes Report
Given an authorized user (Compliance Admin or Practice Owner) and a date range When the user requests an audit export Then the system generates a CSV with columns: audit_entry_id, event_type, appointment_id, patient_id_hash, provider_id, location_id, timestamp_utc, actor_type, model_version, risk_score, risk_tier, action_type, message_channel, template_id, delivery_status, user_ack_flag, attendance_outcome And the file name follows the convention: smilecue_audit_YYYYMMDD_to_YYYYMMDD_<practice_id>.csv with an accompanying SHA-256 checksum file And the dataset contains only the minimum necessary information (no names, phone numbers, or message free text containing PHI) And completion of the export is logged as an audit event with requester identity and export scope
Retention Policies and Patient Data Access Requests
Given configured retention settings for audit logs and communications artifacts and an optional legal hold When data exceeds its retention period without an active legal hold Then the system purges the data and records a purge audit event including counts and scope And when a legal hold is active, the data is retained until the hold is lifted and the release is audited And given a verified patient access request for a date range When an authorized user executes the request Then the system produces a patient-centric export of communications, risk scores at time of send, actions taken, and attendance outcomes in human-readable PDF and machine-readable CSV within 15 minutes And the export includes model_version and risk_score values but excludes internal model parameters and non-essential PHI And both the request and fulfillment are captured in the audit trail

Score Explain

Transparent, human-readable reasons behind each risk score (e.g., prior attendance pattern, booking lead time, channel responsiveness, weather/commute signals, guardian involvement). Includes a next-best-action tip for each slot, building trust in the model, speeding decisions, and supporting audit-readiness for compliance leads.

Requirements

Real-time Score Explanation Engine
"As an office manager, I want clear, plain-language reasons behind each no-show risk score so that I can understand the drivers and make informed scheduling decisions."
Description

Generate deterministic, human-readable explanations for each no-show risk score by translating top contributing factors into plain-language reason statements with directionality and relative impact (e.g., increases/decreases risk, high/medium/low). Output both structured JSON (reasons, weights, confidence, reason codes) and a concise narrative. Maintain a mapping from model features to patient-friendly labels, exclude protected attributes, and enforce HIPAA-safe phrasing. Support multiple model versions with reproducible outputs and version tagging. Handle missing or stale signals gracefully and indicate data sufficiency. Provide localization-ready templates and unit-tested templates for clarity and consistency. Integrate with the existing scoring pipeline and event bus to produce explanations on score creation and update.

Acceptance Criteria
Deterministic Explanations with Version Tagging
Given a fixed input score request with a specified model_version and explanation_version When the engine generates explanations twice within the same environment Then the structured JSON and narrative outputs are byte-identical, including key order and numeric precision to 4 decimal places. Given a score request without explicit model_version When processed Then the output includes the active model_version and explanation_version fields and they match system configuration at time of scoring. Given the same inputs across environments with the same model and explanation versions When processed Then reason codes, ranks, directions, and weights are identical; any randomness is seeded by the score_id to ensure determinism.
Structured JSON and Narrative Schema Compliance
Given a score created event When processed Then the engine emits a JSON object with fields: score_id, patient_id (hashed), model_version, explanation_version, created_at (ISO-8601 UTC), reasons[], confidence (0..1), data_sufficiency, narrative, locale, and trace_id. Given reasons[] When populated Then each item contains: reason_code (string), label (patient-friendly), direction (increases|decreases|neutral), impact (high|medium|low), weight (number -1..1), rank (1..N), and source_feature. Given narrative When generated Then it is <= 240 characters, plain text (no HTML), and references no more than the top 3 reasons. Given the output When validated against the JSON schema Then validation passes; otherwise the event is not published and an error is logged with trace_id.
Protected Attribute Exclusion and HIPAA-Safe Phrasing
Given any generated explanation When inspected Then no protected class attributes (race, religion, sexual orientation, gender identity, disability status, ethnicity, citizenship) are referenced in labels, narratives, or reason codes. Given any generated explanation When inspected Then no diagnosis codes, clinical conditions, or highly specific PHI beyond minimum necessary scheduling context are present. Given a curated blocklist and allowlist When applied to labels and narratives Then all outputs pass the automated content scan with 0 violations; on violation, the output is suppressed and a generic safe narrative is emitted with reason_code "SAFE_FALLBACK".
Feature-to-Label Mapping Coverage and Directionality
Given the set of top-K contributing model features (K up to 5) When explanations are generated Then 100% of these features map to patient-friendly labels; unmapped features are not exposed. Given each reason When presented Then direction correctly reflects contribution sign and impact bucket corresponds to absolute weight thresholds (high >= 0.6, medium 0.3..0.59, low < 0.3). Given unit tests for mapping When run Then coverage of mapping functions is >= 90% and no label contains internal jargon or snake_case.
Missing/Stale Signal Handling and Data Sufficiency Indicator
Given inputs with missing or stale signals (older than 30 days for behavior signals, 7 days for weather/commute) When generating explanations Then reasons referencing those signals are omitted and data_sufficiency is set to "low" or "medium" accordingly. Given data_sufficiency = "low" When narrative is generated Then it includes a neutral statement indicating limited data without blaming the patient. Given malformed or null input fields When processed Then the engine degrades gracefully, returns a valid explanation with 0 reasons and a safe narrative, and logs a warning with trace_id; no crashes.
Localization-Ready Templates and i18n Fallbacks
Given locale = "en-US" or "es-US" When generating narrative and labels Then ICU MessageFormat templates render without unresolved placeholders and pass snapshot tests. Given an unsupported locale When processing Then the system falls back to "en-US" and records locale_fallback = true. Given template unit tests When executed Then minimum test coverage is >= 85% and all narratives meet length constraints (<= 240 chars en-US, <= 300 chars es-US).
Pipeline Integration and Event Bus Publication SLA
Given a score creation or update event on the event bus When processed Then an explanation is published to topic "scoring.explanations.v1" with the same correlation_id and score_id within 200 ms p95 and 500 ms p99. Given duplicate score events When processed Then publishing is idempotent using score_id as the dedup key, resulting in at most one explanation per score_id. Given any processing error When it occurs Then the event is dead-lettered with reason and trace_id, and a retry policy (exponential backoff max 3 attempts) is applied.
Explanations UI & Calendar Slot Overlay
"As a scheduler, I want explanations and tips visible directly on each calendar slot so that I can act without leaving my workflow."
Description

Embed explanations directly in SmileCue’s calendar, appointment list, and patient profile with an accessible, responsive UI. Show a compact badge (risk level and count of reasons) and an expandable panel listing the top reasons with icons, tooltips, and confidence indicators. Include a prominent next-best-action tip with a single primary call-to-action. Provide drill-down to see structured details and signal provenance without leaving the workflow. Support copy/share and print-safe views for supervised use. Respect role-based redactions in all views and function within EHR-embedded contexts (iframes) with consistent performance and theming.

Acceptance Criteria
Compact Risk Badge Visibility and Accessibility
- Given an appointment has a computed risk score and N reasons, When the user views the calendar, appointment list, or patient profile, Then a compact badge displays the risk level text (Low/Medium/High) and reason count N adjacent to the item without additional clicks. - And the badge color maps to the risk level and meets WCAG 2.1 AA contrast ≥ 4.5:1 in light and dark themes. - And the badge is focusable via keyboard, appears in logical tab order, and exposes an accessible name: "Risk: <level>. <N> reasons.". - And hover or keyboard focus shows a tooltip summary within 200 ms and does not cause cumulative layout shift ≥ 0.1. - And the badge content and formatting are identical across calendar, list, and profile views for the same slot/patient.
Expandable Reasons Panel with Icons, Tooltips, and Confidence
- Given the badge is focused or clicked, When the user activates it via click, Enter, or Space, Then an inline overlay panel expands without a full-page navigation. - And the panel lists the top 5 reasons by impact (descending); each reason shows an icon, a human-readable label, and a confidence percentage rounded to the nearest whole number. - And each icon has an accessible tooltip that describes the signal; tooltips are reachable and dismissible via keyboard. - And if more than 5 reasons exist, a "Show all" control reveals the full list and a "Show less" returns to the top 5. - And pressing Escape or clicking outside closes the panel and returns focus to the originating badge.
Next-Best-Action Tip with Single Primary CTA
- Given the reasons panel is open, When it renders, Then a prominent next-best-action tip appears at the top with exactly one primary CTA button and an optional secondary text link. - And the primary CTA label is action-oriented and ≤ 28 characters, and the button is visually dominant relative to any secondary action. - And the CTA is enabled only when the user has permission and the action is applicable; otherwise it is disabled with an explanatory tooltip. - And clicking the CTA executes the action in-context (no route change) and logs an analytics event containing {slotId, patientId, actionType, timestamp}. - And the user receives a success or error toast within 2 seconds of action completion.
Drill-Down Details and Signal Provenance
- Given the reasons panel is open, When the user selects "Details & provenance" for a reason, Then a drill-down view opens within the panel showing structured fields: sourceSystem, featureId, featureValue, weight, signalTimestamp, modelVersion, dataLineageId. - And a "Copy JSON" control copies a machine-readable JSON payload of the selected reason's details to the clipboard. - And timestamps display in the practice timezone in UI and as ISO 8601 in copied JSON. - And if any source field is unavailable, the UI displays "Unavailable" with a tooltip explaining the cause. - And closing the drill-down returns to the reasons list with the prior scroll position preserved.
Copy, Share, and Print-Safe Views
- Given the reasons panel is open, When the user selects "Copy summary", Then a plain-text summary (risk level, top 5 reasons, next-best-action) is copied to the clipboard and respects role-based redactions. - And selecting "Copy detailed" copies all reasons with confidence and provenance in JSON while enforcing the same redactions. - And selecting "Share" generates a signed link scoped to the tenant, expiring in 7 days, accessible only to authenticated users with equal or higher permission; each access is logged for audit. - And selecting "Print" renders a print-safe view with clinic header and timestamp that fits A4/Letter without truncation, hides interactive controls, and enforces redactions. - And any attempt to print or share redacted content preserves redactions in the output.
Role-Based Redactions and Permissions Enforcement
- Given role-based access control is configured, When any user views badges, panels, copies, shares, or prints, Then visibility is enforced per role: - Compliance Lead: sees all fields. - Dentist/Hygienist: sees all reasons except sensitive administrative notes; provenance excludes identifiers not required for clinical use. - Office Manager/Front Desk: sees risk level, next-best-action, and non-sensitive reasons; sensitive items (e.g., guardian involvement, commute signals) show "Redacted" placeholders. - And redacted items display a consistent label "Redacted due to permissions" with an info tooltip. - And deep-linked shared items enforce the same redactions; unauthorized access returns 403 and is audited. - And permission changes invalidate previously issued share links and take effect on next view refresh.
EHR Embed, Theming, Localization, and Performance
- Given SmileCue is embedded in an EHR via iframe, When the explanations UI loads, Then it renders without third-party cookies and adjusts height via postMessage to avoid internal scrollbars. - And the UI inherits theme tokens (primary color, background, font family) via CSS variables while maintaining WCAG AA contrast; supports both dark and light modes. - And all labels support localization with default en-US; dates/times render per practice locale and timezone. - And compact badge data is available without additional network calls; opening the panel fetches details with p95 latency ≤ 800 ms on broadband (≥10 Mbps) and ≤ 1500 ms on 4G; failures display a retry control. - And scrolling the calendar/list maintains ≥ 45 FPS on supported browsers when badges are rendered; opening/closing the panel completes within 500 ms p95.
Next-Best-Action Tip Service
"As a front desk staff member, I want a recommended next step for each at-risk appointment so that I can reduce no-shows with minimal effort."
Description

Compute a recommended, actionable next step per appointment by combining risk reasons, patient contact preferences and consent, channel responsiveness, business hours, and practice policies. Produce a single prioritized tip with rationale and expected impact (e.g., “Send SMS now; patient responds fastest to SMS within 24 hours”). Integrate with the campaign orchestration layer to one-click trigger SMS/email/voice or rescheduling workflows, with cooldowns and guardrails to prevent over-messaging. Allow admin-configurable policies and experimentation flags to A/B test tip strategies and measure outcome lift. Log all decisions and triggered actions for auditability and learning loops.

Acceptance Criteria
Single Prioritized Tip with Rationale and Impact
Given an appointment with risk reasons, contact preferences/consent, channel responsiveness, business hours, and practice policies When the Tip Service generates a recommendation Then it returns exactly one tip with fields: tip_id, appointment_id, action.type ∈ {send_sms, send_email, place_call, propose_reschedule, no_action}, action.timing ∈ {now, schedule_at}, priority_score ∈ [0,1], rationale[] (≥1 items referencing specific reason_ids), expected_impact.metric = "confirmation_rate", expected_impact.predicted_delta ∈ [-1,1], confidence ∈ [0,1], source.version ≠ "" And the rationale cites at least the top 2 contributing reasons when available And p95 tip generation latency ≤ 300 ms per appointment (excluding orchestration) And tie-breaking between equal scores is deterministic using a documented rule (e.g., hash(patient_id, appointment_id))
Consent, Policy, and Business Hours Guardrails
Given the patient has not consented to a channel or has opted out When generating a tip Then the tip never recommends the disallowed channel and includes constraints_applied["consent_block"] Given practice business hours are closed for calls in the patient’s timezone When call would otherwise be the best action Then the tip uses action.timing = schedule_at with the next open window and includes constraints_applied["after_hours"] Given a policy max_outreach_per_day = N or max_outreach_per_week = M is reached When generating a tip Then the tip is no_action with rationale including "daily_or_weekly_cap" and expected_impact.predicted_delta = 0 And all guardrails are evaluated before any orchestration trigger is enabled
Cooldowns and Over-Messaging Prevention
Given a contact was sent on channel X within its configured cooldown window When generating a tip Then the tip does not recommend channel X until the window elapses and includes constraints_applied["cooldown_X"] Given all channels are within cooldown or otherwise blocked When generating a tip Then the tip is no_action with rationale including "cooldown_all_channels" and expected_impact.predicted_delta = 0 Given cooldown settings are updated by admin When saved Then new cooldowns take effect in tip generation within 60 seconds
One-Click Trigger Integration and Idempotency
Given a generated tip with action.type ∈ {send_sms, send_email, place_call, propose_reschedule} When the user clicks Trigger Then the orchestration API is called once with idempotency_key = tip_id and returns 202 Accepted with job_id And repeat clicks within 60 seconds do not create duplicate jobs (same job_id returned) And the UI receives a success/queued callback within 5 seconds or shows a retriable status without duplicate side effects And the final delivery/scheduling result is appended to the decision log entry for the tip
Admin Policy Configuration and Experiment Flags
Given an admin updates outreach policies (business hours, caps, allowed channels) When the change is saved Then tip generation reflects the new policy within 60 seconds Given an A/B flag is enabled for tip strategy When appointments are evaluated Then assignment is deterministic via salted hash(patient_id, appointment_date), stable for 90 days, and respects the configured split within ±2% over 10,000 appointments And all events (tip_shown, trigger_clicked, message_sent, confirmation_received) are emitted with experiment arm metadata
Decision Logging and Auditability
Given a tip is generated or triggered When the event occurs Then an immutable audit record is written containing: timestamp (UTC), appointment_id, pseudonymized patient_id, input_feature_hash, top_reasons[], decision payload, constraints_applied[], model/strategy version, experiment arm, actor_id (if user-triggered) And logs exclude message bodies/free text and any unnecessary PHI And logs are write-once, retained for ≥ 6 years, and are queryable by appointment_id within 2 seconds for the last 90 days and within 30 seconds for older records (≥99% availability) And access to logs requires roles ∈ {Compliance, Admin} and every access is itself audited
Outcome Lift Measurement and Reporting
Given experiments are active When sufficient sample size is reached (≥100 appointments per arm) Then the system computes weekly and rolling 28-day confirmation-rate lift with 95% confidence intervals and flags significance at p < 0.05 (two-proportion z-test) And dashboards/APIs expose confirmations, no-shows, outreach volume, and response latency by arm and overall And cancellations/reschedules are excluded from confirmation denominators per documented rules And metrics are recomputed nightly with backfill within 24 hours of late-arriving data
Evidence Traceability & Audit Export
"As a compliance lead, I want an auditable record of the data, model version, and reasoning behind each score so that I can satisfy HIPAA and internal audit requirements."
Description

Persist a complete, immutable evidence record for each score and explanation, including timestamp, appointment and patient pseudonymous identifiers, model/version, feature snapshot, contribution scores, generated narrative, displayed tip, and any user actions taken. Enforce retention policies and cryptographic integrity (hashing) for tamper detection. Provide secure CSV/PDF export and a scoped API with filters (date range, clinic, practitioner, model version) and PHI minimization by default, with elevated-access options for authorized personnel. Record change history when models, templates, or policies are updated to support internal and regulatory audits.

Acceptance Criteria
Immutable Evidence Record Creation
Given a risk score is computed and its explanation is displayed to a user When the Score Explain panel is rendered Then the system persists exactly one evidence record containing: timestamp (UTC ISO-8601), evidence_id (UUIDv4), appointment_pid (pseudonymous), patient_pid (pseudonymous), clinic_id, practitioner_id, model_name, model_version, features_snapshot, feature_contributions, generated_explanation, next_best_action_tip, ui_channel, and user_action (type, actor_role, timestamp) if any Given subsequent user actions on the same score (e.g., confirm, reschedule) When they occur Then the system appends a new evidence event linked via evidence_id and prior_hash, without mutating earlier records Given a direct write or update attempt to an existing evidence record When executed via API or database connection Then the operation is blocked (HTTP 403 for API; DB write denied), and the attempt is audit-logged with actor identity and timestamp
Cryptographic Hashing & Tamper Detection
Given an evidence record is saved When hashing occurs Then content_hash = SHA-256(canonical_payload) is stored and chain_hash = SHA-256(previous_chain_hash + content_hash) is maintained per appointment stream Given any stored record is modified outside the append-only path When the hourly integrity verification job runs Then it detects a hash mismatch within 60 minutes, raises a Sev-1 alert, and marks affected records with integrity_status = "failed" Given an authorized auditor calls GET /audit/evidence/{evidence_id}/verify When the record is intact Then the endpoint returns 200 with verified = true, algorithm = "SHA-256", chain_height, and verification_timestamp
Retention Policy Enforcement & Legal Hold
Given a tenant retention policy is configured to 2190 days (6 years) When an evidence record age exceeds 2190 days plus a 7-day grace period Then the system tombstones the record (payload removed, content_hash and minimal metadata retained) and revokes access, logging purge_reason = "retention_expiry" Given a legal hold is placed on a clinic or case When retention purge jobs run Then no records under hold are purged and the job report includes held_count and reasons Given a policy change sets retention_days = 90 in a test tenant When simulated time advances to trigger purge Then the purge executes idempotently and leaves no broken references (<= 1% orphaned links threshold)
Scoped Audit API with Filter Controls
Given an auditor with role = audit_viewer and scope clinic_id = 123 provides date_range = 2025-01-01..2025-01-31 and model_version = 1.4.2 When calling GET /audit/evidence?clinic_id=123&from=2025-01-01&to=2025-01-31&model_version=1.4.2 Then the response contains only in-scope records, paginated (default limit 100, max 1000), sorted by timestamp desc, with P95 latency <= 2s for up to 10k records Given no date range is supplied When the endpoint is called Then it returns 400 with error = "date_range_required" Given multiple filters (clinic_id, practitioner_id, model_version) are provided When the endpoint is called Then results reflect the intersection (AND) of filters and include total_count of the filtered set
PHI Minimization by Default Responses
Given a standard API token without elevated PHI scope When retrieving evidence via API or export Then responses omit PHI fields (name, phone, email, DoB, address, free-text notes) and include only pseudonymous IDs and minimum necessary metadata Given an authorized user requests elevated PHI access When they complete step-up MFA and submit a justification Then a time-bound session (30 minutes) is issued, responses include PHI only when include=phi is specified, and all accesses are audit-logged with user, justification, and timestamp Given a user lacks the required role or has not completed step-up MFA within the last 15 minutes When requesting PHI fields Then the system returns 403 Forbidden and logs the denied attempt
Secure CSV/PDF Export with Access Controls and Watermarking
Given an auditor with export permission requests CSV and PDF for a specific date range and clinic scope When the export job runs Then files contain the filtered dataset, exclude PHI by default, are generated within 5 minutes for up to 250k rows, and are stored encrypted-at-rest with pre-signed URLs expiring in <= 24 hours Given the requester specifies include=phi and holds an active elevated PHI session When the export completes Then the files are watermarked with requester identity, timestamp, and scope, include a SHA-256 checksum and detached signature, and PHI fields are present as requested Given an export is initiated When the API responds Then it returns a job_id and a progress endpoint; the job supports cancellation until >= 80% completion, and final artifacts list includes csv, pdf, and checksum
Change History Recording & Traceability
Given a model, template, or retention policy is updated When the change is saved Then a change_log entry is created with change_id, actor, timestamp, entity_type, old_version, new_version, diff_summary, justification, and approvals, stored immutably with a content_hash Given an evidence record is created after a model update When retrieving the record Then it references the exact model_version and associated change_id, enabling traceability from score to configuration Given an auditor exports change history for a date range When the export runs Then the CSV contains one row per change, is filterable by entity_type and clinic, and its checksum verifies successfully
Role-based Visibility & PHI Redaction
"As a practice administrator, I want sensitive factors redacted by role so that staff see only what they need while protecting patient privacy."
Description

Enforce role-based access controls that govern which explanation details are shown, at what granularity, and in which channels. Redact or generalize sensitive elements (e.g., replace precise commute details with "long commute"), and ensure redaction is applied consistently across UI, exports, and APIs. Integrate with SSO/SCIM for role provisioning, allow per-practice policy configuration with safe defaults and deny-by-default behavior, and log all access for audits. Provide administrative previews and policy testing to validate what each role will see in production.

Acceptance Criteria
UI Visibility: Front Desk Redacted Explanations
Given a practice policy v1.3 where the Front Desk role is granted attendance_pattern (generalized), booking_lead_time (days), channel_responsiveness (aggregated), and next_best_action, and denied commute_details, exact addresses, and guardian PII And an appointment has a Score Explain with commute distance 27 miles and guardian name "Alex Rivera" When a Front Desk user views the Score Explain panel in the UI Then commute_details is shown as "long commute" (no numeric distance or travel time) And guardian information is shown only as a boolean "guardian involved" (no names, contact info, or identifiers) And no DOB, address, phone, email, or MRN appear in the UI, DOM, or network payloads And risk_score and the allowed explanation categories are visible And the next_best_action tip is visible And a "Policy v1.3" indicator is displayed And an access audit event is recorded with channel=UI and policy_version=v1.3
API Redaction and Deny-by-Default
Given an OAuth token mapped via SSO to role=Front Desk under policy v1.3 When calling GET /api/v1/score-explain?appointment_id={id} Then response status is 200 And the JSON body contains only: risk_score, attendance_pattern_summary, booking_lead_time_days, channel_responsiveness_score, next_best_action, policy_version And commute_details is generalized (e.g., "long commute"), with no numeric distance or exact route And guardian-related fields are absent And no PHI fields (names, emails, phones, addresses, DOB, MRN) are present anywhere in the payload And header X-Policy-Version equals the body policy_version And an audit log is written with channel=API Given an OAuth token with an unrecognized or unpermitted role When calling the same endpoint Then response status is 403 with error_code=RBAC_DENY and no patient-related data in the body
Export CSV: Consistent Redaction by Role
Given a user with role=Office Manager under policy v1.3 When exporting a "Score Explain" CSV for a selected date range Then the generated CSV contains only permitted columns for that role And sensitive columns are omitted or generalized (e.g., commute_category shown as long/short, not miles/minutes) And values in the CSV match the UI for the same role and time (spot-check at least 5 rows) And the file metadata (first row or separate manifest) includes role, policy_version, generated_at And the download URL is single-use and expires within 15 minutes And an audit event is recorded with channel=Export And automated checks confirm no PHI patterns (names, emails, phones, addresses, DOB) appear in any cell
SSO/SCIM Role Provisioning and Revocation Enforcement
Given a user is provisioned via SCIM with role=Front Desk When the user signs in via SSO and accesses Score Explain Then the enforced permissions reflect the SCIM role within 60 seconds of the last SCIM update Given the same user is deprovisioned or their role is changed to a role without Score Explain permission When the user attempts to access Score Explain (UI, API, Export) Then access is denied within 5 minutes of the SCIM change And any existing tokens are blocked for Score Explain endpoints on next use And audit logs capture the SCIM change and subsequent access outcomes
Per-Practice Policy Configuration with Safe Defaults
Given a newly onboarded practice with no custom policy When an admin opens Policy Settings Then safe defaults are applied with deny-by-default for any explanation attribute not explicitly allowed And external channels (email/SMS/voice) cannot be configured to include Score Explain content When the admin adds a rule to allow "guardian involvement (boolean)" for role=Dentist Then saving is blocked if any PHI field would be exposed in disallowed channels And publishing the change requires confirmation, a change summary, and increments policy_version And the new policy only takes effect after explicit publish, with all changes logged
Administrative Preview and Policy Testing Across Channels
Given an admin selects role=Front Desk, channel=UI, and a sample appointment in Policy Preview When clicking Preview Then the preview exactly matches what that role/channel would receive, including redactions, ordering, and policy_version And "Copy API response" returns the exact JSON for that role as /api/v1/score-explain would return And "Download sample export" produces a CSV identical in columns/generalization to a real export And a PHI leak check reports Pass (no PHI patterns detected) And all preview actions are audit logged with channel=Preview
Audit Logging Across Channels for Score Explain Access
Given any access to Score Explain (UI, API, Export) When the access completes Then an immutable audit record is written containing: event_type, timestamp (UTC), user_id, role, practice_id, patient_pseudonym, channel, fields_returned_hash, policy_version, request_id, ip, outcome And the audit record stores no raw PHI values And logs are queryable by compliance users within 5 minutes of the event And tamper-evidence (e.g., WORM or hash chain) prevents deletion/alteration; any attempts are logged And retention is at least 6 years And a daily job verifies log integrity and alerts on failures
Multichannel Signal Ingestion & Fallbacks
"As a scheduler, I want explanations to remain sensible even when some signals are unavailable so that I can still take action confidently."
Description

Ingest and maintain the signals required for explanations and tips: attendance history and booking lead time from EHR, channel responsiveness from SmileCue communications, guardian relationships, and external weather/traffic data. Define data contracts, validation rules, freshness SLAs, and provenance metadata for each signal. Implement retries, circuit breakers, and monitoring for external dependencies. Provide explicit fallbacks and heuristics when signals are missing or stale, degrade gracefully without blocking scoring, and surface which signals were used in each explanation.

Acceptance Criteria
EHR Attendance History & Booking Lead Time Ingestion
Given an EHR emits an appointment create/update event, when the event is available, then attendance_history and booking_lead_time records are ingested and available for scoring within 5 minutes (p95) and 15 minutes (p99). Given the data contract for attendance_history and booking_lead_time, when a batch is processed, then 100% of records conform to schema (types, required fields, timezone) and any batch with >0.5% schema/validation errors is quarantined and alerts are fired. Given duplicate or out-of-order events, when records are upserted, then idempotency is enforced using practice_id + appointment_id + event_version and no duplicate rows exist. Given historical data import, when backfill completes, then 24 months of attendance history is present for ≥99% of active patients.
Channel Responsiveness Signal Computation
Given message delivery/interaction events from SmileCue, when new events arrive, then per-patient per-channel responsiveness metrics (7/30/90-day delivery, response/answer, click rates) are updated within 15 minutes (p95). Given the nightly batch window, when the job completes by 02:00 local, then all responsiveness aggregates are refreshed for all active patients with <0.1% job failure rate. Given invalid contact endpoints, when events contain hard bounces/invalid numbers, then those endpoints are marked uncontactable within 5 minutes and excluded from responsiveness denominators. Given the defined data contract, when metrics are persisted, then fields channel, window, numerator, denominator, last_updated_at, and provenance.source are present and valid.
Guardian Relationship Mapping and Validation
Given EHR relationship data, when a patient under 18 is synced, then a guardian record with relationship_type, contact_id, consent_flag, and last_verified_at is present or the patient is flagged guardian_missing within 1 hour (p95). Given changes in guardianship, when updates are received, then they are reflected in the model within 1 hour and older relationships are end-dated, preserving history. Given data quality checks, when a daily audit runs at 03:00 local, then ≥95% of minors have a verified guardian in the last 12 months; otherwise an alert is raised. Given provenance requirements, when a record is stored, then source_system, source_record_id, collected_at (UTC), and transform_version are populated.
External Weather and Traffic Dependency Resilience
Given the primary weather provider is unavailable or returns 5xx > 20% over 1 minute, when requests are made, then retries (max 3, exponential backoff with jitter) are attempted and a circuit breaker opens for 5 minutes before failing over to the secondary provider. Given both primary and secondary providers fail, when a request is made, then baseline heuristics are applied (zip-code seasonal averages for weather, median commute times by daypart for traffic) and the signal is marked fallback_applied=true with omission_reason=provider_unavailable. Given freshness SLAs, when scores are computed, then weather forecasts for the appointment time are ≤60 minutes old and traffic estimates are ≤5 minutes old during 06:00–20:00 local; otherwise the signal is treated as stale. Given monitoring, when provider errors exceed thresholds or freshness SLAs are violated for >5 consecutive minutes, then alerts page the on-call within 2 minutes.
Signal Freshness SLAs, Validation, and Monitoring
Given defined SLAs, when the system is in steady state, then SLA compliance per signal per day is ≥99% for EHR-derived signals and ≥97% for external signals, with dashboards showing compliance and error budgets. Given schema and range validation, when ingestion runs, then null rates for required fields are ≤0.5% and out-of-range values are ≤0.1%; batches breaching thresholds are quarantined and excluded from scoring. Given stale signals, when a signal exceeds its freshness window, then it is excluded from model features, the explanation marks the signal as stale, and scoring proceeds without error. Given observability, when any exclusion due to staleness occurs, then it is logged with correlation_id and surfaced in a daily report of exclusions by signal type.
Fallbacks and Non-Blocking Scoring Behavior
Given one or more signals are missing or stale, when a score is requested, then the scoring service returns a score within 750 ms (p95) without throwing user-visible errors. Given missing attendance history, when scoring occurs, then the model uses an unknown_attendance feature value and sets confidence to low, and the explanation includes the fallback used. Given missing channel responsiveness, when scoring occurs, then the model uses practice-level channel averages from the last 30 days and flags fallback_applied in the explanation. Given a minor patient with guardian_missing, when scoring occurs, then a next-best-action "confirm guardian contact" tip is generated and included in the output.
Explanation Payload: Signals Used, Omitted, and Provenance
Given a score is generated, when the explanation payload is returned, then it includes used_signals[] with fields name, value_summary, source_system, collected_at_utc, freshness_status, transform_version, and feature_version. Given signals were omitted or fallback applied, when the explanation is returned, then omitted_signals[] includes signal name and omission_reason in {missing, stale, provider_unavailable, validation_failed} and fallback_details if applicable. Given HIPAA constraints, when the explanation is viewed, then it contains no PHI beyond patient_id/practice_id and derived aggregates; direct contact details and free text are excluded. Given audit-readiness, when an auditor requests traceability, then the system can retrieve provenance for any signal in ≤2 seconds (p95) using correlation_id and retains logs for ≥6 years.
Performance, Caching, and SLA Guarantees
"As a busy receptionist, I want explanations to load instantly so that my booking workflow is not slowed down."
Description

Meet strict performance budgets so explanations feel instantaneous in daily workflows: <=200 ms p95 additional latency per slot and <=1.5 s p95 for views with 50+ slots. Implement server-side caching keyed by appointment, patient, model version, and data fingerprint, with precomputation for near-term schedules and invalidation on relevant data changes. Provide graceful degradation to last-known explanations with freshness indicators when backends are slow. Establish monitoring dashboards, alerts, load tests, and autoscaling policies to maintain agreed SLAs under peak usage.

Acceptance Criteria
p95 Latency per Slot: <=200 ms Additional for Explanations
- Server-side measured additional latency attributable to generating explanations per slot is <=200 ms at p95 over a 24-hour window, excluding network RTT. - Measurement is captured by a dedicated metric (explain_slot_latency_additional_ms) from request receipt to response write and compared against baseline score retrieval. - Under a controlled load test with ≥300 concurrent users, p95 additional per-slot latency remains <=200 ms and 5xx error rate <=0.5%. - Results are visible in the performance dashboard with p50/p95/99th percentiles and are exportable for audit.
p95 Latency for Views with 50+ Slots: <=1.5 s to Interactive
- For schedule views containing ≥50 appointment slots with explanations, p95 time from initial request to all explanation payloads received and rendered is <=1.5 s over a 24-hour window. - 99th percentile time for the same is <=2.5 s. - Measurement is implemented via server timings and RUM beacons; outliers beyond 10 s constitute <0.1% of samples. - No blocking errors are introduced; client error rate for the view remains <=0.5%.
Server-side Caching with Correct Keys and Precomputation
- Cache key includes: appointment_id, patient_id, model_version, and data_fingerprint (hash of all features that affect explanations: prior attendance pattern, booking lead time, channel responsiveness, weather/commute signals, guardian involvement, and other model inputs). - For appointments in the next 72 hours, cache hit rate during business hours (8am–6pm local) is >=85%. - Precomputation generates explanations for all appointments in the next 72 hours at least every 15 minutes and upon invalidation; job success rate >=99% daily and each cycle completes in <10 minutes. - Cache TTLs and precompute schedules are documented and observable in dashboards.
Cache Invalidation on Relevant Data Changes
- When any feature contributing to data_fingerprint changes, or model_version increments, corresponding cache entries are invalidated within 2 minutes p95. - Appointment reschedule/cancel or patient contact changes invalidate affected entries within 60 seconds p95. - After relevant data change, users do not see explanations older than 15 minutes without a visible freshness label; updated explanations available within 15 minutes p95. - 100% of invalidation events are audit-logged with reason, timestamp, and affected keys; false-positive invalidations are <=1%.
Graceful Degradation with Freshness Indicators
- If explanation generation exceeds 800 ms per slot or 1.2 s per view, system serves last-known explanations (if available) with a visible "Last updated <timestamp>" indicator and triggers a background refresh. - If last-known explanations are >24 hours old, they are labeled "Stale" and a non-blocking "Refresh" action is provided; UI remains responsive. - Degradation events are metered; average weekly degradation rate <=5% of views and are visible in dashboards with counts and freshness age. - Upon backend recovery, updated explanations replace degraded content without page reload within 15 seconds p95.
Monitoring, Alerts, and Autoscaling to Maintain SLAs
- Dashboards display p50/p95 latencies for per-slot and per-view, cache hit rate, error rate, degradation rate, queue depth, and autoscaling actions with 90-day retention. - Alerts trigger when p95 per-slot >200 ms or p95 per-view >1.5 s for ≥5 minutes, cache hit <75% for ≥10 minutes, or 5xx >1% for ≥5 minutes; on-call is paged within 2 minutes. - Autoscaling policies keep CPU <60% and maintain SLA latencies; scale-up initiates within 60 seconds of threshold breach in load tests and is logged. - Runbook is linked from alerts and validated in a game day; incidents record MTTR and corrective actions.
Load Tests Demonstrate SLA Under Peak Usage
- Load test simulates ≥400 concurrent schedulers across ≥200 practices with average 60-slot views for a 30-minute soak and step-up phases. - Results meet: p95 additional per-slot latency <=200 ms; p95 per-view <=1.5 s; p99 per-view <=2.5 s; 5xx <=0.5%. - Cache hit rate during test >=85%; autoscaling scales to steady state within 1 minute of each step increase. - Test artifacts (config, scripts, results) are archived and reproducible via CI; passing test is a prerequisite for production enablement.

Auto Playbooks

Turns risk thresholds into automated, response-driven actions: earlier reminder cadence, multilingual switch, guardian CC, voice fallback, double-confirm steps, or deposit request for high-value appointments. Fully integrated with SmileCue’s branching templates and consent rules so the right escalation happens automatically and compliantly.

Requirements

Risk Threshold Engine
"As an office manager, I want appointments automatically classified by risk so that the correct communication sequence runs without manual review."
Description

A backend component that evaluates patient and appointment risk attributes (e.g., prior no-shows, appointment value, procedure type, lead time, channel engagement history, consent state) against configurable thresholds to select the appropriate Auto Playbook. Supports weighted rules, time-based conditions, and real-time reevaluation on schedule changes or new signals. Exposes API/webhooks to receive EHR updates and triggers playbook selection without delays. Logs decision rationale for audit and analytics.

Acceptance Criteria
Weighted Rule Evaluation Selects Appropriate Playbook
Given risk rules with configured weights, thresholds, and eligibility constraints are active When the engine receives a PatientAppointmentContext containing priorNoShows, appointmentValue, procedureType, leadTimeHours, channelEngagement, and consentState Then it computes scores for all eligible playbooks and selects the highest-scoring one deterministically And if two or more playbooks tie on score, Then the engine applies tie-breakers in order: higher riskLevel, most recent updatedAt, lowest playbookId And the selected playbook and computed score match an offline evaluator run for the same inputs And p95 decision latency from event receipt to selection is <= 300 ms (p99 <= 800 ms) under 50 rps sustained load
Real-Time Reevaluation on New Signals or Schedule Change
Given a playbook has been selected for an appointment When the appointment startTime changes, the consentState changes, or a new engagement signal arrives (STOP, bounce, hard-fail, or no-response timeout) Then the engine reevaluates and, if the selected playbook changes, emits a PlaybookSelectionChanged event exactly-once within 2 seconds p95 of the triggering signal And any previously scheduled steps from the superseded playbook are canceled within 5 seconds p95 And idempotency keys ensure duplicate inbound signals do not produce duplicate reevaluations or events
Time-Based Lead-Time Conditions Influence Selection
Given lead-time windows are configured (e.g., >168h, 168–48h, <48h) with different playbooks or cadences When the appointment’s leadTimeHours crosses a configured window boundary due to reschedule or time elapsing Then the engine reevaluates automatically at the boundary crossing and selects the playbook associated with the new window And if the current playbook is already the most aggressive, Then no change occurs and this is logged as NO_CHANGE And schedule diffs are computed so that duplicate reminders are not re-sent after a switch
Consent-Aware Channel Compliance
Given the patient’s consentState for SMS, email, and voice is available in the context When the engine evaluates playbook eligibility Then it only considers playbooks whose steps comply with the current consentState And if no playbook is eligible due to consent constraints, Then the engine returns NO_ELIGIBLE_PLAYBOOK and logs reason CONSENT_BLOCK with a timestamp And when consentState later permits outreach, Then a new evaluation may select an eligible playbook
EHR API/Webhook Intake and Triggering
Given the engine exposes an authenticated API and HMAC-signed webhook endpoint for EHR updates When a valid, signed payload that passes schema validation is received Then the engine acknowledges with HTTP 2xx within 1 second p95 and triggers selection within 500 ms p95 of receipt And if an externalEventId has already been processed, Then the engine performs no duplicate work and returns 200 (idempotent) And invalid signatures or schemas result in HTTP 401/400 with machine-readable error codes And inbound requests are rate-limited per practice and logged with traceIds
Decision Rationale Logging and Auditability
Given a selection (or no-eligible decision) is made When writing the audit record Then the record includes selectionId, practiceId, appointmentId, pseudonymized patientId, evaluatedAt UTC, selectedPlaybookId (or null), candidateScores[], matchedRules[], excludedReasons[], tieBreakerApplied, consentSnapshot, and configVersion And audit records are encrypted at rest, retained for >= 365 days, and retrievable via a role-restricted API (role: Compliance Auditor) And given the same inputs via a replay endpoint, Then the engine reproduces the same selection and rationale fields
High-Risk Escalations: Deposit, Double-Confirm, and Fallbacks
Given riskScore >= High threshold or priorNoShows >= 2 and appointmentValue >= depositThreshold When the engine selects a playbook Then the chosen playbook includes a deposit request step due by T-48h and a double-confirm step before T-24h And if deposit is not completed by T-24h, Then the engine escalates to voice fallback and emits an OfficeNotify webhook And if preferredLanguage != 'en', Then the selected playbook uses the corresponding language templates; if hasGuardian = true, Then guardian CC is included per consent And if SMS engagementScore < Low threshold, Then a voice fallback step is included while honoring consent
Playbook Builder UI
"As a practice admin, I want to design and deploy automated communication flows so that each patient receives the right steps for their situation."
Description

A visual, HIPAA-compliant editor to create and manage response-driven branching playbooks that define actions such as reminder cadence adjustments, channel sequencing (SMS, email, voice), multilingual switching, guardian CC, double-confirm steps, and deposit requests. Includes condition nodes, action nodes, wait timers, exit criteria, and reusable templates. Provides validation for consent and channel availability, versioning with draft/publish, and safe rollout via percentage-based activation by appointment type or risk tier.

Acceptance Criteria
Drag-and-Drop Node Creation and Branching
Given a user with Edit Playbooks permission, When they drag a Condition, Action, Wait, or Exit node onto the canvas, Then the node is created with a unique ID and default properties visible in the properties panel. Given two nodes on the canvas, When the user connects them, Then a labeled edge is created and persisted, supporting at least 10 distinct branches per Condition node. Given a playbook with 50 nodes and 100 edges, When the user clicks Save, Then the graph structure persists and reloads identically upon reopening the draft. Given a condition based on patient risk score, When risk >= the configured threshold, Then the True branch is taken; When risk < threshold, Then the False branch is taken.
Wait Timers and Exit Criteria Configuration
Given a Wait node, When the user sets a duration between 1 minute and 30 days, Then the UI validates the range and stores the value as an ISO-8601 duration. Given practice time zone is configured, When a Wait node is saved, Then scheduled waits are computed relative to the practice time zone. Given Exit criteria for "Appointment Confirmed" or "Appointment Cancelled", When the event occurs, Then the playbook terminates within 60 seconds and no subsequent actions fire. Given validation is run, When a Wait would create a circular path or unreachable Exit, Then validation flags a blocking error with the offending node ID and blocks publish.
Consent and Channel Availability Validation
Given any outbound action (SMS, Email, Voice), When Validate or Publish is invoked, Then the action must declare required consent and required attributes (e.g., phone number, email), otherwise a blocking error identifies the node ID and missing requirements. Given an outbound action without an alternate path, When validator detects a possible path where required consent or attributes could be absent, Then publish is blocked unless "Auto-skip if unavailable" or a fallback channel is configured. Given all outbound actions are either consent-guarded or set to auto-skip/fallback, When Publish is clicked, Then the playbook passes consent and channel availability checks with no blocking errors.
Versioning: Draft, Publish, and Rollback
Given a Draft version, When the user clicks Publish, Then a new immutable Published version is created with a unique version ID, timestamp, and publisher identity, and becomes the single Active version. Given an Active version and at least one prior version, When the user selects Rollback to a prior version, Then that prior version becomes Active and the previously Active version remains in history as Archived. Given edits are made to a Draft, When saved, Then they do not affect the Active version until Publish is executed. Given the version history view, When opened, Then it lists versions with status (Active/Archived/Draft), created timestamps, publisher, and change notes.
Percentage-Based Rollout by Appointment Type and Risk Tier
Given a Published playbook, When configuring rollout, Then the user can target by appointment type and by risk tier threshold(s). Given a rollout percentage P between 0% and 100% in 1% increments, When enabled, Then P% (±1%) of eligible appointments are assigned using deterministic hashing for per-appointment stickiness. Given rollout is changed from 10% to 50%, When saved, Then only newly created or unassigned eligible appointments after the change are affected; existing assignments remain unchanged. Given rollout is disabled, When saved, Then no new eligible appointments are assigned the playbook while already-assigned flows continue uninterrupted.
Reusable Templates: Save, Apply, and Update
Given a selection of nodes and edges, When the user clicks "Save as Template", Then the system saves a template with name and description, strips any patient-identifying placeholders, and stores it in the template library. Given a template in the library, When applied to a canvas, Then its nodes are inserted without deleting existing nodes, and new node IDs are generated to avoid collisions. Given an existing template, When updated and saved, Then a new template version is created and existing playbooks that used prior versions remain unaffected. Given the template library, When searching by name, tag, or included actions, Then matching templates are returned for libraries up to 200 templates in under 500 ms.
Action Nodes: Multilingual Switch, Guardian CC, Double-Confirm, Deposit, Voice Fallback
Given a Multilingual Switch action and the patient's preferred language matches an available locale, When messages are sent, Then subsequent content uses that locale; otherwise the default locale is used. Given a Guardian CC action and a validated guardian contact on file with appropriate consent, When an outbound message is sent, Then the guardian receives a CC; if no guardian or consent, Then the action auto-skips without blocking the flow. Given a Double-Confirm step requiring two affirmative responses within 24 hours, When the patient replies "Yes" twice in that window, Then the appointment status is set to Confirmed; a single "Yes" does not complete the step. Given a Deposit Request action with amount and payment link configured, When sent, Then the message includes a unique payment link; upon payment confirmation from the gateway, Then the success branch executes. Given channel sequencing with Voice Fallback configured, When SMS and Email fail or time out per configured waits, Then the system triggers a Voice call within the defined fallback SLA.
Consent & Compliance Gatekeeper
"As a compliance officer, I want every automated action to be vetted against consent and privacy rules so that our practice remains protected."
Description

A policy layer that enforces HIPAA and consent rules at runtime for every action in a playbook. Validates patient/channel consent, honors opt-outs, suppresses PHI in restricted channels, and ensures voice drops comply with TCPA and local regulations. Maintains immutable audit logs of all decisions, content variants sent, and user overrides. Provides breach-safe masking in logs and supports data retention policies.

Acceptance Criteria
Channel Consent Validation and Fallback at Send Time
- Given a playbook action targeting a patient, When the Gatekeeper evaluates eligible channels (SMS, email, voice), Then it shall dispatch only to channels with active, documented consent and suppress any channel lacking consent, recording a suppression reason code. - Given no channels have active consent, When the action is evaluated, Then no communication is sent, the playbook path is halted or rerouted per template rules, and an audit entry is created. - Given a configured fallback channel in the playbook and that channel has active consent, When the primary channel is suppressed, Then the message is routed to the fallback channel in the same transaction and recorded in the audit log. - Given a guardian CC step is present, When the Gatekeeper evaluates recipients, Then it shall verify an active guardian relationship and channel-specific consent for the guardian and policy eligibility for the appointment type; otherwise suppress the guardian send and record the reason. - Given the consent service is unavailable, When the action is evaluated, Then the Gatekeeper shall fail-safe by suppressing all sends and logging a consent-service-unavailable reason. - Given a multilingual template switch is requested, When the selected language variant is unavailable or unapproved for the channel, Then the Gatekeeper shall use the default non-PHI variant if allowed by policy; otherwise suppress and log.
Opt-Out Honor and Real-Time Suppression
- Given a patient has opted out of a channel (e.g., SMS STOP, email unsubscribe, voice DNC) within the last 60 seconds, When any playbook attempts to send via that channel, Then the Gatekeeper shall suppress the send and record the opt-out event ID and timestamp in the audit log. - Given an SMS STOP is received, When processing the event, Then the system shall send a single non-PHI confirmation message and cease further SMS until opt-in is reinstated. - Given a queued but not yet dispatched message for an opted-out channel, When the opt-out is processed, Then the queued message is canceled prior to dispatch and the cancellation is logged. - Given a subsequent opt-in is received (e.g., START), When evaluating new actions, Then the Gatekeeper shall allow sends only after the opt-in is recorded and time-stamped, and shall reference the new consent snapshot in the audit.
PHI Redaction in Restricted Channels
- Given channel policy disallows PHI in SMS or email, When message content contains PHI-tagged fields (e.g., diagnosis, procedure details, payment amounts tied to treatment), Then the Gatekeeper shall either mask those fields with approved placeholders or suppress the send per policy and record the redaction/suppression rule IDs. - Given a message includes an attachment or inline image, When the channel is SMS, Then the Gatekeeper shall strip attachments and replace with an expiring secure portal link, or suppress if a portal link is unavailable. - Given a secure link is included, When generating the link, Then it shall be tokenized, expire within the configured TTL, and not reveal PHI in the URL. - Given a redacted message is dispatched, When the audit log is written, Then only the template ID and redaction map are stored; no raw PHI values are persisted.
TCPA-Compliant Voice Drops
- Given a voice drop action, When the Gatekeeper evaluates compliance, Then it shall verify prior express consent for voice, local time window compliance (08:00–21:00), daily/weekly frequency limits, valid caller ID, and DNC/suppression list checks before allowing dispatch. - Given any TCPA or local regulation check fails, When the action is evaluated, Then the voice drop is suppressed and the specific rule failure code is recorded. - Given a voice drop is allowed, When the call is configured, Then an opt-out mechanism (spoken instructions and DTMF key) is included in the message, and its inclusion is recorded in the audit. - Given the patient's timezone cannot be resolved, When evaluating the time window, Then the Gatekeeper shall default to the practice's timezone and enforce the window, or suppress if ambiguous per policy.
Immutable Audit Logging with Breach-Safe Masking
- Given any allow, suppress, redaction, or override decision, When the decision is made, Then the Gatekeeper shall write an append-only audit record containing action ID, patient pseudonymous ID, channel, consent snapshot ID, rules evaluated with outcomes, content/template variant ID, redaction rule IDs, timestamps (UTC and patient local), and a hash chain pointer. - Given an audit record is written, When stored, Then PHI/PII values shall be masked or tokenized; no raw message body or PHI fields are stored. - Given an attempt to alter or delete an existing audit record, When integrity checks run, Then a hash-chain mismatch alert is raised and the event is logged to security monitoring. - Given a privileged user requests to view an audit entry, When access is checked, Then only users with the required role can view masked details; raw PHI cannot be revealed via the audit interface.
Data Retention and Purge Enforcement
- Given data retention policies are configured per data class (audit logs, delivery receipts, consent events), When records reach end-of-retention, Then the Gatekeeper shall purge them within 24 hours and write a purge-audit record containing counts and IDs. - Given a legal hold is applied to a patient or case, When purge jobs run, Then records under hold are excluded and the hold reference is recorded. - Given an export request for audit data is made by an authorized user, When the export is generated, Then only masked fields and metadata are included, and the export is watermarked with requester, time, and scope. - Given a purge fails, When retries are exhausted, Then an alert is created and the failure is recorded with retry history.
Role-Based Overrides with Justification and Traceability
- Given a suppression decision is presented in the UI, When a user with override permission attempts to override, Then the system shall require a justification text, reason code selection, and confirm scope (single action only), and record the override in the audit with user ID and role. - Given an override is submitted, When policy prohibits overriding a specific rule (e.g., PHI in disallowed channel, TCPA time window), Then the override is rejected with a non-overridable-rule code and no send occurs. - Given an override is accepted, When the message is dispatched, Then all other applicable rules still apply (e.g., PHI redaction, masking), and the outcome is linked to the override record. - Given an override is created, When reviewing the audit trail, Then the system displays the decision lineage from original suppression through override to final dispatch with timestamps.
Multilingual Auto-Switch with Content Library
"As a hygienist, I want messages to switch to the patient’s preferred language so that they understand and respond promptly."
Description

Automatic selection of language-specific content based on patient preference, detected responses, or regional metadata, with fallback rules. Integrates with a centralized content library that stores approved translations for SMS, email, and voice scripts, supports personalization tokens, and tracks content versions per language. Offers QA previews and test sends per language and channel.

Acceptance Criteria
Patient Preference Language Auto-Selection
Given a patient profile includes a language preference code (e.g., es-MX) and channel consent is present And approved templates exist for the selected language in SMS, email, and voice When the system initiates an appointment reminder via the Auto Playbook Then the message for each channel is selected from the content library using the matching language code and channel And the latest Active version effective at send time is used And all personalization tokens resolve with zero unresolved placeholders And the audit log records language code, template ID, version, and selection rule = "patient_preference"
Reply-Driven Language Detection and Switch
Given a patient has no language preference on file and the last outgoing message was in English And language detection threshold is configured at 0.90 When the patient replies in Spanish with detected confidence >= threshold or with configured Spanish keywords (e.g., "SI", "Sí") Then all subsequent automated messages in the same conversation switch to Spanish within 60 seconds And the audit log records detection language, confidence, keywords matched, and selection rule = "reply_detection" And if confidence < threshold and no keyword match, no switch occurs
Regional Default Language with Precedence Rules
Given the patient has no language preference and no qualifying reply detection And the patient region metadata (country/ZIP/locale) maps to a default language (e.g., es-US) and the practice has an optional override language configured When the system prepares the first outreach in a campaign Then language selection precedence is applied: Patient Preference > Reply Detection > Practice Override > Regional Default > System Default (en-US) And the selected language is available in the content library; otherwise fallback rules are applied And the audit log records the precedence path taken and selection rule = "regional_default" or "practice_override" as applicable
Fallback Language When Translation Missing
Given Spanish is the selected language for an SMS reminder And the Spanish template for that message key is not Active or missing When the system sends the message Then it falls back to the configured fallback language (e.g., en-US) using its Active template And emits a content gap alert to content admins with template key, missing language, and channel And no unresolved tokens or mixed-language fragments are sent And the audit log records the fallback event with from_language, to_language, template IDs, and selection rule = "fallback_missing_translation"
Language-Channel Version Selection from Content Library
Given multiple versions of a template exist in the content library for es-MX SMS with statuses Draft, Active, and Archived and effective dates When the system selects content to send Then exactly one Active version with the most recent effective_at <= send time is chosen And Draft and Archived versions are never selected And if zero Active versions exist, the system does not send that language and triggers fallback per rules And the audit log records the chosen version ID and effective_at
Personalization Tokens Localization and Safety
Given a Spanish email template contains tokens {{patient_first_name}}, {{appointment_datetime}}, and {{office_phone}} And locale for formatting is es-MX When rendering the message Then date/time are formatted in the es-MX locale, phone numbers are formatted per E.164 or practice format, and names are correctly inserted And zero unresolved tokens remain; if a required token is missing, the message is not sent and an error is logged And no raw token syntax (e.g., {{...}}) appears in the delivered message
QA Preview and Test Send per Language and Channel
Given a content admin opens the es-ES voice script in the content library When they click Preview and supply sample token values Then the preview renders in the correct language with the configured TTS voice and locale And when they click Test Send to a whitelisted test destination Then the test message/voice call is delivered within 60 seconds, marked as TEST, excluded from patient records and analytics, and logged with language, channel, template ID, and version
Guardian CC and Relationship Routing
"As a pediatric practice manager, I want guardians automatically included in reminders so that appointments are confirmed by the responsible adult."
Description

Ability to associate guardians or responsible parties with patient records and automatically CC or route messages when the patient is a minor or has designated consent. Supports relationship types, per-channel permissions, and escalation logic that ensures confirmations and deposits can be handled by guardians where allowed. Includes data model extensions and UI to manage relationships.

Acceptance Criteria
Minor Patient – Guardian CC on Appointment Reminder
Given a patient is under 18 and has at least one guardian with Scheduling authority and SMS permission=CC When an appointment reminder SMS is triggered by a playbook Then send SMS to the patient (if SMS permission=Allowed) and CC the eligible guardian(s) within 2 minutes And record separate message IDs and delivery statuses for patient and each guardian And create an audit log entry including routing reason=minor, relationship type, channel, and template ID And do not send to any guardian with channel permission=Suppressed or outside effective dates And enforce quiet hours for both patient and guardian recipients
Adult Patient – Deposit Request Routed to Designated Financial Proxy
Given a patient is 18 or older and has a relationship type=Responsible Party with authority scope=Financial and consent on file When a deposit request step is triggered Then suppress the deposit message to the patient and route exclusively to the proxy on allowed channels And include a secure, proxy-bound payment link and attribution of payer=proxy upon success And mark the appointment deposit as paid and update the ledger with transaction ID And log consent basis=designated-proxy and retain evidence in the audit trail
Per-Channel Permissions and Primary/CC Enforcement
Given a patient and one or more guardians with per-channel permissions (Allowed, Suppressed) and roles (Primary, CC) When any playbook step sends a message over SMS, Email, or Voice Then only send on channels where permission=Allowed and valid contact data exists And if guardian is Primary for a channel, route the message to the guardian instead of the patient for that channel; otherwise send to patient and CC guardians marked CC And never send duplicates to the same phone/email on a single step And do not send on channels without documented consent or with Do Not Contact flags
UI – Manage Guardians, Authorities, and Effective Dates
Given a staff user with role=Office Manager is adding or editing a guardian on a patient profile When saving the relationship Then require relationship type, authority scopes (Scheduling/Medical/Financial), per-channel permissions, language, and effective/expiry dates And validate that minors have at least one guardian with Scheduling authority before allowing save And prevent duplicate guardians with identical contact for the same channel And reject expiry dates before effective dates and flag expired relationships And version and timestamp all changes with user ID and reason
No-Response Escalation to Guardian for Confirmation
Given a reminder was sent to a minor patient and no reply is received within 12 hours When the escalation step executes Then send a confirmation request to guardians with Scheduling authority on their allowed channels And include a trackable link enabling guardian confirmation on behalf of the patient And upon guardian confirmation, mark confirmation actor=guardian, stop further escalations, and update appointment status And if all guardian deliveries fail, create a staff follow-up task within 5 minutes
Multilingual Routing Based on Guardian Preference
Given a guardian has language preference set and translations exist for the selected template When a message is routed to that guardian Then send the localized template matching the guardian’s language And if no translation exists, fall back to English and log a missing-translation event And record the language used per recipient for analytics And ensure patient and guardian language selections are applied independently
Audit Trail and Privacy for Guardian-Routed Communications
Given any message is routed to a guardian When viewing the audit trail and exports Then show patient ID, guardian ID, relationship type, consent basis, authority scope used, channel, template ID, timestamp, delivery status, and routing rule ID And do not store PHI content in plaintext (store template IDs and tokens only) And ensure audit entries are immutable, role-restricted, and exportable within 24 hours of the event And log all audit views and exports with user ID and timestamp
Deposit Request Step with Payments Integration
"As a dentist, I want to collect deposits for high-value procedures so that patients commit and no-shows are reduced."
Description

Playbook action that requests a deposit for high-value appointments, integrated with PCI-compliant payment gateways. Supports configurable deposit amounts, due-by times, secure payment links via SMS/email, and voice prompts that transfer to a secure IVR. Tracks payment status, retries per playbook rules, and writes payment outcomes back to the appointment record and analytics.

Acceptance Criteria
Trigger Deposit Request for High-Value, High-Risk Appointment
Given a playbook with a risk threshold ≥ configured value and a Deposit Request step enabled for appointments tagged High-Value And a patient with valid communication consent exists on the appointment When the appointment enters the playbook and meets the risk and value conditions Then the system inserts a Deposit Request step before the confirmation step in the branching flow And the step records the computed deposit amount, due-by timestamp, and selected channels per consent And an audit log entry is created with playbook ID, appointment ID, user/practice ID, and timestamp
Configurable Deposit Amount and Due-By Rules
Given deposit configuration supports Fixed amount and Percentage of estimated fee with min/max caps and currency per practice And rounding is set to nearest $1 When an appointment estimated fee is $800 and percentage is 20% with min $25 and max $150 Then the computed deposit amount is $150 (capped and rounded) And the due-by time is calculated as 48 hours before appointment start or 4 hours after request, whichever is sooner And all times are stored in UTC with patient/practice local timezone offsets for display
Secure Payment Link Delivery via SMS/Email with Consent and Expiry
Given the patient has SMS consent and no email consent When a Deposit Request step is triggered Then the system sends an SMS containing a unique, single-use payment link hosted by the PCI-compliant gateway domain And the link expires at the deposit due-by time and cannot be reused after successful payment And the message template includes practice name, amount due, due-by local time, and secure link placeholder And no card data is collected or rendered by SmileCue; PHI in the message is limited to first name and appointment date/time And if SMS delivery fails, the system retries per playbook rules and does not send email without consent
Voice Fallback to PCI-Compliant IVR
Given the deposit remains unpaid and the playbook defines a voice fallback before due-by When the fallback condition is met Then the system places an automated call respecting quiet hours and time zone And upon patient identity verification (name + DOB/MM/DD or code), the call transfers to a secure PCI-compliant IVR owned by the gateway And SmileCue does not capture DTMF or card data; only payment outcome tokens are received from the gateway And the IVR supports English and Spanish selection consistent with the patient language setting And the call outcome (Connected/No Answer/Voicemail) and payment outcome are recorded on the appointment
Payment Status Tracking, Webhooks, and Write-Back
Given the payment gateway is configured with signed webhooks to SmileCue When a payment is authorized and captured, fails, or expires Then SmileCue verifies webhook signature and idempotency key before processing And updates the appointment record fields: deposit_status (Pending/Paid/Failed/Expired/Refunded/Partial), amount_paid, payment_id, paid_at And emits analytics events for DepositRequested, DepositPaid, DepositFailed, DepositExpired with practice, appointment, playbook, and channel metadata And marks the Deposit Request step as Completed (Paid) or Failed/Expired and advances or branches the playbook accordingly And no duplicate updates occur for replayed webhooks
Retry Cadence, Stop Conditions, and Compliance Guards
Given the playbook retry policy is set to up to 3 attempts every 12 hours, respecting quiet hours 8pm–8am local, and not past due-by When the deposit remains unpaid after the first attempt Then the system schedules and sends retries per cadence with unique message IDs and variant templates And retries stop immediately upon deposit status = Paid, patient opt-out, channel consent revoked, or appointment canceled And retries pause on appointment reschedule and resume with recalculated due-by and updated content And all attempts are logged with timestamp, channel, delivery status, and template version
Confirmation Gate and Staff Visibility
Given the appointment requires a deposit and the due-by has not passed When the deposit is Paid Then the system unlocks the confirmation branch (e.g., double-confirm) and sends the appropriate confirmation message And the appointment UI shows Deposit Paid with amount and timestamp; if Unpaid past due-by, it shows Deposit Overdue and raises an in-app alert to staff And no confirmation is sent while deposit status is Pending/Failed/Expired And analytics reflect conversion rates from DepositRequested to Confirmed
Channel Fallback and Double-Confirm
"As a scheduler, I want the system to escalate and confirm through multiple channels so that high-risk appointments are reliably confirmed."
Description

Orchestration logic that retries across channels when primary messages fail or are ignored, escalating to voice or alternate channels as defined. Supports double-confirm steps that require two independent confirmations for certain risk tiers, with anti-spoof tokens and confirmation logging. Provides delivery/error telemetry and blackout windows to avoid off-hours outreach.

Acceptance Criteria
SMS Hard Bounce to Voice Fallback with Telemetry
Given a playbook with fallback order [SMS -> Voice] and the patient has voice consent When the initial SMS attempt returns a provider hard-bounce error code Then the system suppresses further SMS retries for this step And initiates a voice call within 5 minutes unless within a blackout window And records telemetry for both attempts including channel, timestamp, provider/status code, attempt number, and correlation ID Given the hard-bounce occurs during a blackout window When scheduling the fallback Then the system schedules the voice call at the next permitted window start And logs scheduled_at and reason=blackout
No-Response Escalation Timing and Cancellation
Given escalation thresholds are configured SMS->Email at 4h and Email->Voice at 20h with max 1 attempt per channel per step When no confirmation is received within a threshold Then the next channel is sent at or within ±2 minutes of the configured threshold And all timers are canceled immediately upon a confirmation event on any channel Given a confirmation arrives after the next channel has been sent but before its own threshold When processing the confirmation Then further escalations are halted And the late confirmation is logged with channel and token_id
Double-Confirm for High-Risk Appointments
Given an appointment is tagged High risk requiring 2 confirmations and two unique anti-spoof tokens are issued When the patient completes two confirmations using two distinct valid tokens (any channel) within 24 hours Then the appointment status updates to Confirmed(2/2) And both confirmation events are logged with channel, token_id, and timestamp Given only one valid confirmation is received before the 24-hour window expires When the window elapses Then the status remains Pending(1/2) And the playbook resumes per configuration Given a token is reused, expired, or invalid When a confirmation attempt is made Then it is rejected and logged with reason
Anti-Spoof Token Integrity and Security
Given confirmation tokens are HMAC-SHA256 signed with a per-tenant key, single-use, and have a 15-minute expiry from issuance When a confirmation is submitted Then only a token with a valid signature, unexpired, and unused is accepted Given 5 consecutive invalid token submissions from the same IP/ANI within 10 minutes When processing further attempts from that source Then confirmation attempts are rate-limited for 30 minutes And a security alert is raised Given a token is accepted When persisting logs Then only a non-reversible token hash is stored and the raw token is never persisted
Blackout Windows and Timezone Respect
Given practice blackout windows are set to 20:00–08:00 local to the patient's timezone and voice-permitted hours are 09:00–19:00 When a fallback is due during a blackout Then the system delays the send until the next permitted time in the patient's timezone, handling DST transitions correctly Given a patient has no timezone on file When scheduling Then the system defaults to the practice timezone And logs timezone_source=practice Given a message is delayed due to blackout When it is eventually sent Then telemetry reflects due_at, sent_at, and delay_reason=blackout
Telemetry Surfaces: API and Dashboard Freshness
Given a notification step with multiple channel attempts When viewing telemetry via API or dashboard Then each attempt shows channel, status (queued|sent|delivered|failed), provider code, attempt number, timestamps, and correlation ID And the data is available within 60 seconds of the provider callback Given a user exports telemetry for a date range When generating a CSV Then the file includes the above fields, excludes message bodies/PHI, and is produced within 60 seconds

Confidence Tuner

A sensitivity slider with a what-if simulator that projects chairs saved, extra outreaches sent, and expected confirmation lift by cohort. Managers can tailor aggressiveness by provider, appointment type, or clinic, reducing false alarms and outreach fatigue while maximizing schedule protection.

Requirements

Granular Sensitivity Slider with Scope Overrides
"As an office manager, I want to adjust reminder aggressiveness by provider and appointment type so that I can reduce no-shows without overwhelming patients with unnecessary outreach."
Description

Implement a configurable sensitivity slider (0–100 with labeled presets: Conservative, Balanced, Aggressive) that maps to outreach trigger thresholds for no‑show risk and reminder branching. Support inheritance and overrides at multiple scopes (global, clinic, provider, appointment type), with real-time validation of conflicts and a draft/publish model. Changes must apply without service downtime and expose a deterministic mapping from slider position to system parameters (e.g., risk score thresholds, retry cadence, channel escalation) so outcomes are traceable. Provide preset management, default baselines per cohort, and guard against invalid combinations. Ensure accessibility, responsive UI, and audit-safe persistence in a HIPAA-compliant store.

Acceptance Criteria
Deterministic slider-to-parameter mapping (global)
- Given the published global slider position is 0, 25, 50, 75, or 100, When GET /v1/sensitivity/mapping is called, Then the API returns risk_threshold, retry_cadence, and channel_escalation values that match the published mapping spec exactly on every call. - Given two identical requests executed within 5 minutes, When comparing mapping_version and values, Then they are identical. - Given slider position increases, When computing the mapping, Then risk_threshold is non-increasing, total_outreaches_per_7_days is non-decreasing, and first_escalation_channel occurs at the same or earlier step. - Given a publish event, When querying the audit log by version id, Then an immutable record exists with user_id, scope, old_value, new_value, derived parameters, and a UTC timestamp (second precision).
Scope inheritance and overrides with real-time conflict validation
- Given no overrides, When evaluating an appointment, Then the effective mapping equals the global configuration. - Given a clinic override exists, When evaluating an appointment in that clinic, Then the clinic override applies unless a provider or appointment-type override exists. - Given a provider override exists, When evaluating that provider's appointment, Then the provider override supersedes clinic and global. - Given an appointment-type override exists, When evaluating that appointment type, Then the appointment-type override supersedes provider, clinic, and global. - Given two overrides at the same scope target the same entity, When saving the draft, Then a conflict is surfaced within 300 ms and Publish is disabled until resolved. - Given the "View effective config" tool is opened for a specific appointment, When displayed, Then each parameter shows its resolved value and the source scope label.
Draft/publish workflow with zero-downtime apply
- Given a draft is saved, When live decisions execute, Then no live mapping changes occur until Publish. - Given a draft is published, When new outreach decisions begin within 60 seconds, Then they use the new mapping_version while in-flight decisions continue with the previous version. - Given a publish occurs, When monitoring service health, Then no API endpoint shows >1% error rate above baseline in the next 5 minutes and no process restarts are required. - Given a bad publish is detected, When rollback to the last good version is requested, Then rollback completes within 60 seconds and is fully audit logged.
Preset management and cohort baselines
- Given built-in presets Conservative, Balanced, and Aggressive, When selected, Then slider positions and mapped parameters match the published spec. - Given an admin creates a custom preset with a unique name and slider position, When saved, Then it becomes selectable at global, clinic, provider, and appointment-type scopes. - Given a cohort baseline is set for a clinic, provider, or appointment type, When a new entity for that cohort is created, Then the baseline preset or value applies automatically within 60 seconds. - Given a preset is referenced by any scope, When attempting to delete it, Then deletion is blocked and all references are listed. - Given a preset is updated, When publishing changes, Then all referencing scopes are updated atomically under a new mapping_version.
Guardrails for invalid sensitivity combinations
- Given a draft configuration yields retry_cadence intervals <5 minutes or >72 hours, When validating, Then Publish is blocked and a specific error is shown. - Given channel_escalation includes a disabled or unavailable channel for the target cohort, When validating, Then the channel is skipped or Publish is blocked per policy and an explanation is displayed. - Given any parameter violates monotonicity or creates mutually exclusive rules (e.g., escalation step precedes first contact), When validating, Then an error is shown and Publish is blocked. - Given validation errors exist, When attempting to Publish, Then the Publish action is disabled and the error count is displayed.
Accessible, responsive slider and simulator UI
- Given a keyboard-only user, When navigating to the slider and simulator controls, Then all controls are operable via keyboard with visible focus and ARIA labels describing current values. - Given a screen reader user, When adjusting the slider, Then the current numeric value, preset label, and effective scope are announced. - Given a 320–1920 px viewport, When loading the page, Then layout reflows without horizontal scrolling and all controls remain usable. - Given automated accessibility tests (axe or equivalent), When executed on the page, Then no WCAG 2.2 AA violations are reported for color contrast, name/role/value, or focus order.
Audit-safe HIPAA-compliant persistence and access control
- Given a configuration change is published, When stored, Then the record is written to an immutable, append-only audit log with encryption at rest (AES-256) and in transit (TLS 1.2+). - Given a user without ConfigManage role, When attempting to create, edit, or publish configurations, Then access is denied and the attempt is audit logged. - Given an auditor requests the last 30 days of configuration changes by scope, When querying, Then results return within 2 seconds for up to 1000 records and include user_id, scope, before/after values, version id, and timestamp. - Given logs are generated, When reviewing, Then no PHI or patient identifiers appear in configuration or audit records.
What‑if Outcome Simulator
"As a practice manager, I want to preview the impact of different confidence levels so that I can choose settings that protect the schedule without causing outreach fatigue or added costs."
Description

Provide an interactive simulator that projects expected impact of a proposed sensitivity setting over a selectable lookback window using historical data and current schedule. Surface projected chairs saved (hours), additional outreaches sent (by channel), confirmation lift by cohort, cost vs ROI, and 95% confidence intervals. Allow filters by clinic, provider, appointment type, days-to-appointment, and patient segment. Include scenario comparison (side-by-side) and exportable summaries. Calculations must be explainable (display key assumptions), privacy-preserving (aggregate outputs only), performant (<3s for typical clinics), and consistent with production models. Support sandbox mode that does not alter live outreach until published.

Acceptance Criteria
Projection Metrics Accuracy and Coverage
Given a selected lookback window (e.g., 90 days) and a sensitivity setting applied to the simulator When the user runs the simulation for the currently loaded schedule horizon Then the results include: chairs_saved_hours, outreaches_sent_by_channel (SMS, Email, Voice), confirmation_lift by cohort, cost, ROI, and 95% confidence intervals for each metric And each metric displays lower_bound <= point_estimate <= upper_bound And chairs_saved_hours equals the sum of predicted prevented no-show appointment durations and is rounded to 0.1 hours And outreaches_sent_by_channel values are non-negative integers and sum to total_outreaches And confirmation_lift by cohort is provided for each enabled cohort dimension in the selected scope And ROI is displayed as a percentage and derived from incremental confirmations and channel costs And point estimates are consistent with production model outputs for the same inputs within ±2% or fall within the displayed 95% CI And no metric displays NaN/Infinity; missing or suppressed values render as "—"
Filterable Cohort Analysis with Privacy Safeguards
Given the simulator is loaded with data for one or more clinics When the user applies filters for clinic, provider, appointment type, days-to-appointment range, and patient segment Then all displayed metrics recompute to reflect the intersection of the selected filters And the active filters are visible as removable chips and persist across tabs within the simulator session And the appointment count after filtering is displayed to the user And combined filters behave as logical AND and clearing a filter immediately reverts the results And cohort breakdown tables reflect only cohorts present in the filtered data And any cohort slice with fewer than k=20 appointments in the lookback or upcoming window is suppressed or rolled up, and no patient-level identifiers are shown anywhere
Scenario Comparison Side-by-Side
Given two or more saved scenarios with differing sensitivity settings and/or filters When the user opens the comparison view and selects up to three scenarios Then the simulator displays metrics for each scenario side-by-side using the same definitions and time windows And a delta column appears relative to the pinned baseline scenario showing absolute and percent differences for each metric And changing the pinned baseline immediately updates all delta calculations And updating a scenario parameter (e.g., sensitivity) recomputes and refreshes only that scenario’s column And color cues indicate positive (green) vs negative (red) deltas consistently across metrics
Exportable Summaries
Given a computed scenario or comparison view is visible When the user selects Export Then CSV and PDF exports are generated within 5 seconds without blocking the UI And exported files include: selected filters, scenario parameters (sensitivity, lookback, schedule horizon), timestamp, user, model version, and data scope And exported metrics include aggregated totals and cohort breakdowns with 95% confidence intervals and consistent number formatting And no patient-level or PHI data is included; only aggregates appear And exported numbers match on-screen values within rounding rules
Explainability and Assumptions Disclosure
Given scenario results are displayed When the user opens the Assumptions or Info panel Then the simulator displays key assumptions including: outreach cost by channel, average revenue/benefit assumptions, mapping from prevented no-shows to chairs_saved_hours, sensitivity definition, lookback window, throttle/dedup rules, and production model version/date And each metric has an accessible tooltip or details view showing the calculation formula and inputs used And recomputing the scenario after changing an assumption (where editable) updates the displayed metric values accordingly and logs the change And displayed calculations reconcile to the totals within rounding tolerance (<=0.1% difference)
Performance and Scalability
Given a typical clinic dataset (<=100k appointments in lookback, <=5k upcoming in horizon) When the user runs a simulation, adjusts the sensitivity slider, or changes filters Then median (P50) response time is <= 3 seconds and P95 is <= 5 seconds for result rendering And the UI displays a progress indicator for operations exceeding 1 second And up to 5 concurrent simulations per tenant complete within the stated performance targets And requests that exceed 15 seconds time out with a user-visible retry option without crashing the session
Sandbox Mode and Publish Workflow Integrity
Given sandbox mode is active When a user saves or updates a scenario Then no live outreach jobs are queued or sent, and production settings remain unchanged, with activity logs labeled as Sandbox When a user with Manager role selects Publish Then a confirmation modal summarizes the proposed changes and projected impact, and publishing applies the settings to production, records an audit log (who, when, what), and keeps historical sandbox versions And users without sufficient permissions cannot publish and see an appropriate error state And live outreach using the new settings only begins after the publish timestamp and can be rolled back to the previous version from the audit history
Cohort Configuration & Targeting Rules
"As a regional operations lead, I want to define cohorts that reflect our workflows so that tuning and projections match how different patient groups behave."
Description

Enable creation and management of cohorts that drive tuning and simulation: provider, appointment type, clinic/location, new vs returning patient, historical no‑show risk band, days-to-appointment, time-of-day/day-of-week, and preferred channel. Provide rule builder with AND/OR logic, validation, and preview of impacted appointments. Seed common cohorts and allow cloning. Ensure HIPAA-compliant handling of attributes, respect patient communication preferences and exclusions, and expose APIs to fetch cohort definitions for downstream services. Persist versioned cohort definitions with backward compatibility for past simulations.

Acceptance Criteria
Cohort Rule Builder: Attributes and AND/OR Grouping
Given I open the Cohort Builder, When I add rules for provider, appointment type, clinic/location, new vs returning patient, historical no‑show risk band, days‑to‑appointment, time‑of‑day/day‑of‑week, and preferred channel, Then each attribute is available with appropriate operators (is/is not, in/not in, between, before/after, contains). Given I create grouped rules with parentheses mixing AND and OR up to 3 nesting levels, When I preview, Then the evaluated result matches the expected boolean logic for test fixtures including overlapping and disjoint sets. Given I compose equivalent rules with different ordering, When I preview, Then the resulting membership count is identical. Given I save the cohort, When I reopen it, Then all rules, groupings, and operators persist unchanged.
Rule Validation and Error Messaging
Given a rule is incomplete or has invalid values (e.g., empty list, type mismatch, inverted ranges), When I attempt to preview or save, Then inline validation messages identify the exact fields and the Save action is disabled. Given a days‑to‑appointment range, When the min > max, Then validation prevents save and suggests swapping bounds. Given time‑of‑day/day‑of‑week windows, When boundaries are set, Then inclusivity is clearly indicated and validated (start <= end) with examples. Given an unknown attribute or operator is referenced (e.g., via imported JSON), When I load it, Then the builder rejects it with a descriptive error and no partial save. Given validation errors exist, When all errors are resolved, Then the error state clears immediately and Preview/Save become enabled.
Preview of Impacted Appointments (Privacy‑Preserving)
Given a valid cohort definition, When I click Preview, Then I see the total count of impacted upcoming appointments and a sample list of 20 records without PHI (no phone, email, full DOB; patient name reduced to initials) alongside provider, clinic, appointment type, date/time, and risk band. Given I change any rule, When I click Preview again, Then the count and sample refresh within 2 seconds for datasets up to 25k upcoming appointments. Given pagination controls, When I navigate, Then additional sample pages load without exposing PHI and maintain filter consistency. Given patient communication preferences or exclusions filter out members, When I preview, Then I also see counts for Included and Excluded by Preferences with tooltips explaining exclusion reasons.
Seeded Cohorts and Cloning
Given a new workspace, When the feature is first enabled, Then at least five common cohorts are pre‑seeded and visible (e.g., High No‑Show Risk, New Patient, Hygiene Recall, Provider‑Specific, Channel‑Preference). Given a seeded or custom cohort, When I click Clone, Then a new cohort is created with identical rules and metadata (excluding IDs) and the name is set to "Copy of <original>" (or "Copy (n) of <original>" on collision). Given cloning completes, When I open the clone, Then all rules, groupings, and operators match the source and the clone is independent for further edits. Given create/clone/update actions, When they occur, Then an audit entry records actor, timestamp, action, and cohort/version identifiers.
Enforcement of Patient Preferences and Exclusions
Given a cohort includes channel‑based targeting, When patients have opted out of that channel or are on do‑not‑contact/exclusion lists, Then those patients are excluded from cohort membership used for outreach by default. Given exclusions are applied, When I preview or export membership, Then excluded counts are shown and excluded records are not included in any downloadable or API results. Given an attempt is made to override patient communication preferences at the cohort level, When saving, Then the system blocks the change and displays a message directing use of permissible channels only.
Cohort Definitions API (Read‑Only)
Given a service account with cohort.read scope, When it requests the Cohort Definitions API, Then it receives 200 responses containing id, name, status, currentVersion, versions[], rules (attribute, operator, values, grouping), createdAt, updatedAt, and owner metadata without any patient identifiers. Given missing or insufficient authorization, When the API is called, Then 401/403 is returned with no body containing cohort details. Given large result sets, When listing cohorts, Then responses are paginated and include ETag/Last‑Modified headers for caching. Given a specific version is requested, When the version exists, Then the API returns that immutable version; When it does not, Then the API returns 404.
Versioned Cohort Definitions and Backward Compatibility
Given an existing cohort at version N, When I edit and save, Then a new immutable version N+1 is created and version N remains readable and selectable. Given simulations executed with version N, When I view those historical simulations after newer versions exist, Then they continue to reference version N and produce unchanged membership/results. Given I need to revert, When I select an older version to restore, Then a new version is created with identical rules to the selected version and becomes the latest. Given the cohort list, When displayed, Then it shows the latest version number and last edited timestamp for each cohort.
Outreach Fatigue Guardrails & False Alarm Controls
"As a compliance-minded office manager, I want automatic caps and suppression rules so that patients aren’t spammed and we stay compliant while still protecting the schedule."
Description

Implement platform-level guardrails that cap total outreaches per patient per time window, enforce suppression windows after confirmations, rotate channels to minimize fatigue, and automatically suppress patients who opt out or reach do-not-contact limits. Track and report false alarms (high-risk triggers that did not require extra outreach) and feed this signal back to suggest less aggressive settings. Provide configurable thresholds by cohort, conflict detection with existing campaign rules, and real-time enforcement within the sending pipeline. All guardrails must be auditable and HIPAA-compliant.

Acceptance Criteria
Cohort-Based Outreach Cap Enforcement
- Given a patient belongs to a cohort with cap=N messages per D-day rolling window - When the sending pipeline evaluates a candidate outreach that would exceed N within D days - Then the outreach is blocked and the suppression reason cap_exceeded is attached to the message record - And a metric guardrail.cap_exceeded is incremented with cohort_id, channel, and rule_version tags - And the Outreach Queue UI displays Suppressed by guardrail: cap_exceeded (N/D rolling) within 5 seconds - And if multiple cohort caps apply, the most restrictive cap is enforced - And when cross_channel=true for that cohort, the cap counts all channels; otherwise it counts only the candidate channel
Post-Confirmation Suppression Window
- Given an appointment is in Confirmed status - And a cohort-specific suppression window S hours is configured post-confirmation - When any outreach for that appointment is evaluated within S hours of the latest confirmation - Then the outreach is suppressed with reason post_confirm_suppression - And if the appointment is rescheduled and reconfirmed, the suppression window resets from the new confirmation timestamp - And transactional updates explicitly whitelisted for compliance are allowed and logged with reason post_confirm_exception
Channel Rotation to Minimize Fatigue
- Given channel_rotation is enabled with order=[SMS, Email, Voice] and min_gap_per_channel=G hours - When selecting the next outreach channel for a patient-appointment - Then the system chooses the first channel in order that has not been used within G hours for that patient-appointment - And if no channel meets the gap requirement, the outreach is handled per on_no_channel policy (defer or suppress) and recorded accordingly - And the selected channel is recorded on the message with rotation_sequence index for auditability - And no single channel is used more than R times within a D-day window when rotation_max_per_channel=R is configured
Opt-Out and Do-Not-Contact Suppression
- Given a patient has sent STOP (SMS), clicked unsubscribe (Email), is flagged Do Not Contact, or has reached per-channel DNC limit L within T days - When any outreach is evaluated - Then global opt-out suppresses all channels; per-channel opt-out suppresses only that channel - And an opt-out confirmation, where permitted, contains no PHI and uses standard copy: You will no longer receive messages from SmileCue. Reply START to opt back in. - And no further outreach is attempted until explicit re-opt-in is captured and verified (double opt-in for SMS) - And all suppressions are recorded with reason codes opt_out_global, opt_out_channel, or dnc_limit_reached
False Alarm Tracking and Confidence Tuner Feedback
- Given a high-risk trigger is raised for a patient-appointment - And the appointment is already confirmed or remains confirmed without additional outreach for W hours (configurable) - When the system would schedule an extra outreach but none is sent (due to guardrails or campaign design) - Then a False Alarm event is recorded with cohort_id, trigger_type, rule_version, timestamp, and outcome - And False Alarm rate by cohort is computed daily over the last 14 days with n>=50 triggers - And if False Alarm rate > F% (configurable), the Confidence Tuner surfaces a recommendation to reduce aggressiveness one level for that cohort with an explanation and projected impact - And the recommendation is visible in the Tuner UI within 24 hours and can be accepted or dismissed, with actions logged
Campaign Rule Conflict Detection and Enforcement
- Given a campaign rule schedules outreaches that would violate any active guardrail - When the campaign is created or updated - Then preflight validation flags each conflict with guardrail name, affected cohort, and first expected violation time - And on send-time, guardrail enforcement takes precedence and conflicting messages are suppressed with specific reason codes; no duplicate sends occur - And a warning is displayed in Campaign Diagnostics within 10 seconds and an event is emitted to the audit log
Real-Time Guardrail Enforcement and HIPAA Audit Trail
- Given the sending pipeline evaluates an outreach - When guardrail checks run - Then p95 decision latency is <= 150 ms and p99 <= 300 ms measured over a rolling 1-hour window - And every allow or deny decision writes an immutable audit record with: pseudonymized_patient_id, appointment_id, cohort_id, rule_id, decision, reason_code, evaluator_version, timestamp, trace_id - And audit logs contain no message content or diagnosis codes and are encrypted at rest (AES-256) and in transit (TLS 1.2+) - And audit records are accessible only via role-based access control and exportable within 24 hours for HIPAA audit requests
A/B and Holdout Testing for Tuning Levels
"As a data-driven practice owner, I want to test tuning options against a control so that I can adopt the best-performing setting with confidence."
Description

Add experimentation capabilities to compare different sensitivity settings against a control with randomized assignment at patient or appointment level. Support sample sizing guidance, runtime configuration, guardrails to avoid over-exposure, and measurement of primary metrics (confirmation rate, no‑show rate, chairs saved) and secondary metrics (opt-outs, patient complaints, added outreaches). Provide significance calculations, interim peeks with anti-peeking corrections, and exportable results. Experiments must honor HIPAA constraints, existing opt-out rules, and be fully reversible without data loss.

Acceptance Criteria
Randomized Assignment and Holdout Integrity
- Given an experiment with defined arms (e.g., Control, Sensitivity A, Sensitivity B) and a Holdout, When scope is set to patient-level or appointment-level, Then assignment is randomized within each configured stratum (provider, clinic, appointment type) with allocation achieved within ±3 percentage points after 500 eligible units per stratum. - Given a unit is assigned to an arm, When subsequent interactions occur during the experiment, Then the unit remains sticky to its arm unless explicitly removed by configuration change captured in audit logs. - Given a Holdout group, When the experiment runs, Then Holdout receives the default control sensitivity and is excluded from any experimental outreach variations and branching. - Given opt-outs, DNC, or HIPAA-ineligible records, When assignment is executed, Then those records are excluded from randomization and all experimental outreach while still tracked for eligibility counts. - Given assignment happens, When logging, Then immutable logs capture timestamp, unit identifier (tokenized), stratum, arm, actor/system, and version, and are queryable for audits.
Sample Size and Power Guidance
- Given baseline conversion/no-show rates and user inputs for MDE, power (≥80%), and alpha (≤0.05), When generating guidance, Then the system returns required sample size per arm (including Holdout) with assumptions and variance method clearly stated. - Given historical throughput by stratum, When guidance is generated, Then the system provides projected runtime to reach required sample sizes per stratum and overall. - Given allocation and max duration are configured, When validation runs pre-launch, Then launch is blocked with actionable errors if required sample sizes cannot be met within the configured duration at current throughput. - Given unequal allocation ratios, When guidance is generated, Then sample sizes are correctly adjusted and shown per arm. - Given expected exclusion/opt-out rates are provided or defaulted, When guidance is generated, Then inflation for ineligibles is applied and shown separately.
Runtime Configuration and Full Reversibility
- Given a user with Experiment Admin role, When they configure arms, allocation %, scope (patient vs. appointment), strata, start date, and stop rules, Then the configuration is versioned and validated before activation. - Given an active experiment, When paused or stopped, Then no new assignments are made, existing assignments remain recorded, and analytics freeze at the chosen cutoff without data loss. - Given a rollback to default control is executed, When confirmed, Then all experimental outreach variations cease within 5 minutes and the prior state is restorable from version history. - Given mid-flight changes (e.g., allocation tweak), When saved, Then a new version is created, effectivity timestamps are recorded, and analyses segment by version to prevent contamination. - Given disaster recovery is required, When restoring, Then all assignments, events, and metrics for the experiment can be replayed to the exact state as of a selected timestamp.
Exposure Guardrails and Frequency Caps
- Given clinic/provider-level caps (default: max 3 SMS, 2 emails, 1 voice per patient per 7 days) are configured, When an experimental outreach would breach a cap, Then the outreach is suppressed, the suppression reason is logged, and counts appear in an Over-Exposure Prevented widget. - Given a patient is in multiple experiments or campaigns, When scheduling outreach, Then cumulative frequency is evaluated across programs before sending and guardrails enforced. - Given guardrails suppress an outreach, When computing experiment metrics, Then denominators and numerators exclude suppressed sends and a separate suppression rate metric is reported by arm and stratum. - Given daily send ceilings per clinic are set, When allocations would exceed ceilings, Then send scheduling is throttled fairly across arms to maintain target allocation within ±5 percentage points over a rolling 7-day window. - Given opt-outs or complaint thresholds are crossed (e.g., >0.5% complaints in last 24h in any arm), When monitoring, Then the system auto-pauses the offending arm and alerts admins.
Metric Attribution and Reporting Accuracy
- Given configured attribution windows (default: events until appointment start or 72h post-last outreach, whichever comes first), When computing metrics, Then confirmation rate, no-show rate, and chairs saved are calculated per arm, per stratum, and overall with consistent denominators. - Given chairs saved, When reported, Then it equals Σ(avoided no-shows × scheduled chair time minutes) where avoided no-shows are estimated via difference-in-outcomes between arm and control within stratum. - Given secondary metrics (opt-outs, complaints, added outreaches), When reported, Then they are available per arm, per stratum, and time series with timezone-correct timestamps. - Given cancellations/reschedules, When they occur, Then attribution updates the original unit’s outcome according to business rules and backfills metrics within 15 minutes. - Given HIPAA constraints, When presenting reports, Then PHI is not displayed; identifiers are tokenized and only aggregated views are shown by default.
Significance, Interim Peeks, and Anti-Peeking Controls
- Given interim analyses are enabled, When a peek is executed, Then adjusted p-values and confidence intervals are computed using a pre-specified method (e.g., alpha-spending O’Brien-Fleming) and displayed with the current information fraction. - Given stop rules are pre-registered, When boundaries are crossed, Then the system recommends early stop for efficacy/futility and records the decision and method in an audit log. - Given multiple metrics are monitored, When significance is displayed, Then familywise error control or false discovery rate method selected pre-launch is applied and labeled. - Given sequential peeks, When users attempt unplanned peeks, Then the system applies the chosen correction and marks the peek as unplanned in the audit trail. - Given small-sample conditions, When metrics are sparse, Then exact or appropriately corrected tests (e.g., Fisher’s exact) are used and method is indicated in outputs.
Results Export, Security, and Auditability
- Given an authorized user requests an export, When generating, Then aggregated results (arm-level, stratum-level) are available as CSV and JSON with schema version, confidence intervals, p-values, and analysis method. - Given unit-level export is requested, When generated, Then patient identifiers are hashed with rotating salts, dates are shifted per HIPAA Safe Harbor policy, and a data-use warning is shown and logged. - Given exports are created, When delivered, Then they are available via secure download with time-limited links or delivered to a configured S3/SFTP destination with server-side encryption enabled. - Given the same parameters and time window, When an export is re-run, Then results are reproducible and identical to previous exports (accounting for chosen analysis cut timestamp), and a checksum is provided. - Given compliance requirements, When any export occurs, Then the event is recorded with requester, timestamp, filters, columns, and destination for audit review.
Permissions, Audit Trail, and Versioning
"As a clinic admin, I want permissions and a full change history so that only authorized staff can make adjustments and we can prove compliance during audits."
Description

Introduce role-based access controls restricting who can view, simulate, publish, and roll back tuning changes (e.g., Admin, Manager, Read-only). Record an immutable audit trail capturing user, timestamp, scope, before/after values, and rationale notes. Maintain version history for slider presets, cohort rules, and guardrails with one-click rollback and scheduled publish. Expose read-only audit APIs for compliance reviews and ensure all artifacts are stored in encrypted HIPAA-compliant storage with retention policies.

Acceptance Criteria
Role-Based Access Controls for Confidence Tuner Actions
- Given an Admin user and any scope, When they view, simulate, publish, schedule, or rollback Confidence Tuner changes, Then the action succeeds with a 2xx response and success UI state. - Given a Manager assigned to specific providers/appointment types/clinics, When they attempt to publish or rollback outside their assigned scope, Then the action is denied with 403 and an audit record is created; When within scope, Then the action succeeds with 2xx and is audited. - Given a Read-only user, When they attempt to simulate, publish, schedule, or rollback, Then UI controls are disabled and API requests return 403; When they view configurations and audit logs, Then read-only data is displayed without mutation endpoints. - Given a role change in the identity system, When the change is saved, Then effective permissions propagate to UI and API within 60 seconds. - Given an API access token, When used against Confidence Tuner endpoints, Then RBAC is enforced identically to the UI for all actions and scopes.
Immutable Audit Trail for Tuning Events
- Given any simulate, publish, rollback, schedule create/update/cancel, or RBAC denial event, When the event completes, Then an audit record is written containing: actionType, userId, role, tenantId, scope (provider/appointmentType/clinic), timestamp (UTC ISO-8601), beforeValues, afterValues, rationaleNotes (<=1000 chars), origin (UI/API), correlationId, outcome (success/denied/error). - Given tenant users, When they attempt to modify or delete an audit record, Then the request is rejected with 403 and a new audit entry records the denial; only system retention jobs may purge per policy. - Given a new audit record, When 5 seconds have elapsed, Then it is retrievable via UI and API search/filter by date range, user, actionType, outcome, and scope. - Given stored audit records, When integrity verification is performed, Then each record validates via cryptographic hash/signature chaining; any tampering attempt causes verification to fail and is alerted. - Given system time synchronization, When events are logged, Then inter-record clock skew is <= 2 seconds across services.
Version History with One-Click Rollback
- Given any change to slider presets, cohort rules, or guardrails, When the change is saved or published, Then a new immutable version is created with metadata (versionId, author, timestamp, scope, changeSummary) and linked diff of changed fields. - Given a prior version and appropriate permission, When one-click rollback is invoked, Then the selected version becomes active within 30 seconds and a new version is created capturing the rollback event and rationale. - Given version history, When listed via UI or API, Then complete lineage is returned in order, with field-level diffs visible and downloadable. - Given RBAC constraints, When a rollback is attempted outside the user's assigned scope, Then the attempt is denied with 403 and audited; When within scope, Then rollback succeeds. - Given active sessions, When a version changes, Then all clients reflect the new effective configuration within 60 seconds.
Scheduled Publish of Tuning Changes
- Given a user with publish permission, When they schedule a configuration to go live at a future datetime in the tenant’s timezone, Then scheduling a past time is blocked with validation 400 and an explanatory error. - Given an accepted schedule, When the scheduled time is reached, Then the publish executes within +/- 60 seconds without requiring user presence, creating a new version and audit entry that links to the schedule. - Given a future schedule, When the creator (or Admin) edits or cancels it prior to T-5 minutes, Then the change succeeds and is audited; When within T-5 minutes, Then edits are blocked with 409 and only cancel is permitted. - Given overlapping schedules targeting the same scope and setting window, When a user attempts to save, Then the system prevents the conflict and returns 409 with guidance; non-overlapping schedules save successfully. - Given a scheduled publish failure (e.g., validation/regression check), When it occurs, Then the system aborts the publish, logs the error, alerts the scheduler via email, and leaves the prior version active.
Read-Only Audit APIs for Compliance Review
- Given a compliance client with valid OAuth2 read:audit scope, When it calls GET /audit/events with filters (dateRange up to 93 days, userId, actionType, scope) and pagination (cursor, limit<=1000), Then the API returns 200 with tenant-isolated, paginated results matching an agreed schema and signed checksum. - Given any request using POST, PUT, PATCH, or DELETE on audit endpoints, When executed, Then the API responds 405 or 403 and no data is modified. - Given invalid or insufficient credentials, When requesting audit endpoints, Then responses are 401 (unauthenticated) or 403 (unauthorized) with no data leakage. - Given high request volume, When rate > 600 requests/min per tenant, Then the API returns 429 with Retry-After; below the limit requests succeed consistently with p95 latency <= 500 ms for 1k-record pages. - Given new audit events, When queried, Then data freshness is <= 5 seconds from event time to API availability, and monthly availability of the audit API is >= 99.9%.
HIPAA-Compliant Encryption and Retention Policies
- Given any artifact (audit record, version snapshot, schedule, presets, rules, guardrails), When stored at rest, Then it is encrypted with AES-256 (or FIPS 140-2 validated equivalent) and when transmitted, Then TLS 1.2+ is enforced end-to-end. - Given key management, When keys are rotated, Then KMS rotates at least every 90 days; keys are tenant-isolated or properly segmented, and key access is audited. - Given backups and replicas, When created, Then they are encrypted with the same controls and stored in HIPAA-compliant storage. - Given retention settings, When default policies apply, Then artifacts are retained 6 years unless a tenant-specific policy overrides; upon expiration, purge occurs within 30 days unless on legal hold; all purges are auditable. - Given export requests, When fulfilled, Then outputs are encrypted (AES-256) with a customer-supplied passphrase and delivered over a secure channel; exported data respects scope and retention limits.
Scope-Based Configuration Targeting and Enforcement
- Given an action (simulate, publish, rollback, schedule), When initiated, Then explicit scope selection (provider, appointment type, clinic) is required; an "All" scope must be explicitly chosen and is never the default. - Given a Manager with assigned scopes, When they target any action outside those scopes, Then the system blocks the action with 403 and creates an audit entry; When within scope, Then the action proceeds. - Given a scoped publish, When completed, Then only the targeted scope’s cohorts change; automated regression checks confirm no changes in unrelated scopes. - Given changes to scope membership (e.g., provider added to a clinic), When synchronized from the source of truth, Then permission and targeting enforcement reflect the update within 5 minutes. - Given identifiers for scopes, When entities are deleted or renamed, Then historical audit and version records retain referential integrity via immutable IDs and readable former names.
Practice Management Integration for Tuner & Simulator
"As an operations manager, I want the tuner and simulator to use our live schedule and preferences so that projections and outreach behavior reflect reality across all clinics."
Description

Integrate the tuner and simulator with existing schedule data pipelines (e.g., Dentrix, Open Dental, Eaglesoft) to fetch real-time appointment data, provider rosters, and patient communication preferences. Ensure near-real-time sync (≤5 minutes), idempotent processing, resiliency to outages (queueing, retries, backfill), and accurate mapping between external entities and internal cohorts. Write back non-PHI flags/notes where supported to indicate applied tuning. Provide health dashboards and alerts for data freshness to guarantee simulator accuracy and safe rollout.

Acceptance Criteria
Near-Real-Time Schedule Sync (≤5 min SLA)
Given SmileCue is connected to a supported PMS (Dentrix/Open Dental/Eaglesoft) with valid credentials When a new appointment is created, updated, or canceled in the PMS Then the change appears in SmileCue within 5 minutes at p95 and within 10 minutes at p99 and is available to the Tuner and Simulator APIs And provider roster changes propagate within the same SLA And patient communication preference changes propagate within the same SLA And per-domain freshness timestamps are updated and visible to observability endpoints
Idempotent Event Processing and Safe Replays
Given duplicate webhook events or batch reimports for the same external record IDs within a 24-hour window When the integration processes these events Then no duplicate appointments, providers, or preference records are created and the final state reflects last-write-wins by authoritative PMS update timestamp And reprocessing the last 30 days of data completes without side effects or duplication And downstream tuner/simulator projections remain unchanged after a no-op replay
Outage Resiliency: Queueing, Retries, and Backfill
Given the PMS API becomes unavailable or returns transient errors When ingestion attempts fail Then events are queued durably and retried with exponential backoff up to 10 attempts over 24 hours And unrecoverable events are routed to a dead-letter queue with metadata for diagnosis And upon recovery the backlog is drained at a sustained rate ≥ 2,000 records/minute until data lag < 5 minutes And a manual backfill job can restore a specified date range without downtime
Accurate Mapping to Internal Cohorts
Given provider, appointment type, clinic/location, and operatory codes from the PMS When mapping rules are applied Then 100% of in-scope records have either a mapped cohort or an explicit Unmapped status with reason And mapping coverage is ≥ 98% over a 24-hour window with no critical cohort missing And mapping rules are versioned with audit logs (who, when, what changed) And unmatched rate > 1% over any rolling 15 minutes triggers an alert
Write-Back of Non-PHI Tuning Flags/Notes
Given the PMS supports notes or custom fields via API When the Confidence Tuner applies settings that affect an appointment Then a non-PHI flag/note is written in standardized format including tuner version, rule ID, and ISO-8601 timestamp And write-backs succeed ≥ 99% and complete within 5 seconds at p95 with retries on transient failures And no PHI (e.g., names, phone numbers, diagnoses) is included in the payload And if write-back is unsupported, the operation is skipped gracefully and logged without blocking tuning
Health Dashboard and Alerting for Data Freshness
Given the integration is operating When a user or on-call views the integration health dashboard Then it shows per source: last successful sync time, current lag (minutes), error rate, backlog size, dead-letter queue size, and mapping coverage And alerts are sent when lag > 5 minutes for 10 consecutive minutes, error rate > 2% over 15 minutes, or unmapped > 1% over 15 minutes And alerts include source, metric, threshold, current value, and a link to the runbook And acknowledgements are recorded with user and timestamp
Simulator Data Fidelity and Safe Rollout Gate
Given a user opens the Simulator for a selected provider/clinic/cohort When underlying schedule or preference data are older than 10 minutes or mapping coverage < 98% Then the Simulator blocks projections and displays a freshness warning with a retry option And when thresholds are met the Simulator uses the latest snapshot (≤ 5-minute lag) and base counts match current schedule within ≤ 1% variance And rollout of new tuning configs is blocked unless freshness, mapping coverage, and write-back capability checks pass

Smart Deposits

For high-risk, high-value appointments (surgery, long procedures), automatically triggers a polite, timed deposit request via secure link or staff-assisted call. Eligibility rules, insurance exceptions, and compassionate waivers maintain patient goodwill while cutting last-minute no-shows that waste premium chair time.

Requirements

Deposit Eligibility & Risk Rules Engine
"As an office manager, I want deposit eligibility to be determined automatically based on our policies and patient risk so that we reduce no-shows without burdening low-risk or fully insured patients."
Description

Configurable rules engine that evaluates appointment metadata and patient history to decide when a deposit request should be triggered. Inputs include appointment type and duration, provider utilization, estimated cost, time-to-appointment, patient no-show/cancellation history, insurance coverage/pre-authorization status, and practice-level policy thresholds. Provides a UI to author AND/OR rules, reusable templates, and a test/simulator to preview outcomes. Evaluates in real time at booking and on subsequent changes, producing a structured decision with reason codes for audit and message personalization. Supports compassionate waiver flags, regulatory constraints by location, and safe defaults if data is incomplete. Integrates with SmileCue’s PMS/EHR connectors and event bus for low-latency decisions.

Acceptance Criteria
Real-time Decision and Event Publishing at Booking/Update
Given a new appointment is created via PMS/EHR connector with complete metadata When the event "appointment.created" is received Then the engine returns a decision in {require_deposit, no_deposit, manual_review} within p95 ≤ 300 ms and p99 ≤ 1000 ms And the decision includes decision_version, reason_codes[], trace_id, appointment_id, and evaluated_at And the same payload is published to the event bus topic "smart-deposits.decisions" within 100 ms of decision And repeated identical events with the same appointment_id and version are processed idempotently (no duplicate downstream messages) Given an existing appointment is updated with metadata relevant to eligibility When the event "appointment.updated" is received Then the decision is re-evaluated And a new decision is published only if the outcome or reason_codes changed Given an internal engine error occurs during evaluation When the event is processed Then the engine returns decision=no_deposit with reason_codes including "ENGINE_ERROR_SAFE_DEFAULT" And the error is logged with trace_id and no PHI
Rule Authoring UI: AND/OR, Templates, Versioning
Given a practice admin with "Manage Deposit Rules" permission When they create or edit a rule set in the UI Then they can reference inputs: appointment_type, appointment_duration, provider_utilization, estimated_cost, time_to_appointment, patient_no_show_count, patient_cancellation_count, insurance_coverage_pct, preauthorization_status, practice_policy_thresholds, patient_compassionate_waiver_flag, location_jurisdiction And they can compose conditions using AND/OR, parentheses, comparisons (=, !=, >, <, >=, <=, IN, BETWEEN), and string/enum matches And the editor validates syntax and field availability and prevents saving invalid rule sets And they can save rule sets as reusable templates and clone them And rule sets support versioning with Draft and Active states and require explicit Publish to activate And the Active version is used for real-time evaluation immediately after Publish
Decision Simulator and What-If Preview
Given a user opens the simulator When they input test values for supported fields and select a location/jurisdiction Then the simulator returns the decision, reason_codes, matched_rule_ids, and an evaluation trace And the simulator performs no side effects (no patient communications, no event bus publish) And the simulator supports what-if comparisons by varying inputs and shows diffs of decision and reason_codes And the simulator uses the selected rule set version (Draft or Active) And simulator results match real-time engine responses for identical inputs
Safe Defaults and Missing/Delayed Data Handling
Given required data is missing or stale beyond configured TTL from external connectors When a decision is requested Then the engine applies the configured safe default decision (default=no_deposit unless overridden) and includes reason_codes listing missing_fields[] And the booking flow is not blocked and the decision returns within latency SLOs And late-arriving data is recorded but does not change the published decision unless an update event is received Given external connector timeouts or errors occur When evaluating a decision Then the engine fails open to the safe default and records connector_error codes without storing PHI
Compassionate Waiver Override and Audit
Given a patient has compassionate_waiver_flag=true and the waiver is not expired When an appointment is evaluated Then the decision is no_deposit regardless of other rule matches And reason_codes include "COMPASSIONATE_WAIVER_ACTIVE" And no deposit request messages are enqueued Given an authorized role submits a one-appointment override with justification When the override is saved Then require_deposit outcomes may proceed for that appointment And the override, user_id, timestamp, and justification are recorded in an immutable audit log Given a compassionate waiver has expired When the appointment is evaluated Then normal rules apply and reason_codes include "COMPASSIONATE_WAIVER_EXPIRED" if previously present
Insurance Coverage and Pre-Authorization Exceptions
Given preauthorization_status=Approved and estimated_patient_responsibility < minimum_deposit_threshold When evaluating eligibility Then the decision is no_deposit and reason_codes include "INSURANCE_PREAUTH_COVERS_THRESHOLD" Given the plan policy prohibits deposits for covered procedures When evaluating eligible appointments Then the decision is no_deposit and reason_codes include "INSURANCE_POLICY_PROHIBITS_DEPOSIT" Given estimated_patient_responsibility ≥ minimum_deposit_threshold and no prohibitions apply When evaluating eligibility Then a require_deposit decision may be returned per configured rules and the triggering rule_id is included in reason_codes
Location-Based Regulatory Constraints Enforcement
Given appointment.location_jurisdiction prohibits deposits for specified appointment types When evaluating eligibility Then the decision is no_deposit and reason_codes include "REGULATORY_PROHIBITION" And the rule editor blocks publishing rule sets that would require deposits for prohibited combinations and displays validation errors Given a jurisdiction requires pre-disclosure language prior to requesting deposits When a require_deposit decision is produced Then reason_codes include "REGULATORY_DISCLOSURE_REQUIRED" for downstream message personalization Given jurisdictional constraints are updated with an effective_date When the effective_date is reached Then evaluations honor the new constraints and decision_version reflects the constraint metadata
Secure Deposit Payment Links & Compliance
"As a patient, I want a secure, simple way to pay my deposit from my phone so that I can confirm my appointment without calling the office."
Description

Generation of expiring, single-use, HMAC-signed payment links that avoid PHI, directing patients to a branded, mobile-first payment page. Supports major cards, Apple Pay/Google Pay, HSA/FSA where applicable, and 3-D Secure. Uses a PCI-DSS compliant processor with tokenization; SmileCue stores only tokens and transaction metadata. Enforces HIPAA-aligned practices (no PHI in messages/URLs, access logging, BAAs with vendors), plus rate limiting, CAPTCHA, and identity verification via one-time code or DOB/ZIP check. Handles partial deposit amounts, sliding scales, multi-currency, taxes, and receipts via the patient’s preferred channel. Implements webhook retries and idempotency for resilient posting, WCAG 2.1 AA accessibility, multilingual support, and link expiry/reissue flows.

Acceptance Criteria
HMAC-Signed, Expiring, Single-Use Payment Link (No PHI)
- Given a deposit is requested for an eligible appointment When a payment link is generated Then the link token is HMAC-SHA256 signed using a server-side secret and embeds an expiry timestamp - Given a payment link is generated When the URL is inspected Then it contains no PHI and only an opaque token and non-sensitive branding - Given a valid unused link within its TTL When the patient opens it Then the token is marked as consumed and subsequent opens return 410 Gone - Given a link past its expiry time When the patient opens it Then the server returns 410 Gone and offers a reissue flow without exposing PHI - Given a tampered or invalid signature When the link is opened Then the server returns 403 Forbidden and logs the event
Mobile Payment Page: Wallets, 3-D Secure, Accessibility, Multilingual
- Given a supported mobile browser When the payment page loads Then it renders responsively and meets WCAG 2.1 AA keyboard navigation, focus order, labels, and color contrast requirements - Given device and merchant configuration support Apple Pay or Google Pay When the page loads Then the relevant wallet button is displayed and enabled - Given an HSA/FSA card is presented When the processor authorizes Then the payment is accepted if eligible or declined with a clear message if restricted - Given the issuer or region requires SCA When payment is attempted Then 3-D Secure is invoked and the flow completes with a success or actionable error - Given the user's locale preference is Spanish When the page loads Then all user-facing strings and currency formats are presented in Spanish - Given practice branding is configured When the page loads Then the header shows the practice name/logo without any PHI
PCI-DSS Processor and Tokenization-Only Storage
- Given a card payment is made When data is captured Then raw PAN and CVV are handled only by the PCI-DSS compliant processor via hosted fields and never pass through SmileCue servers - Given a successful authorization or charge When SmileCue stores records Then only tokens, last4, brand, expiry month/year, transaction ids, amount, currency, and non-sensitive metadata are stored; PAN/CVV are never stored - Given a stored token exists When a refund or void is requested Then the operation succeeds via the processor using the token without exposing sensitive data - Given a processor is configured When due diligence is performed Then current PCI-DSS attestation is recorded and validated - Given transport of payment or audit data occurs When connections are negotiated Then TLS 1.2+ is enforced
HIPAA Alignment: No PHI in Messages/URLs and Access Auditing
- Given SMS, email, or voice templates for deposit requests When a message is generated Then no PHI fields are allowed to render and automated checks block any PHI placeholder usage - Given a payment URL is created When the URL and referrer are evaluated Then they include no PHI in the path, query, or fragment - Given a patient accesses the payment page or completes a payment When events occur Then each event is audit logged with timestamp, pseudonymous patient reference, link id, IP, and user agent - Given vendors that process or store ePHI are used When onboarding occurs Then BAAs are executed and stored with vendor metadata - Given an auditor requests records When logs are retrieved Then access and change logs can be exported by date range without exposing PHI
Abuse Protection: Rate Limiting, CAPTCHA, and Identity Verification
- Given repeated requests for a payment link from the same IP or contact occur When thresholds are exceeded Then rate limiting returns 429 Too Many Requests with a Retry-After header - Given suspicious activity or multiple failed verifications occur When the payment page is requested Then a CAPTCHA challenge is presented with an accessible alternative - Given identity verification is required When the patient chooses OTP Then a one-time code is sent to the contact on file and access is granted only after correct entry - Given identity verification is required When the patient chooses DOB/ZIP Then access is granted only when both values match the record - Given three consecutive failed identity attempts occur When further access is attempted Then the session is locked for 15 minutes and an alert is logged
Flexible Deposits: Partial, Sliding Scale, Multi-Currency, Taxes, Receipts
- Given an appointment type has a configured deposit of 20% When the estimate is $2,000 Then the deposit due displays $400 plus applicable taxes - Given a compassionate waiver is applied by staff with a reason code When the link is issued Then the deposit amount reflects the waiver and the action is audit logged - Given the practice operates in a taxable jurisdiction When the payment page shows totals Then taxes are calculated per configuration and itemized - Given the practice currency is CAD When the page loads Then all amounts and receipts show CAD with the proper currency symbol/code - Given a payment succeeds When receipts are sent Then the receipt is delivered via the patient’s preferred channel and includes transaction id, amount, date, last4, and practice contact, with no PHI
Resilience: Webhook Retries, Idempotency, and Link Expiry/Reissue
- Given a payment event webhook is sent to SmileCue When the endpoint returns non-2xx Then the processor retries with exponential backoff for up to 24 hours and SmileCue processes the first successful delivery only - Given two identical charge requests occur within the same idempotency key window When processing occurs Then only one charge is created and the subsequent request returns the original result - Given a webhook is delivered more than once When SmileCue handles it Then processing is idempotent and produces no duplicate side effects - Given a payment link has expired When the patient follows it Then they see an expiration message and can request a new link after identity verification - Given staff reissues a deposit link from the console When confirmation occurs Then a new link is generated and sent, and any prior link is immediately invalidated
Multi-channel Deposit Request Orchestration
"As a front desk coordinator, I want deposit requests to be automatically sequenced and adjusted based on patient responses so that I spend less time chasing confirmations."
Description

Automated, polite outreach sequence across SMS, email, and optional voice that initiates after an eligibility approval. Cadences are configurable by appointment lead time and respect quiet hours and time zones. Branching logic adapts to patient responses (paid, waiver requested, insurance exception, opt-out, unreachable), with automatic cessation upon resolution. Includes personalization tokens, pre-approved templates, and A/B testing of copy and timing. Tracks delivery, bounces, and spam signals; falls back to alternate channels when needed. Sends staff alerts when payment deadlines approach and adds calendar attachments where appropriate. Honors patient communication preferences and regulatory opt-out requirements.

Acceptance Criteria
Eligibility-Approved Appointment Triggers Time-Zoned Cadence
Given a high-risk/high-value appointment is eligibility-approved and has a 7-day lead time And the patient’s time zone and quiet hours (20:00–08:00 local) are configured And the practice’s channel order is SMS > Email > Voice (optional) When the system generates the outreach schedule Then messages are scheduled at configured offsets (T-7, T-3, T-1 at 10:00 local) in the patient’s local time And no message is scheduled or sent during quiet hours And each scheduled outreach uses a pre-approved template and renders all personalization tokens without error And the system logs channel, template ID, token render status, and intended send time for each item
Payment Completion Ceases Outreach and Confirms Receipt
Given a deposit request sequence is active for an appointment When the patient completes payment via the secure link Then all pending and future outreach steps for that appointment are immediately cancelled across all channels And a payment confirmation is sent via the patient’s preferred channel within 1 minute And staff are notified with payment amount, timestamp, and transaction ID And the appointment record status updates to "Deposit Paid" with an audit entry And no further deposit-related messages are sent for this appointment
Waiver or Insurance Exception Branching and Pause
Given a deposit request sequence is active When the patient requests a compassionate waiver or indicates an insurance exception Then the outreach sequence is paused within 1 minute And a staff review task is created with the patient’s reason, category, and a due-by time And if staff approves, the sequence is cancelled and the patient is notified with the approved template And if staff declines, the sequence resumes at the next scheduled step using the compassionate language template variant And all actions are captured in the audit log
Opt-Out and Communication Preferences Enforcement
Given patient channel preferences are on file and regulatory opt-out applies When the patient replies STOP to SMS or clicks the email unsubscribe link Then the system immediately ceases outreach on the opted-out channel and records the opt-out And sends a confirmation message where permitted by regulation And opt-out persists across future deposit sequences for that channel And alternate channels are used only if allowed by the patient’s preferences And no outreach violates quiet hours or opt-out status
Delivery Tracking and Channel Fallback with Voice Escalation
Given an outreach step is scheduled via SMS When the provider returns a hard bounce, block, or spam warning Then the system records the delivery status with provider code and timestamp And falls back to email within 15 minutes if email is permitted And if SMS and email both fail or are unavailable, a voice call task is created or auto-voice is placed per configuration And the failing channel is suppressed for 24 hours to avoid repeated failures And per-appointment, per-channel delivery metrics are available in reporting
A/B Testing of Copy and Timing
Given two or more pre-approved templates or send times are configured as variants for a cadence step When eligible outreach is initiated Then patients are randomly assigned to variants with ±5% allocation tolerance And the assigned variant remains fixed for that appointment And delivered/open/click-to-pay/payment-complete metrics are attributed to the assigned variant And reporting can compare variants over a selected date range And the system enforces a minimum sample size before indicating a leading variant
Staff Alerts Before Deadline and Calendar Attachment Inclusion
Given a payment deadline is set for the appointment When the deadline is 24 hours away and no payment is recorded and no waiver is approved Then staff receive an alert via dashboard and email with patient, appointment time, deposit amount, and last outreach status And if the next step is an email and the appointment has a calendar entry, an ICS attachment is included And alerts observe staff notification quiet hours for email but are always visible on the dashboard And once payment is recorded, pending deadline alerts for that appointment are withdrawn
Staff-Assisted Call Workflow & Scripts
"As a billing specialist, I want a guided call workflow to collect deposits securely so that I can resolve edge cases quickly and compliantly."
Description

In-app call queue for patients requiring staff-assisted deposit collection, with one-click dialing/softphone integration and dynamic call scripts tailored to appointment context, eligibility rationale, and suggested deposit amount. Captures call outcomes with standardized disposition codes (paid by phone, voicemail, refused, waiver review) and schedules follow-ups. Enables phone payments via a PCI-compliant virtual terminal that shields card data from staff while recording necessary metadata. Provides permissions, audit trails for who collected payments or granted waivers, and automatic synchronization of statuses to halt automated outreach when resolved.

Acceptance Criteria
Queue Patients Requiring Staff-Assisted Deposits
Given an appointment is flagged as high-risk/high-value and eligible for a deposit When Smart Deposits evaluates eligibility or the appointment is saved/updated Then the patient appears in the in-app call queue with appointment datetime, risk tier, suggested deposit amount, insurance/waiver flags, and last outreach attempt visible And the queue excludes items already resolved (Paid, Approved Waiver, Canceled) And items are ordered by appointment start time within priority tiers; overdue items are highlighted And each item shows an SLA target and due-by timestamp per practice settings
One-Click Dialing and Softphone Integration
Given a staff user with call permissions views a queue item When they click Call via the embedded softphone Then a SIP/WebRTC call is initiated using the practice-configured caller ID and the call start time is logged against the item And if the call connects or fails, the connection outcome and duration are recorded Given the user selects Use External Phone When they click Reveal/Copy Number or tel: link Then the event is tracked as Initiated (External) and the item is locked to the user during the attempt
Dynamic, Context-Aware Call Scripts
Given appointment context (type, duration, date/time, insurance, prior attempts) and a suggested deposit amount When the call view loads Then a dynamic script renders with patient name, appointment details, eligibility rationale, and the deposit ask amount And the script provides branching prompts for Agree to Pay, Needs Info, Insurance Exception, Financial Hardship, and Refusal And selecting a branch updates guidance in real time and enforces required talking points; free-text is limited to notes; script content is versioned
Standardized Dispositions and Follow-Up Scheduling
Given a call is completed or a disposition is selected When the user chooses a standardized code [Paid by Phone, Left Voicemail, Refused, Waiver Review, No Answer, Wrong Number, Scheduled Callback] Then required fields are enforced per code (e.g., receipt for Paid, timestamp/message for Voicemail, reason for Refused) And the system offers default follow-up presets per code and creates a task with owner and due date And the queue item status updates accordingly and cannot be closed without required data
PCI-Compliant Virtual Terminal for Phone Payments
Given the patient agrees to pay the deposit by phone When the user clicks Collect Payment Then a PCI-DSS compliant virtual terminal opens that shields PAN/CVV from staff (e.g., DTMF masking or secure input) And SmileCue stores only a payment token, auth code, amount, last-4, and payer name; no raw card data is stored or displayed And upon approval a receipt is generated and sent via SMS/email; the appointment deposit status updates to Paid and the queue item is resolved And partial payments are supported if enabled, with remaining balance shown; on failure, no PAN is retained and a retry or secure link option is provided
Role-Based Permissions and Audit Trails
Given role-based permissions are configured When a user without Collect Deposits or Grant Waivers attempts those actions Then access is denied with a clear message and no sensitive UI is rendered When a user collects a payment or grants a compassionate waiver Then the system requires rationale/fields per policy and records an immutable audit entry with user, timestamp, patient, appointment, action, before/after statuses, and metadata; admins can export and filter audit logs
Status Sync and Automated Outreach Halt
Given a deposit is paid or a waiver is approved via staff-assisted workflow When the transaction or approval is confirmed Then the appointment deposit status changes to Resolved within 5 seconds and the patient is removed from the call queue And all deposit-related automated SMS/email/voice outreach for that appointment halts; subsequent messages reflect the resolved state And updates are idempotent to prevent duplicates; reschedules/cancellations trigger re-evaluation of eligibility and queue/script refresh
Compassionate Waivers & Insurance Exceptions
"As a practice owner, I want a consistent waiver process with clear rules and documentation so that we maintain patient trust while protecting premium chair time."
Description

Lightweight approval workflow to handle compassionate waivers and insurance-based exceptions. Patients can request a waiver from the payment link; staff can initiate on behalf of patients. Captures reason categories, notes, and optional documentation, and enforces configurable policy limits (e.g., annual waiver caps, excluded procedures, public program exemptions). Routes approvals to designated roles with SLAs and notifications; upon decision, updates orchestration, sends appropriate messages, and records immutable audit entries with reason codes. Provides reporting on waiver rates, financial impact, and correlation with no-show reductions, while ensuring respectful copy and suppression of further requests after denial or approval.

Acceptance Criteria
Patient-Initiated Waiver Request via Payment Link
- Given a patient opens a Smart Deposits payment link for an eligible appointment, When they select "Request Compassionate Waiver or Insurance Exception," Then a form displays a reason category dropdown, notes (max 1000 chars), and optional file upload (PDF/JPG/PNG; up to 10 MB per file; max 3 files). - Given the patient submits valid inputs, Then a request is created within 2 seconds with unique ID, patient ID, appointment ID, reason code, notes, attachment metadata, status "Pending Review," and timestamp (UTC). - Given configured policy limits (annual cap, excluded procedures, public program exemptions), When submission violates a hard rule, Then submission is blocked with a specific rule message and no request is created. - Given configured policy limits, When submission triggers a soft warning (e.g., within 10% of annual cap), Then submission proceeds and the request is tagged "Policy Attention." - Given a request is created, Then the patient sees an on-screen confirmation and receives SMS/email confirmation within 1 minute containing request ID and next steps. - Given a request is pending, Then deposit reminders for the appointment are paused until a decision or SLA expiry, whichever occurs first. - Given the form is rendered, Then it meets WCAG 2.1 AA for labels, contrast, keyboard navigation, and error messaging.
Staff-Initiated Waiver/Exception from Dashboard
- Given an authenticated staff user with Front Desk, Billing, or Manager role, When they open the appointment and click "New Waiver/Exception," Then the request form appears with the same fields and an additional "Submitted by Staff" flag auto-populated with user ID and role. - Given the staff submits the form, Then reason category is required, notes are optional up to 1000 chars, and attachments follow the same file rules; client and server validations must pass or show field-level errors. - Given the appointment is ineligible per policy hard rules, Then submission is blocked with the specific rule cited and a link to view policy details; no request is created. - Given submission succeeds, Then an immutable audit entry records staff user ID, role, timestamp, action "Create-Staff," and a confirmation appears within 2 seconds. - Given submission succeeds, Then the patient is notified within 1 minute unless the user selects "Notify later," in which case no message is sent and the request is tagged "Patient Notify Pending." - Given a user without the required role attempts access, Then the action is denied, the attempt is logged as a security event, and no data is exposed.
Approval Routing, SLAs, and Notifications
- Given a new request is created, When routing rules (practice, location, amount threshold, reason category) are evaluated, Then the request is assigned to the correct approver group and primary approver within 5 seconds. - Given assignment occurs, Then the approver receives an in-app notification immediately and an email/SMS within 1 minute including request summary, SLA deadline, and secure link. - Given the SLA (e.g., 2 business days) elapses without decision, Then the request auto-escalates to the next approver tier and sends reminder notifications every 24 hours until decision. - Given an approver opens the request, Then they can Approve, Deny, or Request More Info; a decision reason code is mandatory and free-text notes are optional up to 1000 chars. - Given "Request More Info" is selected, Then the patient receives a secure link to provide additional info; the SLA pauses until patient response or 7 days maximum, after which it auto-resumes and escalates if needed. - Given the final decision is recorded, Then status updates to Approved or Denied, all watchers are notified, and the decision timestamp is captured.
Policy Enforcement and Deposit Orchestration Updates
- Given a request is Approved, Then the deposit requirement for that appointment is marked Waived, all future deposit reminders are suppressed, and the appointment remains confirmed or scheduled per existing workflow. - Given a request is Denied, Then deposit reminders resume on the next scheduled cadence and additional waiver requests for that appointment are disabled. - Given approval is for an insurance exception based on public program eligibility, Then the patient's profile is tagged to auto-bypass deposits per configured coverage window and procedure codes. - Given an annual waiver cap per patient is configured, When an approval would exceed the cap, Then approval is blocked unless the approver has override permission; if overridden, an "Override Used" flag and reason are recorded. - Given excluded procedures are configured, Then requests tied to those procedure codes cannot be approved without override and the UI displays the policy reference. - Given any orchestration change occurs, Then it is applied within 5 seconds and reflected in the appointment timeline and messaging queue.
Respectful Patient Messaging and Copy Controls
- Given any waiver/exception message is sent, Then it uses an empathy-approved template, reading level ≤ 8th grade, avoids blame language, and includes a clear contact option. - Given a patient language preference is stored, Then all related messages are delivered in that language when supported; otherwise default to English with a link to translation assistance. - Given a request reaches Approved or Denied, Then no additional deposit requests or waiver prompts are sent for that appointment beyond a single final decision notice. - Given an approver edits the outbound message, Then the content passes profanity and PHI leakage checks prior to send or else presents corrective errors and blocks sending. - Given a message is sent, Then delivery status (queued, sent, failed) is tracked and failures are retried up to 3 times within 30 minutes before alerting staff.
Immutable Audit Trail and Data Governance
- Given any action on a request (create, view, assign, decide, notify, override), Then an immutable audit entry is appended capturing actor ID, role, timestamp (UTC), IP, action, previous/new state, reason code, and SHA-256 hash of attachments. - Given an audit entry is written, Then it cannot be edited or deleted by any role; attempted modifications are denied and logged as security events. - Given an attachment is uploaded, Then it is virus-scanned, encrypted at rest, linked by hash in the audit, and access to view/download is logged per user. - Given a compliance user requests an audit export for a date range, Then a CSV and JSON bundle with integrity checksum is generated within 15 minutes and made available via secure download. - Given HIPAA minimum necessary requirements, Then notifications, UI, and reports exclude unnecessary PHI by default and require explicit permission to include identifiers.
Reporting and Insights on Waivers and Impact
- Given reporting access, When a user applies filters (date range, location, provider, procedure code, payer type, decision outcome), Then results return within 10 seconds for datasets ≤ 100k rows. - Given a report is generated, Then it includes waiver volume, approval rate, average decision time vs SLA, deposit dollars waived, deposit dollars collected, and estimated chair-time saved. - Given correlation analysis is requested, Then the system displays no-show rates before vs after Smart Deposits adoption and segment-level correlation with waiver approvals. - Given export is requested, Then the report can be exported to CSV and scheduled for automated email delivery on a chosen cadence (daily/weekly/monthly). - Given privacy controls, Then PHI fields are excluded by default and only visible when the user's role has explicit permission; exports inherit the same restrictions.
Deposit Application, Refunds, and Reconciliation
"As a practice accountant, I want deposits to reconcile automatically with our PMS and processor so that our books stay accurate and refunds are handled correctly."
Description

Automated application of collected deposits to the patient ledger and specific appointment at check-in or treatment completion via PMS/EHR integration. Implements policy-driven handling for cancellations/reschedules (e.g., refundable before 48 hours, partial forfeiture, rollover to rescheduled date). Supports manual adjustments with role-based approvals, initiates refunds to original payment methods, and updates accounting entries. Maintains a reconciliation dashboard that matches internal transactions to processor settlements using webhooks and idempotent operations, with alerts for discrepancies. Exposes APIs/events for downstream billing and produces clear patient communications for applied or refunded deposits.

Acceptance Criteria
Auto-Apply Deposit at Check-In or Completion
Given a patient has a collected deposit linked to appointment A and the PMS/EHR emits a check-in or treatment-completed event for appointment A When the event is received Then the deposit is applied to appointment A’s ledger within 5 seconds And the PMS/EHR patient balance is updated via integration And the application amount does not exceed the appointment’s outstanding patient responsibility And any remainder remains as patient credit tagged to the patient account Given duplicate or replayed check-in/completion events for the same appointment and deposit When the system processes the event again Then the application is idempotent and no additional application occurs And an audit entry notes the duplicate was ignored Given the PMS/EHR is temporarily unavailable When the event occurs Then the deposit application is queued and retried with exponential backoff for up to 24 hours And the application time and retries are logged And staff are alerted after 3 failed attempts
Cancellation Policy Refund/Forfeiture Enforcement
Given a scheduled appointment with a deposit and a cancellation occurs outside the configured policy window When the cancellation is recorded Then 100% of the deposit is marked refundable per policy and a refund is initiated automatically unless staff opts to hold as credit per policy Given a cancellation occurs inside the configured policy window When the cancellation is recorded Then the system calculates the forfeiture and refundable portions per configured policy rules And applies the forfeited amount to the practice’s designated ledger item/GL code And marks the refundable portion for refund or credit per policy Given an appointment flagged with an insurance exception or compassionate waiver When a cancellation occurs Then the policy engine overrides forfeiture per the flag and processes a full or partial refund accordingly And all decisions are logged with policy rule IDs Given a cancellation is processed more than once for the same appointment When a subsequent cancellation event is received Then it is ignored idempotently with no duplicate forfeiture or refund
Reschedule with Deposit Rollover
Given a patient reschedules appointment A to appointment B within the policy’s rollover window When appointment B is created and linked Then the deposit from appointment A is automatically reassigned to appointment B within 5 seconds And appointment A shows a zero deposit balance with a rollover note And no refund is initiated Given a reschedule occurs outside the rollover window per policy When the reschedule is recorded Then the system follows forfeiture/refund rules instead of rollover Given multiple consecutive reschedules When deposit rollover is processed Then only one active appointment holds the deposit at any time, enforced idempotently
Manual Adjustment and Compassionate Waiver with Role-Based Approval
Given a staff user initiates a manual adjustment (apply, unapply, reallocate, waive forfeiture) exceeding the configured approval threshold When the adjustment is submitted Then the system requires approval from a user with an authorized role before changes take effect Given an approved adjustment When it is applied Then the patient ledger, PMS/EHR, and accounting entries reflect the change within 5 minutes And an immutable audit log captures user, timestamp, before/after values, reason code, and approval trail Given a user without required permissions attempts an adjustment When the adjustment is submitted Then the system blocks the action and displays an authorization error And no financial records are changed
Refund to Original Payment Method with Accounting Update
Given a deposit eligible for refund per policy When staff initiates or an auto-refund is triggered Then the refund is sent to the original payment method via the payment processor with a unique reference ID And the corresponding ledger and accounting entries are posted using mapped GL codes And a receipt is generated Given the original payment method cannot accept the refund When the processor returns a failure Then the refund status is set to Action Required And staff are alerted And no replacement payout is sent without explicit staff confirmation Given duplicate refund requests for the same deposit When processing occurs Then idempotency keys prevent multiple refunds and only one processor refund exists Given a partial refund When processed Then the remaining deposit balance remains available for application or future refund And totals reconcile to the original deposit
Reconciliation Dashboard and Settlement Matching with Alerts
Given settlement webhooks and daily reports from the payment processor When data is received Then 100% of settled transactions are matched to internal deposits within 24 hours or are listed as Unmatched with reasons Given an Unmatched or amount-mismatched transaction When detection occurs Then an alert is sent to the reconciliation inbox and Slack channel within 15 minutes And the dashboard shows suggested matches and remediation actions Given duplicate webhooks for the same transaction When processing occurs Then idempotency prevents duplicate settlement records Given staff mark a transaction as resolved When the resolution is saved Then the dashboard status updates And audit logs record the action And financial totals recalculate instantly
Billing Events and Patient Communications
Given a deposit is applied, refunded, forfeited, or rolled over When the state changes Then SmileCue emits a signed event (HMAC-SHA256) to registered webhooks with event_type, patient_id pseudonym, appointment_id, amount, currency, and idempotency_key And retries delivery for up to 24 hours with exponential backoff Given a patient-facing communication is triggered for an applied or refunded deposit When the event occurs Then the patient receives an email/SMS within 2 minutes containing practice name, appointment date/time, deposit amount applied/refunded, last4 of payment method, a secure receipt link, and support contact And no diagnosis or treatment details are included Given an undeliverable webhook or message When retries are exhausted Then the system records failure, surfaces it in Notifications, and alerts staff
Admin Policy Management & Performance Analytics
"As a practice manager, I want to configure policies and monitor outcomes so that we can optimize deposits for high confirmation rates and low patient friction."
Description

Centralized admin console to configure deposit policies, amounts (flat/percentage with caps), eligible appointment types, communication channels, cadences, templates, and quiet hours at practice and location levels. Provides role-based access, change history, and versioned policy rollouts with safe revert. Displays real-time analytics on request-to-pay conversion, time-to-payment, waiver rates, revenue secured, no-show impact, and staff workload. Supports cohort and provider-level segmentation, exports/BI connectors, threshold-based alerts, and A/B test reporting with recommendations to optimize deposit strategy for high confirmation and low patient friction.

Acceptance Criteria
Practice and Location-Level Deposit Policy Configuration
- Given a Practice Admin is on the Policy Console, when they create or edit a policy with Amount Type set to Flat or Percentage, then validation enforces Flat >= $0.00, Percentage between 1 and 100, and optional Min/Max caps for Percentage are respected at runtime. - Given appointment types, providers, and locations are selectable, when the admin saves a policy, then the system persists inclusions/exclusions and shows a coverage preview count based on the next 30 days of scheduled appointments. - Given conflicting rules exist (e.g., two policies target the same appointment type at the same location), when saving, then the system requires a priority order and blocks save until conflicts are resolved. - Given a policy is saved as Draft, when the admin publishes it, then the policy status changes to Active and is available to the Smart Deposits trigger service within 5 minutes.
Eligibility Rules: Insurance Exceptions and Compassionate Waivers
- Given insurance exception rules are enabled with a coverage threshold and payer list, when a patient’s verified insurance matches the rule, then no deposit request is sent and the encounter is logged with reason "Insurance Exception" and rule ID. - Given compassionate waiver rules are configured (auto conditions and manual override), when an auto condition matches, then the deposit is suppressed and an audit record captures patient ID, reason, policy version, timestamp, and actor=system. - Given a user with Waiver.Approve permission manually waives a deposit, when they submit a waiver, then they must enter a note of at least 10 characters, and the system records approver ID and links the waiver to the appointment. - Given eligibility rules change, when the new version is published, then only deposit requests generated after the effective timestamp apply the new rules; previously sent requests are not retroactively canceled.
Role-Based Access Controls and Audit Logging
- Given RBAC is configured, when a user without Policy.Admin tries to create, edit, publish, or revert a deposit policy, then access is denied with HTTP 403 and the UI shows an authorization error message. - Given a user with Policy.Read role, when viewing the console, then they can view policies and history but cannot modify, publish, or revert. - Given any policy change is made (create/update/publish/revert), then an immutable audit log entry is created with user ID, action, policy version, diff of changed fields, timestamp (UTC), and source IP address. - Given PHI is restricted, when exporting or viewing policy data in the admin console, then no patient-level PHI is displayed outside analytics aggregates.
Versioned Policy Rollouts with Safe Revert
- Given a policy version is scheduled with effective date/time and target locations/providers, when the schedule time is reached, then the version becomes Active only for the targets and the prior version moves to Superseded state. - Given issues are detected, when an admin clicks Revert on an Active policy, then the previous version is restored to Active within 2 minutes and the rollback is logged. - Given ongoing deposit requests exist, when a policy is rolled out or reverted, then requests generated before the change continue under their originating version and new requests use the current Active version. - Given a staged rollout is configured with a traffic split (e.g., 10%), when published, then traffic adheres to the configured split with ±2% tolerance.
Quiet Hours, Channels, Cadences, and Templates
- Given channel preferences (SMS, Email, Voice) and cadence steps are configured, when a policy is Active, then the system sends deposit requests according to the defined sequence and delays. - Given quiet hours are set per location timezone, when a scheduled send falls within quiet hours, then the send is deferred to the next allowed window and marked as "Deferred by Quiet Hours" in logs. - Given message templates use variables, when previewing, then the system renders a sample with placeholders resolved from test data and validates that required variables are present; publish is blocked if validation fails. - Given opt-out compliance is required, when a patient is opted out of a channel, then that channel is skipped and the next available channel in the cadence is used; if none, the attempt is aborted and logged.
Real-Time Analytics Dashboard
- Given the Analytics dashboard is opened, when data loads, then it displays at minimum: request-to-pay conversion rate, median and 95th percentile time-to-payment, waiver rate, revenue secured, estimated no-show reduction, and staff workload hours saved. - Given filters for date range, location, provider, appointment type, and policy version, when filters are applied, then all charts and KPIs update within 5 seconds for datasets up to 12 months. - Given data ingestion occurs continuously, when new deposit events are ingested, then dashboard metrics reflect them within 5 minutes. - Given any KPI is hovered or clicked, then a drill-through shows the underlying cohort definition and sample rows with masked identifiers according to role permissions.
Segmentation, Exports/BI Connectors, Alerts, and A/B Test Reporting
- Given cohort segmentation is configured (e.g., new vs returning, insurance type, appointment duration ≥ X minutes, high-risk flag), when applied, then the dashboard shows KPIs per cohort and allows provider-level breakdown. - Given an export is requested with current filters, when CSV export is generated, then it includes the selected KPIs and breakdowns, completes within 30 seconds for up to 50,000 rows, and is available via a time-limited secure download link. - Given a BI connector is enabled, when the external tool connects, then it can query the documented schema of policy, event, and aggregate tables with row-level security enforcing the user’s scope. - Given alert thresholds are defined (e.g., conversion < 70%, waiver > 15%), when a metric breaches a threshold for a sustained 30 minutes, then an alert is sent via the configured channel within 10 minutes including a link to the filtered dashboard view. - Given an A/B test is running on two policy variants with a defined primary metric and traffic split, when statistical significance at 95% confidence is reached or the test duration limit is met, then the report shows lift, p-value, winner/neutral, and provides a one-click option to promote the winner to Active for the targeted scope.

Hold & Release

Places risk-based soft holds on adjacent slots or backup patients and auto-releases them when confirmations reach a safe threshold. Syncs with the waitlist to pre-stage replacements without hard double-booking, giving the front desk a safety net that reduces scramble and preserves productivity.

Requirements

Risk-Based No-Show Scoring
"As an office manager, I want reliable no-show risk scores for upcoming appointments so that the system can decide when to place holds and I can protect chair time proactively."
Description

Compute a real-time no-show risk score per appointment using historical attendance patterns, latest SMS/email/voice responses, reminder cadence, appointment type/duration, provider, day/time, lead time, weather and traffic signals, and practice-specific heuristics. Expose a scoring service with confidence and reason codes so downstream logic can explain why holds were placed. Ensure data minimization and HIPAA-compliant processing, and cache scores with time-based invalidation to react to new confirmations or cancellations. Provide configuration for feature weights and thresholds per practice, provider, or appointment type.

Acceptance Criteria
Score API: Output Schema and Explainability
Given a valid appointment and practice-scoped auth When the client calls POST /v1/score Then the response status is 200 and includes appointment_id, score (0.00–1.00), confidence (0.00–1.00), reason_codes [{code,label,contribution}], generated_at (ISO-8601 UTC), ttl_seconds, cache_hit (boolean) Given identical immutable inputs within the cache TTL When the same scoring request is repeated Then the returned score and confidence are identical and cache_hit is true Given optional input signals are missing When a score is computed Then reason_codes includes an entry indicating each missing signal and a score is still returned Given feature contribution ranking When reason_codes are returned Then they are sorted by absolute contribution descending, limited to top 5, and contributions reconcile to the model delta within ±0.05 Given downstream Hold & Release explanation needs When reason_codes are returned Then each label is plain-language (≤60 chars) and present for ≥99% of scores
Per-Entity Configurable Weights and Thresholds
Given practice default configuration exists When provider- or appointment-type overrides are defined Then precedence is provider > appointment_type > practice and is applied at score time Given configuration submission When invalid values are provided Then the API rejects with 400 and messages; allowed ranges: weights ∈ [-5.0,5.0], thresholds ∈ [0.00,1.00] Given a configuration change is saved When activated Then new scoring requests reflect it within 60 seconds and an audit log records actor, timestamp, and diff Given a new practice without custom config When scoring is requested Then safe defaults apply (e.g., high=0.70, medium=0.45) and are echoed in response metadata Given a practice admin requests config When GET /v1/config is called Then the effective config after precedence resolution is returned with 200
Real-Time Cache and Invalidation
Given a cache TTL configured between 5 and 60 minutes (default 15) When a score is computed Then it is cached for ttl_seconds and ttl_seconds is included in the response Given an appointment receives confirmation, reschedule, or cancellation When the event is processed Then any cached score for that appointment is invalidated within 10 seconds and recomputed on next request Given concurrent requests for the same uncached appointment When scoring is triggered Then only one computation executes and others coalesce to the same result within 300 ms of the leader response Given the cache layer is unavailable When scoring is requested Then a fresh score is computed, served successfully, and a single warning per minute is logged
HIPAA Compliance and Data Minimization
Given PHI/PII inputs When scoring executes Then only minimum necessary fields are accessed (IDs, timestamps, aggregates, coded attributes, weather/traffic indices); free-text notes are never read or stored Given request/response logging When API calls occur Then no names, phone numbers, emails, or free-text are logged; IDs are hashed/tokenized; TLS 1.2+ in transit and AES-256 at rest are enforced Given role-based access control When a non-privileged token calls the scoring API Then access is denied with 403 and the attempt is recorded in an immutable audit log (subject, action, resource, timestamp, outcome) Given data retention policies When derived features are stored Then retention does not exceed 30 days and automated purges are auditable
Service Reliability and Performance
Given typical load of 100 RPS with p95 payload When scoring requests are executed over a 1-hour window Then p95 latency ≤ 300 ms, p99 latency ≤ 500 ms, and 5xx error rate ≤ 0.1% Given burst load of 500 RPS sustained for 5 minutes When scoring requests are executed Then p95 latency ≤ 450 ms and 5xx error rate ≤ 0.1% Given upstream weather/traffic timeouts When requests are executed Then provider timeouts are ≤ 200 ms, total p95 latency impact ≤ +100 ms, and fallbacks are used Given transient failures When they occur Then 503 responses include Retry-After, bodies contain no PHI, and requests are idempotent for safe retries
Model Quality and Calibration
Given ≥1,000 appointments with outcomes per practice or ≥5,000 cross-practice over the last 90 days When backtesting is performed Then ROC AUC ≥ 0.75 and Brier score ≤ 0.20 Given monthly calibration evaluation per practice When assessed Then calibration slope ∈ [0.8,1.2] and expected calibration error (ECE) ≤ 0.05 Given high-risk operational threshold When score ≥ high_threshold on holdout data Then recall@top-30% flagged ≥ 0.60 for actual no-shows Given performance degradation >10% in AUC or calibration metrics When detected Then an alert fires and the system rolls back to the last known-good model/config within 1 hour
External Signals Integration and Graceful Degradation
Given weather and traffic providers are healthy When scoring runs Then signals are refreshed ≥ every 60 minutes per practice location and not older than 90 minutes at use Given provider outages or timeouts > 200 ms When scoring runs Then scoring completes without those signals, reason_codes include signal_missing:weather or signal_missing:traffic, and confidence is decreased accordingly Given timezone and DST differences When external signals are aligned Then the practice location timezone is used to map scheduled_datetime to signals correctly Given malformed or extreme external values When ingested Then values are clipped to predefined ranges and validation errors are logged without blocking scoring
Soft Hold Allocation Engine
"As a scheduler, I want the system to place temporary holds near risky appointments so that I have a safety net without disrupting the official schedule."
Description

Place non-invasive, risk-based soft holds on adjacent time slots or pre-select backup patients without creating hard double-bookings in the PMS. Enforce configurable policies: maximum concurrent holds per provider/day, adjacency windows, buffer minutes, hold expiration, and provider/resource constraints (room/equipment). Provide visual indicators in the SmileCue scheduler and PMS annotations, ensure idempotent hold placement, and handle conflicts from external edits. Holds remain invisible to patients and do not trigger automated patient messaging until converted.

Acceptance Criteria
Adjacent Slot Soft Hold Placement and Resource Compliance
Given an appointment A for provider P at time T with configured adjacencyWindowMinutes and bufferMinutes When the risk model authorizes soft holds for A Then holds are placed only on slots within T ± adjacencyWindowMinutes and do not overlap bufferMinutes before/after A And provider, room, and equipment constraints are validated before placing each hold; holds are placed only when all constraints pass And no hard double-booking is created in the PMS; only a non-appointment annotation is written And each hold is tagged with provider, room, equipment, risk score, and expiration timestamp
Max Concurrent Holds per Provider/Day
Given maxConcurrentHoldsPerProviderPerDay = N for provider P on date D When the engine attempts to place the (N+1)th soft hold for P on D Then the request is rejected; no additional hold is created And a denial reason MAX_CONCURRENT_LIMIT is recorded and observable via API/logs And when a hold for P on D is released or expired, the count decrements, allowing new holds up to N
Waitlist Backup Patient Pre-Selection (No Double-Booking)
Given a waitlist with eligible backup patients matching provider P, room/equipment, and time window W When the engine pre-selects a backup patient B for a soft hold Then B is marked as pre-staged without creating an appointment in the PMS And no automated patient messaging is triggered for B until conversion And on release or conflict, B’s pre-staged status is cleared and the candidate is returned to the waitlist
Idempotent Hold Placement and Retry Safety
Given an idempotency key composed of {providerId, slotId, candidateId (optional), sourceRef} When the same hold placement request is submitted multiple times within the idempotency window Then exactly one soft hold exists; subsequent calls return the original hold representation And if a previous attempt partially wrote annotations, the state is reconciled to a single hold without duplicates And the audit trail shows a single logical operation associated with the idempotency key
Hold Expiration and Auto-Release
Given holdExpirationMinutes = X and an active soft hold H When H reaches X minutes without conversion and policies permit release Then H is auto-released and the slot becomes available for booking And the PMS annotation is removed or updated to reflect release And provider/day hold counts are updated accordingly
External Edit Conflict Handling and Reconciliation
Given a soft hold H on slot S and an external PMS edit books or modifies S When the sync layer detects the conflict Then H is released or reallocated per policy without creating double-bookings And the SmileCue scheduler displays a conflict/resolution indicator for the affected slot And no automated patient messaging is triggered by this event
UI Indicators and PMS Annotation (No Patient Visibility/Messaging)
Given a soft hold is created for slot S When viewed in the SmileCue scheduler Then S displays a Soft Hold badge with provider/resource tags and expiration time And in the PMS, only a non-appointment annotation/note is present; appointment counts remain unchanged And holds are invisible to patients and do not trigger automated patient messaging until converted
Auto-Release Thresholds & Scheduler
"As a front desk lead, I want holds to auto-release once my day is secure so that we avoid unnecessary blocking and maximize productivity."
Description

Automatically release soft holds when confirmation rates exceed configurable safety thresholds per provider, day part, or block, or when a specific appointment confirms. Support time-based gates (e.g., T-72/T-48/T-24 hours), release prioritization (oldest-first or lowest-risk-first), and hysteresis/debounce to prevent rapid hold churn. Generate staff notifications on release events and update all calendars in near real time. Provide simulation mode to preview releases based on current confirmations.

Acceptance Criteria
Auto-Release by Provider/Day Part/Block Threshold
Given safety thresholds are configured per provider, day part, and block And soft holds exist for Dr. Lee in the AM day part within block "Hygiene A" And the current confirmation rate for Dr. Lee's AM block is 79% When confirmations increase and the rate reaches or exceeds the configured threshold of 80% for that scope Then the system releases all eligible soft holds in that scope within 30 seconds And no holds outside the matching provider/day part/block are released And an audit event is recorded with scope, threshold value, rate at trigger, release count, and timestamp
Time-Gated Release Windows (T-72/T-48/T-24)
Given time-gated releases are enabled with gates at T-72h, T-48h, and T-24h before appointment start And an appointment with soft holds is currently at T-65h with a confirmation rate above threshold When the gate condition is not met (not at a configured gate) Then no release occurs When the clock reaches T-48h and the confirmation rate for the scope is at or above its threshold Then eligible soft holds for that appointment’s scope are released within 30 seconds And if the rate is below threshold at a gate, no release occurs at that gate
Appointment Confirmation Triggered Release
Given Appointment A has one or more soft holds on adjacent/backup slots tied to it And the release rule "on appointment confirmation" is enabled for Appointment A’s scope When Appointment A is marked Confirmed via any channel (SMS, email, voice IVR, or manual) Then all holds explicitly linked to Appointment A are released within 30 seconds And holds not linked to Appointment A are not released And a release notification is queued to staff with Appointment A’s details
Release Prioritization Strategies (Oldest-First, Lowest-Risk-First)
Given there are multiple eligible holds in the same scope And release strategy is set to "oldest-first" When a release action is executed Then holds are released in ascending order of holdCreatedAt until all eligible holds are released Given there are multiple eligible holds in the same scope And release strategy is set to "lowest-risk-first" with a numeric riskScore where lower = lower risk When a release action is executed Then holds are released in ascending order of riskScore And ties on riskScore are broken by ascending holdCreatedAt
Hysteresis and Debounce to Prevent Hold Churn
Given releaseThreshold is 80% and rearmThreshold is 75% for the scope And stabilityWindow is 2 minutes and debounceInterval is 5 minutes When the confirmation rate crosses up to 80% and remains >= 80% for the full stabilityWindow Then a single release is executed and no additional releases for that scope are executed during the debounceInterval When the confirmation rate fluctuates between 78% and 82% during the debounceInterval Then no further release actions are triggered When the debounceInterval has elapsed and the rate is again >= 80% for the full stabilityWindow Then another release may be executed
Release Event Notifications and Calendar Sync
Given staff notification channels are configured (in-app and email/SMS) and calendar integrations are connected When a release event occurs Then an in-app notification is delivered to front desk and assigned provider within 30 seconds containing provider, appointment, gate (if any), strategy, and count of holds released And an email/SMS is sent according to user preferences within 2 minutes And all connected calendars (SmileCue scheduler and external integrations) reflect the released holds within 30 seconds And any notification or sync failures are logged with retry attempted up to 3 times
Simulation Mode Release Preview
Given simulation mode is enabled for the Auto-Release Thresholds & Scheduler And current confirmation rates and configurations are loaded When a user runs a simulation for a selected provider/day part/block and optional time gate Then the system produces a preview listing which holds would be released, the trigger reason (threshold, gate, appointment confirmation), and the prioritization order And the simulation does not modify any live holds, calendars, or send notifications And the preview can be exported and is timestamped and reproducible using the same inputs
Waitlist Sync & Candidate Pre-Staging
"As a hygienist, I want ideal backup patients pre-staged from the waitlist without messaging them prematurely so that I can fill fallouts quickly when a slot opens."
Description

Continuously rank and pre-stage waitlist candidates that best match each potential hold based on appointment type, provider, insurance, travel time, availability windows, readiness flags, and patient preferences. Do not contact candidates until a hold converts to an open slot or staff explicitly triggers outreach. Support multi-tier candidate queues, expiration windows, and exclusion rules. Respect consent and communication channel preferences; log all selection decisions with rationale for traceability.

Acceptance Criteria
Continuous Ranking and Pre-Staging of Waitlist Candidates
Given a hold is created or updated with appointment type, provider, location, date/time, and duration And the waitlist contains candidates with provider preferences, insurance plan, address, availability windows, readiness flags, and patient preferences When the ranking job runs on hold creation, hold change, or waitlist change Then the system computes a match score per candidate using appointment type fit, provider fit, insurance compatibility, travel time to the practice location, availability window overlap, readiness flags, and stated preferences And returns the top K candidates (default K=5; configurable) as the pre-staged list for that hold And the pre-staged list is created or refreshed within 10 seconds of the triggering event And each pre-staged entry includes rank, score, tier, and a brief reason summary
No Outreach Until Slot Opens or Staff Triggers
Given a pre-staged list exists for a held slot When the slot remains on hold and no staff outreach is triggered Then no SMS, email, or voice messages are sent to pre-staged candidates And no contact attempts are written to communication logs When the hold converts to an open slot OR authorized staff explicitly triggers outreach for the hold Then the system initiates outreach only to the current top-of-queue candidate(s) per configuration And all outreach actions are timestamped and attributable to the system or the specific staff member And if outreach is canceled before send, no contact log is created
Multi-Tier Candidate Queues with Expiration and Escalation
Given tiers are configured as T1 (ready now), T2 (flexible), T3 (low likelihood) with expiration windows T1=15 minutes and T2=30 minutes And a pre-staged list exists for a hold When outreach to the top T1 candidate does not result in confirmation within 15 minutes Then the system advances to the next candidate in T1 or proceeds to T2 if T1 is exhausted And candidates that expire or decline are marked with that outcome and are not re-contacted unless reset rules explicitly allow And when the slot is filled, all pending timers are canceled and the queue is closed for that hold And when the hold’s time or provider changes, tiers and expirations are recalculated and the queue is rebuilt within 10 seconds
Exclusion Rules Enforcement
Given exclusion rules are configured (e.g., do-not-contact flag, overlapping appointment > 0 minutes, provider not accepted, out-of-network insurance, travel time exceeds patient max, readiness=false, no availability overlap) And a hold is created or updated When candidates are evaluated Then any candidate meeting any exclusion rule is not added to the pre-staged list And the specific exclusion reason code(s) are recorded for that candidate for that hold And if an exclusion condition is later cleared, the candidate becomes eligible on the next re-rank within 10 seconds
Consent and Communication Channel Compliance
Given each candidate has recorded consents and channel preferences (e.g., SMS allowed, email denied, voice allowed; PHI consent flags) When outreach is triggered due to an open slot or explicit staff action Then only channels permitted by the current consents and preferences are used And if no channels are permitted, the candidate is marked contact-blocked and the next candidate is attempted And message templates automatically use HIPAA-safe content when PHI consent is absent And the audit log records channels considered, selected, and rejected with reasons
Decision Logging and Traceability
Given a pre-staging or re-ranking process runs When candidates are scored and queued (or excluded) Then an immutable audit record is written per candidate-hold decision including: hold ID, candidate ID, timestamp, rank, score, tier, matched criteria, unmet criteria, exclusion reasons (if any), data sources/versions, configuration version, and actor (system/user) And audit records are retrievable by hold ID within 2 seconds for the most recent 1,000 events And all access to logs is access-controlled and PHI is encrypted at rest and in transit
Deterministic Tie-Breaking and Fairness Rotation
Given two or more candidates have identical match scores for a hold When the queue is built Then a deterministic tie-breaker is applied in this order: highest readiness flag > earliest availability window start > least recently contacted by the practice for any hold > earliest waitlist join time > ascending candidate ID And a fairness rotation ensures a candidate contacted but not confirmed in the last 24 hours is de-prioritized behind equally scored candidates who were not recently contacted And applied tie-breaker values are included in the audit record for each tied candidate
PMS/EHR Non-Invasive Calendar Integration
"As an IT admin, I want holds reflected in our schedule without creating duplicate appointments so that our PMS remains authoritative."
Description

Integrate with supported dental PMS/EHR systems to represent holds as metadata, annotations, or custom blocks rather than booked appointments, preserving the official schedule as the source of truth. Implement adapter layers for major vendors (e.g., Dentrix, Open Dental, Eaglesoft) with read/write capabilities, conflict detection, retries, and eventual consistency. Handle reschedules, cancellations, and external edits gracefully; fail-safe to remove or pause holds on adapter errors and surface alerts to staff.

Acceptance Criteria
Non-appointment holds representation in PMS calendars
- Given a soft hold is created in SmileCue for provider P at time T in location L, When the adapter writes to the PMS, Then the PMS contains a single non-appointment artifact (annotation/flag/custom block) named "SmileCue Hold" for P at T in L and no appointment record is created. - Given a scheduler uses the PMS UI, When booking an appointment on a slot that has a SmileCue hold artifact, Then booking proceeds without override prompts caused by the artifact and without changing the provider’s availability rules. - Given the hold is released in SmileCue, When the adapter updates the PMS, Then the hold artifact is removed within 15 seconds and no residual annotations/notes remain for that slot. - Given the hold artifact text, Then it contains at most "SmileCue Hold" and a correlation ID; it contains no patient name, phone, DOB, treatment codes, or other PHI. - Given PMS appointment listings and reports, When only holds are added/removed, Then no new appointment objects appear and production/utilization metrics remain unchanged from baseline.
Multi-vendor adapter read/write, idempotency, and conflict detection
- Given supported vendors (Dentrix, Open Dental, Eaglesoft), When creating, updating, and deleting hold artifacts via their adapters, Then the PMS state matches the SmileCue state within 30 seconds for each operation. - Given the same hold create request is retried with the same correlation ID up to 3 times, When the PMS processes these requests, Then exactly one hold artifact exists in the PMS for that slot (idempotent write). - Given a real appointment exists at provider P, time T, location L in the PMS, When a hold create is attempted for that slot, Then the adapter returns a conflict status, no artifact is written, and SmileCue marks the hold request as "conflict" within 5 seconds. - Given periodic read synchronization, When a hold artifact is manually removed in the PMS by staff, Then SmileCue detects the removal within 60 seconds and updates the internal hold status to "externally removed".
Eventual consistency and retry policy under transient PMS API failures
- Given PMS APIs return retriable errors (HTTP 429, 5xx, or timeouts), When the adapter attempts a write, Then it retries with exponential backoff (1s, 2s, 4s, 8s, 16s with jitter) up to 5 attempts before marking the operation as deferred. - Given successful write operations, Then 99% are visible in the PMS within 30 seconds; and 99% of read-after-write syncs converge within 60 seconds. - Given 10 consecutive failures to the same vendor endpoint, When additional requests arrive, Then a circuit breaker opens for 2 minutes and incoming operations are queued without being sent to the PMS. - Given the vendor endpoint becomes healthy, When the circuit closes, Then queued operations are flushed in FIFO order, preserving idempotency, and backlogs of ≤1000 operations clear within 5 minutes. - Given each operation, Then retries, failures, circuit open/close events, and correlation IDs are logged with timestamps for auditability.
External edits: reschedules, cancellations, and hold auto-release
- Given external appointment changes occur in the PMS, When webhooks are available, Then the adapter processes webhook events; otherwise it polls at 30-second intervals to detect creates, updates, and cancels. - Given a held slot in the PMS, When an appointment is rescheduled into that slot externally, Then the hold artifact is removed within 10 seconds and SmileCue marks the slot as booked. - Given an appointment is cancelled externally, When SmileCue syncs, Then SmileCue updates the slot as free and may place or adjust holds per policy using only non-appointment artifacts; no appointment objects are written by SmileCue. - Given a staff member manually edits the hold annotation text in the PMS, When SmileCue syncs, Then SmileCue restores the canonical artifact format without converting it into an appointment and logs the external edit. - Given any external change is detected, Then an audit entry is recorded in SmileCue with old value, new value, source=PMS, timestamp, and actor if available.
Fail-safe behavior and staff alerts on adapter errors
- Given a hold write/update/delete remains unresolved due to adapter errors for more than 2 minutes or a circuit breaker is open, When this threshold is met, Then SmileCue activates fail-safe for the impacted provider/location. - Given fail-safe is active, Then all existing hold artifacts for the impacted provider/location are removed from the PMS within 60 seconds and new hold placements are paused. - Given fail-safe activation, Then a high-severity alert is shown in SmileCue within 10 seconds including vendor name, scope (provider/location), error summary, and recommended action; an audit entry is created. - Given the adapter health is restored, When a user with Scheduler or Admin role acknowledges the alert, Then new hold placements resume; otherwise they remain paused. - Given the scheduling board, Then the impacted provider/location displays a "Hold Paused" status badge until acknowledgment.
No hard double-booking and waitlist pre-staging integrity in PMS
- Given SmileCue places holds, Then it never creates PMS appointment objects for holds; only non-blocking artifacts are used so the PMS schedule remains the source of truth. - Given a real appointment is booked in the PMS over a held slot, When SmileCue syncs, Then the hold artifact is removed within 10 seconds and any linked waitlist candidate is detached without altering PMS appointments. - Given two concurrent hold create requests target the same provider/time/location, When processed, Then at most one artifact exists in the PMS and all others are marked as conflict in SmileCue within 5 seconds. - Given PMS waitlist features exist, Then SmileCue does not modify PMS waitlist objects; waitlist pre-staging is maintained only within SmileCue and reflected in PMS solely via non-appointment artifacts. - Given baseline booked hours for provider P on date D, When N holds are created and later removed without any real appointments booked, Then the PMS booked-hours metric remains equal to baseline (tolerance 0).
Staff Controls, Overrides, and Guardrails
"As a practice owner, I want fine-grained control over hold behavior and overrides so that the system aligns with my risk tolerance and operational policies."
Description

Provide role-based UI to view active holds, adjust policies, override placement/release decisions, and perform bulk actions (e.g., weather disruption, provider illness). Require reason codes for overrides, display projected impact on utilization and revenue, and prevent unsafe actions via guardrails (max holds, minimum buffers). Include audit-friendly summaries and quick actions within the daily schedule view for rapid triage.

Acceptance Criteria
Role-Based Visibility and Permissions for Active Holds
Given a signed-in user with a defined role and provider/location assignments When the user opens the Hold & Release panel Then only holds for the user’s permitted providers/locations are listed And actions not permitted by the role are hidden or disabled And any attempt to invoke a disallowed action via API returns 403 and is logged with user ID, role, endpoint, and timestamp And the UI displays total active holds count and supports filter by provider, location, and hold status
Override with Reason Code and Impact Projection
Given a permitted user initiates an override of a hold placement or release When the user selects Override Then the system requires a reason code from an admin-managed list or “Other” with free text (minimum 10 characters) And the system displays projected utilization change (%) and revenue change ($) for the affected provider/day prior to confirmation And the user must confirm via a 2-step confirmation dialog to proceed And upon success, the audit log records actor, timestamp, target slot(s), prior state, new state, reason code, free text, and the displayed projections And if the reason code is not provided or projections cannot be computed, the override is blocked with a descriptive error
Policy Adjustment with Versioning and Safe Validation
Given a user with Admin permissions opens Hold Policy Settings When the user edits Max Holds per Provider per Hour or Minimum Buffer Minutes Then inline validation prevents values outside platform guardrail limits and shows specific error messages And Save remains disabled until all validation passes And before saving, the system displays a 7-day projected impact summary (utilization % and revenue $) for selected providers/locations And upon Save, a new policy version is created with version ID, editor, timestamp, and change diff And the change is applied atomically and recorded in the audit log And API attempts to set invalid values return 400 with machine-readable error codes
Bulk Action for Weather or Provider Disruption
Given a permitted user selects Bulk Actions When the user chooses a disruption template (e.g., Weather, Provider Illness), a date range, providers/locations, and an action (place holds, release holds) Then the UI shows a preview with affected slots count and projected utilization/revenue impact prior to execution And a reason code is required (template default may pre-populate) before Run is enabled And execution completes within 60 seconds for up to 500 affected appointments with a progress indicator And an Undo option is available for 15 minutes to restore pre-change state And an audit summary record is created with counts by action type, success/failures, and correlation ID And partial failures are retried up to 3 times and surfaced with actionable error messages
Guardrails Prevent Unsafe Scheduling
Given a user attempts any action that would exceed Max Holds per provider per hour or violate Minimum Buffer Minutes When the action is submitted via UI or API Then the system blocks the action and displays a specific error referencing the violated limit and current usage And no partial changes are persisted (atomic rejection) And the API returns a structured error (409 with error_code and limit values) And concurrent actions are serialized to ensure limits are not exceeded under race conditions And policy values cannot be set below platform minimums or above platform maximums
Quick Actions in Daily Schedule View
Given the daily schedule view is open When a slot with a hold is selected Then inline quick actions (Release Hold, Override, Convert to Waitlist Candidate) are visible if permitted by role And any action completes in <= 2 clicks and returns a success/failure toast with correlation ID And p95 action round-trip time is <= 2 seconds under normal load And override and convert actions require a reason code and respect guardrails And Convert to Waitlist Candidate pre-stages a backup without creating hard double-bookings (no overlapping confirmed appointments) And all quick actions are keyboard accessible and have ARIA labels
Audit-Friendly Summaries and Export
Given an auditor or Admin opens the Hold & Release Audit view When a date range, provider/location, and action types are selected Then the system displays a summary with counts of holds placed/released, overrides by reason code, bulk actions, and impacted slots And the user can drill down to itemized entries showing actor, timestamp, action, pre/post state, reason code, and correlation ID And exports are available as CSV and PDF and exclude PHI beyond minimally necessary metadata (no phone numbers, message bodies) And generated reports include report parameters, generation timestamp, and checksum/hash And access to audit exports is restricted to authorized roles; unauthorized requests return 403 and are logged
Compliance, Auditing, and Performance Reporting
"As a compliance officer, I want complete, traceable records and performance metrics so that we can demonstrate due diligence and quantify ROI."
Description

Ensure HIPAA-compliant handling of PHI across scoring, hold placement, and waitlist matching. Maintain immutable audit logs for holds created/updated/released, inputs to risk decisions, staff overrides, and outbound communications. Provide dashboards and exports for confirmation rate trends, no-show reduction, hold utilization, average fill time, and revenue protection estimates. Meet performance SLAs: scoring and hold decisions under 300 ms p95, calendar sync under 5 seconds p95, and zero data loss on network retries.

Acceptance Criteria
HIPAA-Compliant PHI Handling Across Scoring, Holds, and Waitlist
- Given PHI is processed for risk scoring, hold placement, and waitlist matching, When data is stored or transmitted, Then PHI is encrypted at rest (AES-256/KMS) and in transit (TLS 1.2+) and verified by automated compliance tests. - Given user roles (Dentist, Hygienist, Office Manager, Admin, Support), When accessing PHI screens or APIs, Then only authorized roles obtain access and unauthorized attempts return 403 and are captured in access logs. - Given application logging and metrics pipelines, When PHI values are emitted, Then logs/metrics contain only masked or tokenized values and static/dynamic scans find 0 instances of unmasked PHI. - Given analytics/reporting jobs, When computing aggregates, Then only de-identified data is used and row-level exports exclude PHI unless the requester has explicit Export PHI permission. - Given retention policies, When PHI exceeds its retention window, Then PHI is purged/archived per policy while associated audit records remain accessible.
Immutable Audit Log for Holds, Risk Inputs, Overrides, and Communications
- Given any hold is created/updated/released, outbound communication sent, staff override performed, or risk decision computed, When the event completes, Then an append-only audit record is written with: event_type, UTC timestamp, actor_id (or system), practice_id, appointment_id, patient_guid (pseudonymized), prior_state, new_state, reason_code (if any), correlation_id, model_version (if scoring), and payload_hash. - Given the audit store, When attempting to modify or delete a record via API/DB, Then the operation is rejected and tamper-evident hash-chain verification succeeds for 100% of records. - Given auditors query the log, When filtering by date range, event_type, practice_id, appointment_id, or actor_id, Then results return within 5 seconds at p95 and CSV export yields identical record counts to the on-screen results. - Given compliance retention requirements, When configured, Then audit records are retained for at least 6 years (configurable) and are discoverable during that period.
Staff Override Capture and Authorization
- Given a staff member attempts to override a hold or risk decision, When they lack the Override permission, Then the action is blocked with HTTP 403 and an audit event with reason "unauthorized_attempt" is created. - Given a staff member with Override permission performs an override, When they submit the change, Then they must select a reason_code from a controlled list (required) and may add a note (optional), and the system records user_id, timestamp, previous_value, new_value, reason_code, and note_id to the immutable audit log. - Given an override is applied, When reporting refreshes, Then the override is reflected in hold utilization metrics within 15 minutes and is filterable by reason_code.
Risk Decision Traceability and Reproducibility
- Given an appointment ID, When an admin requests the risk decision record, Then the system returns score, threshold, model_version, evaluation timestamp, and a feature vector manifest (feature names with normalized values pseudonymized where PHI) linked via correlation_id to the audit log. - Given the stored inputs and model artifact for model_version, When the decision is recomputed, Then the resulting score matches the original within ±0.001 for ≥99% of cases, with any mismatches flagged and logged. - Given data retention policies, When decisions exceed PHI retention windows, Then PHI-derived feature values are absent while non-PHI metadata (score, model_version, timestamps) remains for traceability.
SLA: Scoring and Hold Decision Latency p95 ≤ 300 ms
- Given production traffic, When measuring end-to-end latency from event ingestion to decision persistence, Then p95 ≤ 300 ms and p99 ≤ 600 ms over rolling 15-minute windows, visible on an APM dashboard. - Given an SLO breach condition, When p95 exceeds 300 ms for 5 consecutive minutes, Then an alert is sent to on-call and the incident is annotated with the affected services and error budget impact. - Given backpressure or retry conditions, When queues are non-empty, Then decision latency p95 still meets ≤ 300 ms by auto-scaling or graceful degradation, and no decisions are dropped.
SLA: Calendar Sync p95 ≤ 5 s with Zero Data Loss on Retries
- Given an upstream calendar change (create/update/cancel), When the event is emitted, Then SmileCue reflects the change and updates holds within 5 seconds at p95 and 10 seconds at p99 measured over rolling 15-minute windows. - Given transient network failures between SmileCue and the calendar/EHR, When retries are triggered, Then no events are dropped: end-of-day reconciliation against the source shows 0 missing or out-of-order changes, and idempotent processing prevents duplicates. - Given dead-lettered events after max retries, When the upstream recovers, Then dead-lettered events are automatically reprocessed and reconciliation reaches 100% parity within 15 minutes, with alerts cleared automatically.
KPI Dashboards and Exports: Confirmation, No-Show Reduction, Hold Utilization, Fill Time, Revenue Protection
- Given a practice uses Hold & Release, When viewing dashboards, Then KPIs are available with daily and weekly granularity and filters by date range, location, provider, and channel: confirmation rate trend, estimated no-show reduction, hold utilization rate, average fill time, and revenue protection estimate. - Given KPI definitions, When validating against audit logs, Then metric values match recomputed ground truth within ±0.5% and totals within ±0.25%. - Given an authorized user requests an export, When generating CSV for any KPI up to a 12-month range, Then the file downloads within 15 seconds, includes column headers and a data dictionary snippet, uses the practice time zone, and contains no PHI unless "Include PHI" is explicitly selected and permissioned. - Given data freshness requirements, When loading the dashboard, Then the last-refresh timestamp is visible and underlying data is ≤ 15 minutes stale at p95.

Household Graph

Automatically discovers and maintains family relationships from your PMS and imports (shared address/guardian, insurance, last name, custom flags) with manual overrides. Creates a clean, bundle-ready household record so staff can message one thread, see everyone’s upcoming appointments at a glance, and avoid duplicate outreach. Faster setup, fewer errors, and effortless family coordination from day one.

Requirements

PMS Household Data Ingestion & Mapping
"As an office manager, I want SmileCue to automatically import and map household-relevant data from our PMS so that setup is fast and accurate without manual data entry."
Description

Implement secure connectors to import patient and household-relevant attributes from practice management systems, including shared addresses, guardianship relationships, insurance subscriber/policy links, last names, and custom flags. Normalize sources into a unified schema with deterministic field mapping, data validation, and idempotent upserts. Support initial bulk import and incremental updates with retry, backoff, and reconciliation reports. Provide an admin mapping screen for field configuration and transformation rules. Enforce HIPAA compliance with encryption in transit/at rest and least-privilege access. Output a clean, deduplicated household seed suitable for downstream relationship inference.

Acceptance Criteria
Initial Bulk Import Produces Unified, Deduplicated Household Seeds
Given a PMS bulk export containing patients and related attributes, When an initial import is executed, Then 100% of well-formed records are ingested and validated against the unified schema, and malformed records are rejected with structured error details. Given duplicate patient entries across files or sources share the same PMS external ID, When imported, Then a single unified patient record is created with a stable unified_patient_id and no duplicates. Given multiple patients share the same normalized address and explicit household indicators, When imported, Then they are assigned the same seed household_id and no more than one seed household is created per address+practice. Given normalization rules, When addresses and names are mapped, Then addresses are standardized to USPS format and last names are case-normalized and trimmed according to the active mapping configuration. Given the same bulk file is re-run, When the import is executed again, Then the outcome is idempotent: record counts and hashes match the previous run, with zero new duplicates and only timestamps updated where allowed.
Incremental Updates with Idempotent Upserts and Backoff
Given a patient record is updated in the PMS, When an incremental sync runs, Then only changed fields are upserted in the unified record, unchanged fields remain intact, and updated_at reflects the PMS change time. Given the same PMS change event is delivered multiple times, When processed, Then the upsert is idempotent and results in no additional writes beyond the first. Given transient connector errors (e.g., HTTP 5xx or timeouts), When fetching updates, Then the system retries with exponential backoff and jitter up to 5 attempts and moves failed batches to a dead-letter queue with alerting. Given high-watermark tracking, When consecutive incremental runs occur, Then no eligible changes are missed or processed twice, as verified by reconciliation counts and change-token continuity. Given an update is processed, When measured under nominal load, Then end-to-end latency from PMS change to unified store commit is less than 5 minutes at P95.
Guardianship and Household Relationship Mapping Accuracy
Given PMS guardianship/guarantor fields, When mapping executes, Then guardian_of/dependent_of edges are created with correct directionality and cardinality according to schema constraints. Given unknown or unmapped guardianship codes, When encountered, Then records are excluded from relationship creation with a validation error and listed in the reconciliation report with counts by code. Given circular or conflicting guardianship input, When validation runs, Then the import fails the offending relationships with errors and prevents cycles in the relationship graph. Given admin-configured code-to-relationship mappings, When applied, Then resultant relationships reflect the configured mapping and are versioned with the mapping configuration identifier used.
Insurance Subscriber and Policy Linkage Integrity
Given PMS insurance data for subscriber and dependents, When mapping executes, Then each dependent links to a subscriber via subscriber_external_id and policy_number, and the link is present in the unified schema. Given missing or invalid policy numbers, When encountered, Then the dependent is ingested but the insurance link is omitted with a validation warning recorded in reconciliation. Given multiple active policies, When mapping executes, Then the primary policy is selected per configured priority rules and secondary policies are recorded accordingly. Given duplicate subscriber records across sources, When imported, Then they consolidate to one unified subscriber entity based on the configured composite external key and do not create duplicate links.
Admin Mapping Screen: Field Configuration, Transformations, and Preview
Given an authorized admin, When viewing the mapping screen, Then they can create, edit, and version field mappings and transformation rules with role-based access control enforced. Given a proposed mapping, When running a sample payload through preview, Then the UI displays the transformed unified record diffs without persisting changes. Given a mapping version is activated, When the next import runs, Then the active version is used and recorded in run metadata for traceability. Given a bad mapping is deployed, When a rollback is triggered, Then the previous working version is restored and subsequent runs use it without data loss. Given PII in sample payloads, When displayed in the UI or logs, Then all sensitive fields are masked according to policy.
HIPAA Security: Encryption, Least Privilege, and Audit Logging
Given data in transit, When connectors communicate with PMS and internal services, Then TLS 1.2+ is enforced with strong ciphers and certificate pinning where supported. Given data at rest, When stored in databases, queues, and object storage, Then AES-256 encryption at rest is enabled with keys managed by KMS and key rotation at least annually. Given service accounts, When accessing PMS APIs and internal stores, Then least-privilege IAM policies restrict access to only required resources and operations, validated by automated access tests. Given logs and metrics, When generated, Then PHI/PII fields are redacted or tokenized and access to raw logs is audited. Given admin and data access, When performed, Then audit logs capture who, what, when, and where for 100% of operations, and logs are immutable and retained per policy.
Reconciliation Reports for Import Runs
Given any import run, When it completes, Then a reconciliation report is generated with counts of total, created, updated, unchanged, skipped, and failed by entity type (patient, household, relationship, insurance_link). Given the report, When downloaded via UI or API, Then it includes per-record error details (code, message, external_id) for failed/skipped items and a unique run_id. Given consecutive runs over the same input, When compared, Then record counts and checksums align for idempotent runs and deltas are attributable to PMS changes only. Given a failed run, When rerun after correction, Then the report shows only previously failed items processed and no duplicates introduced.
Relationship Inference Engine
"As a scheduling coordinator, I want the system to infer family relationships with confidence scores so that I can coordinate reminders without creating incorrect links."
Description

Create a rules-driven and heuristics-based engine that infers household membership and roles by evaluating signals such as shared address normalization, guardian/guarantor links, shared insurance subscriber, and last-name similarity. Assign confidence scores per inferred edge, apply configurable thresholds, and prevent false positives (e.g., multi-unit addresses, roommates, facility addresses). Generate a stable Household ID and explicit relationship edges (member, guardian, dependent) with provenance metadata. Provide collision detection and soft-locks to avoid oscillations across syncs. Surface low-confidence cases to a review queue.

Acceptance Criteria
Address Normalization and Multi-Unit False-Positive Prevention
Given multiple patient records with addresses that differ only by case, punctuation, or USPS abbreviations When the engine normalizes addresses Then records with different unit/apartment identifiers (e.g., Apt, Unit, #) are not linked into the same household And any edge based solely on shared street address without matching unit is assigned a score below the review threshold And addresses flagged as facility/business or PO Box are not used as sole signals to form a household
Guardian/Guarantor and Insurance Subscriber Inference
Given two or more patients share the same PMS guardian/guarantor identifier When the engine evaluates relationships Then create guardian→dependent edges with provenance PMS.guardian and a confidence score ≥ 0.90 And assign all members to the same household if no conflicting soft-lock or manual override exists Given patients share the same insurance subscriber ID and relation codes When the engine evaluates signals Then infer subscriber→dependent edges with provenance Insurance.subscriber and a confidence score ≥ 0.85 And do not require address match to commit these edges
Last-Name Similarity Matching with Safeguards
Given two patients share a normalized last name (case/diacritics/hyphenation insensitive) and a normalized street address including matching unit When the engine computes similarity Then assign a similarity-based edge with provenance Name.address and a confidence score ≥ 0.80 and commit only if score ≥ acceptance threshold Given last-name similarity exists without any other corroborating signal (address+unit, guardian, or insurance) When evaluating edges Then do not form a household; score remains below review threshold
Confidence Scoring and Configurable Threshold Behavior
Given the engine produces an inferred edge When scoring is applied Then a numeric confidence in [0,1] and a list of contributing signals with weights are persisted as provenance metadata Given system thresholds are configured as T_accept = 0.85 and T_review = 0.65 (defaults) When an edge score ≥ T_accept Then the edge is auto-committed; if T_review ≤ score < T_accept the edge is placed in the review queue; if score < T_review the edge is discarded And changing thresholds updates future evaluations without altering committed or soft-locked edges
Deterministic Household ID and Role Edge Generation
Given a set of committed relationship edges for a practice When the engine builds households Then it generates a deterministic Household ID per connected component that remains stable across syncs unless membership changes And all members receive explicit role edges (member, guardian, dependent) with timestamps and provenance And repeated syncs are idempotent: no duplicate edges and unchanged Household IDs for unchanged inputs
Collision Detection and Soft-Lock to Prevent Oscillation
Given a patient is assigned to Household A in one sync and inferred to Household B in a subsequent sync with comparable scores When the engine detects a potential oscillation (≥ 2 flips within 7 days or score delta < 0.05) Then it raises a collision event, applies a soft-lock to the current assignment, and prevents automatic reassignment And the case is added to the review queue with reason Oscillation and includes conflicting signals and scores And the soft-lock is cleared only by manual resolution or when source data materially changes (e.g., guardian removed)
Manual Overrides Precedence and Audit Trail
Given a user manually assigns or edits a household membership or relationship role When the engine runs subsequently Then manual overrides take precedence over inferred edges regardless of score and are not altered by automated syncs And an audit record is persisted including user, timestamp, action, and reason And removing the override returns the patient to automated inference on the next sync
Manual Household Overrides & Audit
"As a front-desk staff, I want to manually edit, merge, or split households with a full audit trail so that I can correct edge cases and stay compliant."
Description

Deliver a staff UI to view and edit household membership, designate primary/secondary guardians, and assign minors. Enable merge and split of households with conflict checks, preview diffs, and rollback. Persist manual overrides as first-class rules that supersede inference, survive re-syncs, and record full audit trails (who, what, when, why). Enforce role-based permissions and PHI masking by user role. Provide alerts when future syncs would overturn a manual decision, requiring explicit approval to apply.

Acceptance Criteria
Edit Household Membership and Roles
Given a user with Household.Edit permission is viewing a household When they add a patient by PMS ID or MRN and click Save Then the patient appears in the household within 2 seconds, a manual override rule (source=manual) is created, and the change is visible on refresh without re-login Given a user with Household.Edit permission When they set a Primary Guardian and one or more Secondary Guardians and assign minors Then exactly one Primary Guardian is enforced per household, each minor has at least one guardian, and violations block Save with error HH-VAL-001 Given a user with Household.Edit permission When they attempt to remove a guardian that would leave any assigned minor without a guardian Then the operation is blocked with error HH-VAL-002 and no changes are persisted Given pending membership/role edits When the user clicks Review Changes Then a diff panel shows before/after for members and roles, and only on Confirm are changes committed; Cancel discards all pending edits
Merge Households with Conflict Checks and Rollback
Given two households (A and B) are selected for merge by a user with Household.Merge permission When the user initiates Merge Then a pre-merge diff shows combined membership, role conflicts, duplicate contacts, and field-level conflicts with required selections for winners; unresolved conflicts disable Confirm Given a merge is confirmed When the operation completes Then a single merged household is created, source households are archived, message threads and appointments are re-linked, and completion occurs within 10 seconds for ≤10 members (≤20 seconds for >10) Given a merge completed within the last 30 minutes and no subsequent edits occurred When the user clicks Rollback Merge Then original households and relationships are restored, the merged household is archived, and all affected records are logged in audit with correlation ID Given a merge involves minors When guardianship conflicts arise Then the user must assign at least one guardian for each minor; otherwise Confirm remains disabled with error HH-MERGE-004
Split Household and Reassign Guardians
Given a user with Household.Split permission is viewing a household When they select one or more members to move to a new household and click Review Split Then a preview shows the source and new household memberships, guardians, minors, and contact details with required assignments Given the selection includes minors When there is no primary guardian assigned in the destination or source for those minors Then Confirm is disabled and error HH-SPLIT-003 is displayed until a primary guardian is assigned Given the user confirms the split When the operation completes Then a new household is created with a unique ID, threads and appointments are re-linked to the correct household, no duplicate outreach threads are created, and completion occurs within 10 seconds for ≤10 members Given a split completed within the last 30 minutes and no subsequent edits occurred When the user clicks Rollback Split Then the original household state is restored and an audit entry is created with correlation ID
Persist Manual Overrides Across PMS Re‑Syncs
Given a manual override rule exists for a household membership or role When a PMS re-sync imports inferred relationship changes that conflict Then the manual override remains in effect, no production data is changed automatically, and a suggestion is queued with status Requires Approval Given multiple re-syncs occur When the same conflicting inference is received Then the manual override continues to supersede inference on every sync until explicitly changed by an approver Given a manual override rule is explicitly removed by a user with Household.Edit permission When the next re-sync occurs Then inference is applied per Household Graph logic and the change is audited
Audit Trail for Household Overrides
Given any create/update/delete/merge/split of household membership or roles When the user attempts to Save Then a Reason field is required (≥3 characters); missing reason blocks Save with error HH-AUD-REQ Given a change is committed When the transaction completes Then an immutable audit record is written within 2 seconds capturing who (user ID), what (entities and fields before/after), when (UTC timestamp), why (reason), source (manual/API), and correlation ID Given a user with Audit.View permission When they open the Audit tab and filter by date range, action type, user, or patient ID Then matching audit entries are displayed within 2 seconds and can be exported to CSV; restricted roles cannot access audit data
Role-Based Permissions and PHI Masking
Given a user role lacking a specific permission (e.g., Household.Merge) When the user attempts the restricted action Then the action is blocked with 403 and no data is changed; an access-denied event is logged Given a user with a restricted role (e.g., ReadOnly or Clinician without PHI.Expanded) When viewing household details Then PHI is masked: DOB shows year only, phone shows last 4 digits, address shows city and state only, and masked values are not present in API responses or UI DOM Given an Admin or Manager with full permissions When performing the same views and actions Then no masking is applied and all permitted actions succeed Given permission changes are updated in IAM When the user session is refreshed or after 5 minutes, whichever comes first Then the new permissions take effect consistently across UI and API
Alerts and Approval for Override-Overturning Syncs
Given a PMS re-sync proposes a change that would overturn a manual decision (e.g., remove a manually added member) When the sync completes Then an alert is created in the Approval Queue within 1 minute, a banner appears on the household, and no data changes are applied automatically Given an approver with Override.Approve permission opens the alert When they review the diff and enter a reason (≥3 characters) Then Approve applies the change and deactivates or updates the manual rule; Reject dismisses the suggestion; both outcomes are audited Given an alert remains unaddressed When 3 business days elapse Then its status becomes Due and approvers receive a daily reminder notification until resolved
Household Threading & Bundled Outreach
"As an office manager, I want to message a single household thread with bundled appointment reminders so that families receive clear, consolidated communication."
Description

Create a household-level conversation object that consolidates communication across members and channels while respecting consent and preferences. Deduplicate automated reminders so a family receives a single, consolidated message with individualized appointment summaries and smart links per member. Implement routing rules to select the appropriate recipient (e.g., guardian for minors) and fallback logic per channel (SMS, email, voice). Support personalization tokens, language preferences, and quiet hours. Ensure opt-out is honored at person and household scopes with appropriate logging and compliance safeguards.

Acceptance Criteria
Household Conversation Creation & Consolidation
Given a household of 3+ members is synced from the PMS and linked by shared address/guardian or custom flag And at least one member has an upcoming appointment When any outbound automated reminder or manual staff message is initiated for any household member Then a single household-level conversation object is created if none exists, else the existing conversation is reused And all outbound messages (SMS, email, voice) and inbound replies across members attach to this conversation with per-message member attribution And the unified timeline displays events across channels in chronological order within 2 seconds of send/receive And the conversation header shows all household members and their next 30 days of appointments within 1 second of thread load And manual household membership overrides take effect in the conversation within 60 seconds and apply to subsequent routing decisions
Bundled Automated Reminder Deduplication
Given a household with 3 members each having a future appointment inside the same reminder window And automated reminders are enabled for the practice When the reminder job runs for that window Then exactly 1 outbound message per chosen primary channel is queued for the household (not per member) And the message contains individualized appointment summaries for each member: first name, date, time, location, provider And each summary includes a unique smart link parameterized by member_id and appointment_id And no additional per-member reminder messages are queued or sent for the same reminder window across any channel And a deduplication audit record is stored with job ID, household ID, affected member IDs, timestamp, and rule version
Recipient Routing & Guardian Selection
Given a household that includes minors with an assigned primary guardian and one or more adults And a Primary Contact is set to the guardian when any minor exists, otherwise to the designated adult contact When generating a bundled reminder Then the message is addressed to the Primary Contact for the household And the content lists each member by name with their appointment summary, clearly labeling minors And replies (e.g., CONFIRM/CANCEL or button clicks) update the correct member’s appointment status based on the targeted smart link or reply context And if the Primary Contact has no reachable consented channel for the send type, routing selects the next eligible guardian/contact according to configured priority without creating duplicates
Channel Preferences, Fallback, and Delivery Retries
Given channel preferences are configured at person and household levels (SMS > Email > Voice by default) And delivery constraints (carrier errors, hard bounces, unreachable, rate limits) are detected in real time When a bundled reminder send is initiated Then the system attempts the preferred allowed channel for the designated recipient respecting consent And on definitive failure (e.g., hard bounce, carrier code 30007, STOP), a fallback is attempted to the next allowed channel within 2 minutes And no more than 1 successful delivery per household per reminder window occurs across all channels And soft failures trigger up to 2 retries spaced at least 5 minutes apart on the same channel unless quiet hours intervene And all attempts and outcomes are logged with channel, status code, timestamp, and correlation IDs
Personalization Tokens and Language Preferences
Given a household default language and individual member language preferences are stored And message templates include member- and household-level tokens ({household_name}, {member_first}, {appt_time}, {smart_link}, etc.) When composing a bundled reminder Then the overall framing text is rendered in the recipient’s language preference, falling back to household default, then practice default And each member’s segment uses that member’s name, appointment details, and a distinct smart link And if any required token is missing, the send is blocked and a templating error is logged without partial delivery And links are unique per member-appointment pair and are verifiably correct via signed parameters
Quiet Hours and Time Zone Enforcement
Given practice-defined quiet hours (e.g., 9:00 PM–8:00 AM) and a household time zone resolved from address or explicit setting When a bundled reminder would otherwise be sent during quiet hours in the household’s local time Then the send is deferred until the next permitted window and the schedule reflects the deferred time And no SMS or voice calls are placed during quiet hours; email may be queued but not delivered until quiet hours end unless explicitly exempted by configuration And if deferral would miss a minimum notice threshold (e.g., <2 hours before appointment), the system sends via the least disruptive allowed channel (email) if permitted, otherwise suppresses and logs the exception And all deferrals and suppressions are recorded with reason, computed local time, and next action time
Consent, Opt-Out Scope, and Compliance Logging
Given consent and opt-out states exist at both person and household scopes per channel When composing and sending a bundled reminder Then household-level opt-out suppresses all outreach across channels for the household And person-level opt-out excludes that person’s PHI from the bundled content and suppresses any direct outreach to them while still allowing household delivery for others And all SMS include legally required opt-out text as configured (e.g., “Reply STOP to opt out”) And every send/suppress/partial include writes an immutable audit log with household ID, member IDs, scope evaluated, rule outcomes, content template ID, and a minimal-PHI payload And re-opt-in events re-enable outreach only for the scope and channels consented
Household Appointments Oversight
"As a receptionist, I want a household-level view of all upcoming appointments so that I can confirm or reschedule the family efficiently."
Description

Provide an at-a-glance household view listing upcoming and recent appointments for all members, with status badges (confirmed, pending, reschedule requested), conflicts, and gaps. Enable batch actions (confirm all, propose times, send prep instructions) and quick links to patient charts in the PMS. Sync appointment updates bidirectionally and display reason codes for failures. Include filters for provider, location, and date range, and performance targets to render within 200 ms for typical households.

Acceptance Criteria
Household View Performance (≤200 ms)
Given a typical household defined as ≤8 members and ≤20 total appointments across the past 30 days and next 30 days, and the appointment dataset has been returned to the client When a user opens the Household view Then the initial appointment list with status badges renders in ≤200 ms measured from data-ready timestamp to first contentful paint And the p95 of this render time across at least 100 consecutive loads in staging is ≤200 ms And if render time exceeds 200 ms, a non-PHI performance event is recorded with householdId and renderTime
At-a-Glance Appointments with Status Badges, Conflicts, and Gaps
Given household appointment data is available When the user views the Household Appointments panel Then upcoming (next 30 days) and recent (past 30 days) appointments for all members are listed with member name, date, start time, provider, and location And each appointment displays one of: Confirmed, Pending, Reschedule Requested based on the PMS-to-SmileCue status mapping And a Conflict badge appears when any two appointments within the selected range overlap by ≥1 minute; clicking the badge filters the view to conflicting items And a Gap indicator appears for any day in the selected range where at least one household member has an appointment and at least one does not; clicking the indicator shows the members without appointments for that day And counts of Conflicts and Gaps are displayed at the top of the list
Filtering by Provider, Location, and Date Range
Given filter controls for Provider, Location, and Date Range are visible When the user applies any combination of filters Then only matching appointments are displayed within 100 ms of selection after data is loaded And the default range shows upcoming next 30 days and recent past 30 days on initial load And clearing filters restores the full list without a page refresh And applied filters are shown as removable chips and persist for the session
Batch Confirm All Pending Appointments
Given at least one Pending upcoming appointment is visible and the user has Confirm permissions When the user clicks Confirm all and confirms the action Then all visible Pending upcoming appointments within the current filters are marked Confirmed in SmileCue and written to the PMS within 10 seconds p95 And a results summary displays counts for Attempted, Confirmed, Skipped (already confirmed), and Failed And each failure displays the PMS reason code and a retry option And an audit entry is recorded per appointment with actor, timestamp, old status, and new status
Batch Propose Times and Send Prep Instructions
Given one or more appointments are selected and the user has Messaging permissions When the user selects Propose times Then the user can choose up to three time options per appointment and send a single consolidated message to the household thread; each proposal is associated to its appointment And if the PMS supports time holds/proposals, corresponding holds are created; otherwise only the message is sent; any PMS errors show a reason code When the user selects Send prep instructions Then the correct template per appointment type is sent to the household thread for each selected appointment, deduplicated per patient per day, and outcomes show Delivered, Bounced, or Failed with channel-specific reason codes And all batch messages respect opt-out status and channel preferences; non-delivered items are reported with reason codes
Quick Links to PMS Patient Charts
Given appointment rows are visible When the user clicks a patient's Chart link Then the PMS chart opens in a new tab/window using the configured deep link and loads the correct patient within 3 seconds p95 And if SSO or deep linking is unavailable, the link is disabled with a tooltip explaining the limitation And the link is generated without exposing PHI beyond PMS-required identifiers And only users with the appropriate role see the Chart link
Bidirectional Sync and Failure Reason Codes
Given the PMS integration is connected When an appointment status is updated in the PMS Then the Household view reflects the change within ≤60 seconds p95 and displays the updated timestamp When an appointment status is updated from SmileCue Then the PMS is updated accordingly; on failure, the UI shows a failure icon with a machine-readable reason code and human-readable message from the PMS, accessible via hover/click And sync handling is idempotent; duplicate events do not create duplicate updates And a Last sync indicator shows time since last successful sync; if >5 minutes, a non-blocking warning is shown
Consent & Preferences Inheritance
"As a compliance officer, I want consent and channel preferences to inherit to the household and minors appropriately so that outreach remains compliant and respectful."
Description

Model and enforce consent, privacy, and channel preferences at both person and household scopes with clear inheritance for minors and dependents. Capture source, timestamp, and proof of consent; support TCPA-compliant opt-in/opt-out workflows per channel. Apply precedence rules (individual overrides household), and guardrails to prevent sending PHI-bearing content where consent is absent. Expose UI to review and edit preferences, and validators that block outbound sends violating policy. Maintain a compliance log for audits.

Acceptance Criteria
Household Defaults Inherit to Minors
- Given a household with SMS and email Opt-In and a new minor dependent without explicit preferences, When the minor record is saved, Then the minor's effective preferences mirror the household per channel and are labeled Inherited in the UI. - Given inherited preferences, When the household updates a channel consent, Then all dependents with inherited status update accordingly and the compliance log records a cascade event for each dependent. - Given a dependent with inherited consent, When staff edits the dependent's preference, Then the system allows a manual override that converts the status to Individual with its own source and timestamp.
Individual Overrides Household
- Given a person with an individual SMS Opt-Out and the household is Opt-In, When computing effective consent, Then SMS is treated as Opt-Out for that person. - Given a person with an individual override, When the household consent later changes, Then the person's individual setting remains unchanged and continues to take precedence. - Given an outbound household-thread message, When recipients are resolved, Then the system excludes any channel/person combinations that are Opt-Out by individual override and displays a per-recipient consent status. - Given an override is created or removed, When the action completes, Then the compliance log captures actor, timestamp, channel, old/new values, and proof reference.
TCPA-Compliant SMS Opt-In/Opt-Out
- Given a mobile number with no prior consent, When the patient texts START to the practice number or clicks a compliant opt-in link, Then the system marks SMS as Opt-In for that person, storing source, timestamp, and capture context. - Given an opted-in number, When the patient texts STOP, Then SMS is immediately marked Opt-Out for that person and all automated and manual SMS are blocked within 60 seconds. - Given SMS Opt-Out by keyword, When any SMS is attempted to that number, Then the system prevents sending and replies once with a compliance message indicating opt-out status; no PHI is included. - Given TCPA keywords HELP, START, STOP, When received, Then the system responds with compliant templates and updates state accordingly, logging message bodies and short codes used. - Given consent capture via web form, When the form is submitted, Then a signed proof artifact (IP, user agent, checkbox text, timestamp) is stored and linked to the consent record.
PHI Guardrails and Send-Time Validation
- Given content detected as PHI-bearing by tags or classifier, When effective consent for a channel is not Opt-In, Then the send action is blocked and the UI shows a clear error with channel, rule violated, and remediation steps. - Given a bulk or automated campaign, When recipients are compiled, Then the validator removes non-consented channel/persons before scheduling and provides a downloadable suppression report. - Given a manual one-to-one message, When a user attempts to override a block, Then the system does not allow send but may allow scheduling a non-PHI template; all attempts are logged as denied. - Given multiple channels configured, When at least one channel has PHI-safe consent, Then the system suggests and can auto-route via the compliant channel if enabled.
Preferences Review and Edit UI
- Given a household record is opened, When the Preferences tab is viewed, Then the UI displays a matrix of channels (SMS, Email, Voice) by person with Effective, Source (Household/Individual/PMS/Web), Timestamp, and Proof links. - Given a user with appropriate role, When editing preferences, Then the UI supports per-channel toggles, marking overrides vs inherited, with inline validation and confirmation modals citing compliance text. - Given a change is saved, When the operation succeeds, Then the UI updates immediately, the change is propagated to effective consent, and a toast confirms success with compliance log ID. - Given a user without permission, When attempting to edit, Then controls are disabled and an explanatory tooltip is shown; no backend mutation is attempted.
Compliance Log and Audit Export
- Given consent changes and send decisions occur, When viewing the Compliance Log, Then entries include event type, actor/system, person/household IDs, channel, old/new values, timestamps (UTC and local), and proof hashes/URLs. - Given an auditor date range and filters, When export is requested, Then the system generates a CSV within 60 seconds containing all matching entries with stable column headers and a cryptographic checksum. - Given an export is generated, When the download completes, Then the action is recorded as an audit event including who downloaded and the filter parameters.
PMS Consent Import and Conflict Resolution
- Given PMS provides consent/preference flags per patient and channel, When nightly import runs, Then the system maps flags into SmileCue channels, sets source = PMS with timestamp, and applies them according to predefined mapping rules. - Given a PMS value conflicts with an existing individual override, When resolving, Then the individual override is retained and the PMS value is stored as a historical snapshot without changing effective consent. - Given PMS provides ambiguous or missing consent, When mapping, Then the system defaults to the most restrictive (Opt-Out/Unknown), flags the record for review, and notifies staff via a dashboard alert. - Given multiple PMS records belong to the same household, When imported, Then household-level defaults are set only if all members share the same consent state per channel; otherwise no household default is created.
Household Graph Data Model & APIs
"As a developer, I want stable APIs and a clear household graph model so that other SmileCue modules can query and act on household data reliably."
Description

Define a scalable, normalized data model for households, members, guardianship roles, contact endpoints, consent artifacts, and edge confidence/provenance. Provide internal APIs to query a patient’s household, list members and roles, fetch household appointments, and initiate household conversations. Guarantee SLAs (p95 < 200 ms) and pagination for large families. Implement RBAC, row-level security, and audit logging for every read/write. Offer change events (webhooks/message bus) so other SmileCue services react to household updates.

Acceptance Criteria
Query Household and List Members
Given a valid patient_id mapped to a SmileCue patient When GET /households?patient_id={id} is called Then respond 200 with a single household object containing: id, external_keys, created_at, updated_at, provenance, and an array members[] And members[] includes for each member: patient_id, role ∈ {self, guardian, dependent, other}, relationship_edges[], confidence_score (0.0–1.0), provenance.sources[], and contact_endpoints[] with {type ∈ {sms,email,voice}, value, verified, consent_artifact_id} And the household contains no duplicate patient_ids and includes primary_guardian_id when ≥1 guardian exists And relationship_edges[] include {from_member_id, to_member_id, relationship_type, confidence_score, provenance} And if the patient_id does not belong to any household, respond 404 And response JSON schema validates against versioned contract v1.0 and includes ETag header for caching And the same shape is returned when GET /households/{household_id}/members is called, limited to members[] only
Fetch Household Upcoming Appointments
Given an existing household_id and default time window of now..+30d When GET /households/{household_id}/appointments?from={iso}&to={iso}&status=in([scheduled,confirmed,rescheduled]) is called Then respond 200 within p95 < 200 ms with a list of appointment objects: {appointment_id, patient_id, start_at, end_at, location_id, provider_id, status} And results are scoped to members of the household and de-duplicated across PMS sources And results are sortable by start_at asc and paginated (cursor) with page.size default 25, max 100, and next/prev cursors And invalid date ranges return 400 with error.code=invalid_date_range And requesting a household outside caller’s tenant returns 403
Initiate Household Conversation with Consent Enforcement
Given a valid household_id and a message payload {channel ∈ {sms,email,voice}, template_id or body, metadata, idempotency_key} When POST /households/{household_id}/conversations is called by an authorized user Then if at least one member has a contact_endpoints entry for the channel with verified=true and a valid consent_artifact scope=household_messaging status=granted Then respond 201 with {thread_id, targeted_members[], skipped_members[] with reasons, message_preview} And if zero eligible endpoints exist, respond 409 with error.code=no_eligible_recipients And consent revocations or expirations are honored in real time (no message sent to revoked endpoints) And repeated requests with the same idempotency_key within 24h are treated idempotently and return the original 201 response And the created thread is linked to the household_id and visible in household timeline
Manual Override of Household Relationships with Provenance
Given an authorized user with households.write permission When POST /households/{household_id}/relationships is called with {from_member_id, to_member_id, relationship_type, role_updates, confidence_score=1.0, provenance.source=manual} Then respond 200 with updated household graph reflecting the override and a new provenance entry capturing actor_id, timestamp, and rationale And invariants are enforced: no self-guardianship, no cycles in guardianship graph, a member may have multiple guardians but at most one primary_guardian And a change log entry is created with before/after snapshots of affected edges And invalid member_ids return 404; invalid relationship_type returns 400 And overrides can be reverted via POST /households/{household_id}/relationships/revert with a prior change_id returning the previous state
Performance and Pagination SLAs
Given production-like test data with households up to 100 members and 500 upcoming appointments across the window When calling GET /households?patient_id=*, GET /households/{id}/members, GET /households/{id}/appointments, and POST /households/{id}/conversations under p95 load of 50 RPS per endpoint Then each endpoint’s p95 latency is < 200 ms and error rate < 0.1% And all list endpoints support cursor pagination with page.size default=25, max=100, deterministic ordering, and return next/prev cursors when more data exists And responses include X-Request-ID and total_count if requested via include_total=true with p95 remaining < 200 ms for result sets ≤ 1,000 items And load tests and results are stored with reproducible scripts and benchmarks
RBAC, Row-Level Security, and Audit Logging
Given a caller with households.read permission scoped to tenant T When accessing any households* endpoint for a household in tenant T Then respond with 2xx; otherwise 403 for households in other tenants And service accounts with role=service-household can read/write only within assigned tenants and actions are constrained by least privilege And every read/write produces an immutable audit record containing: timestamp, actor_id, actor_type, tenant_id, endpoint, verb, resource_ids (household_id, patient_ids), correlation_id, source_ip, and for writes a before/after diff hash and full snapshot in secure storage And audit records are retrievable by security admins with filtering by actor_id, resource_id, time range And PHI is encrypted in transit (TLS1.2+) and at rest; logs exclude PHI fields except hashed identifiers
Change Events on Household Updates
Given a household is created, updated, member added/removed, relationship changed, consent updated, or contact endpoint updated When the change is committed Then emit an event to the message bus topics=households.v1 with event_type ∈ {household.created,household.updated,member.added,member.removed,relationship.updated,consent.updated,contact.updated}, schema-version, household_id, changed_fields, actor, and sequence number guaranteeing in-household ordering And deliver webhooks to subscribed tenants with HMAC-SHA256 signature over the body using tenant secret, idempotency-key header, and retries (1s, 5s, 30s) up to 5 attempts before DLQ And duplicate deliveries are safely ignored by consumers using idempotency-key And events are published within 1s of transaction commit and are at-least-once

Sibling Stacker

Finds optimal back-to-back or concurrent slots for siblings across providers and rooms, then offers 2–3 ready-to-book bundles inside one parent-friendly message. On tap, it confirms all selected slots and writes them back to the calendar, minimizing trips and maximizing chair utilization without manual juggling by the front desk.

Requirements

Family Linking & Eligibility Detection
"As an office manager, I want the system to correctly identify siblings under a shared guardian and verify communication consent so that I can confidently send bundled offers without risking privacy violations or manual cleanup."
Description

Automatically detect and maintain sibling relationships and guardian linkage within SmileCue using patient demographics and household data from the practice management system. Validate that a single guardian has communication consent for all included dependents before generating offers. Aggregate each child’s appointment needs (type, duration, due date), provider eligibility, and room/equipment constraints into a unified request object. Enforce contact preferences and quiet hours at the guardian level. Prevent cross-family leakage by scoping PHI to authorized guardians only and masking nonessential PHI in downstream messages.

Acceptance Criteria
PMS-Driven Family Linking Sync
Given a PMS export or webhook event provides patient, guardian, and household identifiers with last_updated timestamps When the nightly sync runs or a real-time event is received Then SmileCue creates/updates a familyId linking all siblings that share the guardianId and household, within 15 minutes of receipt And a single guardianId is associated to all linked dependents with relationship type = guardian And removed/changed guardian relationships in PMS are reflected in SmileCue within 15 minutes And conflicting data (e.g., the same dependent linked to two unrelated households) results in no family linkage change, the record is flagged "review_required", and no sibling offers are generated for the impacted familyId
Guardian Consent Gate for Bundle Generation
Given a candidate familyId with N dependents and a target outbound channel (SMS, Email, Voice) And valid communication consent exists for the guardianId across the selected channel for all N dependents When the system attempts to generate a sibling bundle offer Then the bundle is generated And if any dependent lacks consent for the selected channel, no bundle is generated And the abort reason "missing_consent" is logged with dependentIds and channel And no outbound message is queued
Unified Family Scheduling Request Object
Given dependents with appointment needs from the PMS (appointment type code, duration, due_date) and SmileCue rules When constructing the FamilySchedulingRequest Then the object contains for each dependent: dependentId, appointmentTypeCode, appointmentCategory, durationMinutes, dueDate, dueWindowStart, dueWindowEnd, providerEligibleIds[], providerExcludedIds[], roomRequiredTags[], equipmentRequiredTags[] And the object contains shared fields: familyId, guardianId, practiceId, timezone, createdAt, priorityScore And durationMinutes are normalized to 5-minute increments And due windows are computed per practice rules (e.g., dueDate +/- 14 days) and stored as ISO-8601 timestamps And the object validates against JSON schema v1.0 and rejects on schema violations
Guardian-Level Contact Preferences and Quiet Hours Enforcement
Given guardian-level preferences: channelOrder, channelOptOuts[], quietHoursStart, quietHoursEnd, timezone When queuing any outbound sibling bundle message Then the system selects the first available channel in channelOrder not present in channelOptOuts And messages are not sent during quiet hours in the guardian's timezone And if queued during quiet hours, delivery is scheduled for the next allowed window And channel-specific compliance flags (e.g., SMS STOP) are honored and prevent send And all decisions are written to the message audit log
PHI Minimization and Masking in Downstream Messages
Given a generated sibling bundle for a guardianId When rendering message content and deep links Then only data for dependents authorized to the guardianId is included And allowed fields in the message are limited to: childFirstName, appointmentCategory, offeredSlotDateTime, providerDisplayName, practiceName, locationCity And the following PHI is never included in messages: MRN, full DOB (age may be shown), full address, insurance details, medical history, internal identifiers And all links are single-use, tokenized, scoped to guardianId + familyId, and expire after 30 minutes And unauthorized access to a link returns HTTP 403 without disclosing whether records exist
Cross-Family Data Access Controls
Given an authenticated guardian or internal API call scoped to guardianId A When requesting family data, offers, or scheduling requests Then only records where guardianId A is authorized are returned And records for other familyIds are not returned or enumerated And attempts to access other familyIds return HTTP 403 and are logged with correlationId and IP And sibling bundles cannot include dependents from more than one familyId And database queries enforce row-level filters on guardianId/familyId
Audit Trail for Eligibility and Consent Decisions
Given any decision to include or exclude a dependent from a bundle due to eligibility, constraints, or consent When the decision is made Then an audit record is written with timestamp, guardianId, familyId, dependentId, decision, reasonCode, actor, and source eventId And audit records are immutable and retained for 7 years And authorized staff can query the audit log by guardianId and date range
Multi-Provider Slot Optimization Engine
"As a parent, I want the system to find back-to-back or same-time appointments for my children so that we can complete all visits in one trip with minimal waiting."
Description

Compute candidate bundles of back-to-back or concurrent appointments across providers and rooms that satisfy each child’s appointment requirements. Respect provider skills, room/equipment availability, buffers and cleaning times, guardian preference windows (e.g., after school), and practice hours. Optimize for minimal total visit time, minimal gaps between siblings, and provider continuity. Return results in under two seconds for typical two- to three-sibling scenarios. Support configuration for search horizon, bundle size, and whether concurrency is allowed per practice policy.

Acceptance Criteria
Back-to-Back Bundles Respect Buffers and Cleaning Times (No Concurrency)
Given concurrency is disabled, provider buffer is 10 minutes, and room cleaning time is 5 minutes And two siblings each require a 30-minute appointment with qualified providers and available rooms When the engine computes bundles over a 7-day horizon with bundle size set to 3 Then every returned bundle schedules the siblings back-to-back with required buffers and cleanings inserted And no provider, room, or equipment is double-booked And the gap between siblings within each bundle is minimized given the constraints And total visit time per bundle is minimized among feasible options
Concurrent Bundles Enforce Provider Skills and Room/Equipment Constraints
Given concurrency is enabled by practice policy And sibling A requires provider skill S1 and equipment E1 and sibling B requires provider skill S2 and equipment E2 And qualified providers and rooms are available in overlapping time slots When the engine computes bundles over a 14-day horizon with bundle size set to 3 Then at least one returned bundle schedules the siblings concurrently in different rooms with qualified providers And no provider, room, or equipment is assigned to overlapping appointments And equipment availability is honored with no simultaneous over-allocation
Guardian Preference Windows and Practice Hours Are Respected
Given the guardian preference windows are weekdays 15:00–18:00 local time and practice hours are 08:00–18:00 When the engine computes bundles Then all returned bundles start and end within both the guardian preference windows and the practice hours And if no feasible bundles exist within the preference windows, the engine returns an empty result set within the performance SLA
Optimization Ordering, Provider Continuity, and Deterministic Sorting
Given multiple feasible bundles exist for the same siblings When the engine ranks and returns results Then bundles are ordered by (1) minimal total visit time, (2) minimal gap between siblings, (3) maximal provider continuity (fewest distinct providers), then (4) earliest start time as deterministic tie-breaker And only the top N bundles equal to the configured bundle size are returned in that order
Configurable Search Horizon, Bundle Size, and Concurrency Policy
Given practice configuration sets search horizon to 14 days, bundle size to 2, and concurrency policy to disabled When the engine computes bundles Then no returned bundle schedules siblings concurrently And exactly 2 bundles are returned And all returned bundles fall entirely within the next 14 calendar days from the search start
Performance SLA for Typical Two- to Three-Sibling Cases
Given a typical dataset with 2–3 siblings, a 14-day search horizon, and normal provider and room availability When the engine computes bundles under production conditions Then the p95 end-to-end response time per request is ≤ 2.0 seconds And any empty-result response (no feasible bundles) also meets the same SLA
Bundle Ranking & Deduplication
"As a guardian, I want to receive the top two to three appointment bundles that best match my preferences so that I can choose quickly without reviewing dozens of options."
Description

Score and rank candidate bundles using configurable signals: guardian-stated day/time preferences, historical show patterns, distance/travel constraints, time between sibling appointments, and provider continuity. Deduplicate near-equivalent bundles and ensure two to three distinct, high-quality choices. Validate availability at render time; drop stale bundles and refill as needed. Expose ranking diagnostics for admins to aid troubleshooting without revealing PHI.

Acceptance Criteria
Weighted Multi-Signal Bundle Ranking
Given a configured weight set {guardian_pref, show_pattern, travel, gap, provider_continuity} (versioned) and a set of candidate bundles When ranking is executed Then each bundle's total score equals the weighted sum of normalized signal contributions and bundles are ordered by descending score Given two bundles have equal total scores to three decimal places When tie-breaking is applied Then order by earliest overall start time, then smallest total inter-appointment gap, then ascending provider IDs Given up to 200 candidate bundles When ranking runs on the production service Then it completes within 300 ms p95 Given weights are updated and saved When a subsequent ranking is performed Then the new weight version is applied and stored with each ranked result
Near-Equivalent Bundle Deduplication and Distinct Choices
Given a ranked list of bundles When deduplication runs Then any two bundles are considered near-equivalent if they include the same siblings on the same date with identical provider assignments and all sibling start times within 10 minutes; only the highest-scoring bundle is kept Given more than three distinct bundles remain after deduplication When preparing the offer list Then only the top three are kept Given fewer than two bundles remain after deduplication When search expansion is attempted (provider-equivalents and ±30-minute window) Then either at least two bundles are produced or the system returns "insufficient availability" and does not send offers Given any bundle is removed by deduplication When diagnostics are generated Then the removal reason "near-equivalent" is recorded
Render-Time Availability Revalidation and Refill
Given a prepared list of 2–3 bundles with stored slot revision tokens When a parent-facing message is rendered (preview or send) Then each slot is revalidated against the calendar; only bundles with all slots available are shown When any slot fails revalidation Then that bundle is dropped and the next highest-ranked non-duplicate candidate is inserted until 2–3 valid bundles are present or none remain Then revalidation and refill complete within 2 seconds p95; if fewer than two valid bundles remain, the message is not sent and the UI/API returns "no valid bundles" Then each presented bundle displays a "validated at" timestamp no older than 60 seconds
Admin Ranking Diagnostics (No PHI) with RBAC and Audit
Given an Admin or Support user opens diagnostics for a ranking When the data loads Then it includes for each bundle: total score, per-signal contributions, weight version, tie-break path, and prune reasons Then no PHI is present: no patient names, phone numbers, emails, DOBs, addresses, or free-text; patients are represented by internal hashed IDs; provider identities use non-PHI codes When a non-Admin/Support user attempts access Then access is denied and the attempt is audit-logged with user ID, timestamp, and ranking ID Then all diagnostics access is audit-logged and data retention does not exceed 30 days
Guardian Preference Prioritization in Offered Bundles
Given guardian preferences define one or more preferred day/time windows When there are two or more candidate bundles fully inside any preferred window Then the top two offered bundles are selected from within those windows When exactly one candidate bundle is inside a preferred window Then it is ranked first; remaining offered bundles are the highest-scoring within ±60 minutes of a preferred window When no candidates exist within ±60 minutes of preferences and the "allow outside preference" policy is disabled Then no offers are sent and "no suitable bundles" is returned Then all preference parameters (windows and ± buffer) are configurable; default buffer is 60 minutes
Travel and Inter-Appointment Gap Constraints Enforcement
Given practice-configured constraints (concurrent appointments must be in the same location; back-to-back min gap ≥ 5 minutes; max gap ≤ 20 minutes unless overridden) When generating bundles Then any bundle violating these constraints is excluded before ranking When multiple locations exist Then concurrent sibling appointments are considered valid only if all appointments occur at the same location code Then the per-bundle total inter-appointment gap is computed and exposed in diagnostics
Historical Show Pattern Influence on Ranking
Given a sibling's historical show pattern indicates low show rates for specified time segments and the show_pattern weight > 0 When ranking bundles Then bundles within low-show segments incur a penalty reflected in the per-signal score Given at least one candidate bundle falls outside the identified low-show segments and meets other constraints When selecting the 2–3 bundles to offer Then at least one of the offered bundles avoids low-show segments Then the time-segment classification and penalty amount are visible in diagnostics without exposing PHI
Parent-Friendly Unified Offer Message
"As a busy parent, I want a single, easy-to-understand message with a couple of great options I can confirm in one tap so that scheduling takes seconds, not calls back and forth."
Description

Generate a single message per guardian that presents two to three tappable appointment bundles with clear labels (child names, date, start/end time, providers, and estimated visit length) and a one-tap confirmation call-to-action per bundle. Support SMS, email, and voice with consistent content, localization, and accessible formatting. Use secure deep links that reveal sensitive details only after authentication when required by practice policy. Integrate with SmileCue’s adaptive branching to handle replies such as numeric selections, requests for more options, or a call-back. Track delivery, open, and selection events for analytics and retries.

Acceptance Criteria
Unified Offer with 2–3 Clearly Labeled Bundles
Given a guardian has at least two eligible sibling scheduling bundles When the unified offer message is generated Then include exactly 2 or 3 bundles, ranked by earliest acceptable time and shortest total visit duration And each bundle displays: child name(s), appointment date, start time, end time, provider name(s), room (if applicable), and estimated visit length in minutes And each bundle includes one primary CTA labeled "Confirm this time" with a unique deep link And no duplicate times or overlapping bundles are shown within the same message And if fewer than 2 eligible bundles exist, do not send the unified offer and escalate to the standard outreach flow
Channel Consistency, Localization, and Accessibility
Given SMS, email, and voice templates are configured for the practice When a unified offer is sent across any supported channel Then the content order, labels, and bundle details are semantically equivalent across channels And localization uses the guardian’s preferred locale and time zone (12/24‑hour format accordingly) And the SMS body is ≤ 480 GSM‑7 chars (or ≤ 210 UCS‑2 chars) and ≤ 3 concatenated segments; links are tappable And the email version meets WCAG 2.1 AA for contrast, has logical headings, and is mobile‑responsive And the voice version (TTS/IVR) reads each option with child name, date, start/end time, provider, length, offers DTMF instructions, and completes in ≤ 90 seconds for 3 options And if a localized template is missing, fall back to the practice default locale with a consistent format
Secure Deep Links with Policy‑Driven Authentication
Given a practice policy that may require authentication to view appointment details When a guardian taps a bundle CTA Then sensitive details are revealed only after successful authentication if policy=auth‑required; otherwise they are shown immediately And deep links are tokenized, HMAC‑signed, scoped to guardian+bundle, single‑use or expire within 72 hours (configurable) And no PHI appears in the URL, notification previews, or unauthenticated screens; pre‑auth content is limited to minimal identifiers (e.g., child first name + initial) And expired or invalid links display a friendly error, offer to resend or request a call‑back, and do not leak data
One‑Tap Confirmation and Atomic Calendar Write‑Back
Given the guardian selects a bundle via its CTA When confirmation is submitted Then all involved provider and room slots are held, re‑validated for conflicts and eligibility, and written back atomically to the practice calendar And on any partial failure the transaction is rolled back, the guardian receives a clear retry/alternative message, and the front desk is alerted with error details And successful confirmations return a success screen and send a confirmation receipt via the original channel within 10 seconds at p95 And created calendar entries include source=SmileCue, campaign/message IDs, and a complete audit trail (guardian, time, channel)
Adaptive Branching for Selections, More Options, and Call‑Back
Given a guardian replies to the unified offer When the reply is numeric 1–3 (SMS/email) or DTMF 1–3 (voice) Then the corresponding bundle is selected and confirmation flow begins And replies of “more”/“M” (SMS/email) or DTMF 9 (voice) return up to 3 new bundles without repeating prior ones And replies of “call”, “call back” (SMS/email) or DTMF 0 (voice) create a call‑back task with contact times And invalid/ambiguous replies prompt a help message and up to 2 retries before escalating to human follow‑up And all branches are idempotent, rate‑limited, and fully logged with outcome codes and timestamps
Event Tracking and Intelligent Retries
Given analytics and delivery tracking are enabled When a unified offer is sent Then delivery, open (email open or first link click for SMS), and selection/confirmation events are recorded with timestamp, channel, message ID, bundle ID, and guardian ID And events are deduplicated per guardian+message and available to BI within 5 minutes at p95 And non‑delivery or no‑open within 24 hours triggers a single retry via an alternate permitted channel; if none available, the attempt is logged with reason And reporting surfaces confirmation rate, time‑to‑open, and time‑to‑confirm per campaign without exposing PHI in exports
Atomic Multi-Slot Booking & Calendar Write-Back
"As a front-desk coordinator, I want bundle confirmation to book all required slots together and update the calendar automatically so that I don’t have to fix partial or conflicting appointments."
Description

Confirm all appointments in a selected bundle as a single atomic transaction with short-lived slot holds during review. Write back confirmations to the practice calendar in real time; on any failure, roll back all changes to prevent partial bookings. Implement idempotent confirmation links and concurrency controls to handle race conditions. Update downstream reminders and confirmations, notify providers as configured, and emit auditable events for each step.

Acceptance Criteria
Atomic Multi-Slot Confirmation Succeeds
Given a bundle of 2–4 sibling appointment holds across providers and rooms with a valid confirmation link and a 5-minute hold window When the parent taps Confirm within the hold window and no conflicts exist Then all slots are committed in a single atomic transaction And each appointment is written back to the practice calendar successfully in real time And the parent receives a success response within 2 seconds (p95) And a single booking group ID is assigned and stored on each appointment And auditable events are emitted: bundle_confirmed and appointment_confirmed (per slot) with a shared correlation ID
Rollback On Partial Failure During Write-Back
Given a selected bundle with valid holds And at least one downstream calendar write-back is configured to fail When the parent taps Confirm Then the transaction aborts and no appointments are confirmed in any system And all holds are immediately released And the parent sees a clear failure message with a Retry option And no reminders or provider notifications are scheduled And an audit event bundle_rolled_back is emitted with error codes and correlation ID
Idempotent Confirmation Link Prevents Duplicates
Given a confirmation link containing an idempotency key for a specific bundle When the link is invoked multiple times or retried within 24 hours Then the first valid request performs the confirmation And subsequent requests return an already_confirmed result without creating duplicate appointments And no duplicate reminders or notifications are generated And audit events record deduplicated attempts referencing the same idempotency key and correlation ID
Concurrent Booking Conflict Detected and Handled
Given one or more held slots in the bundle are booked externally before commit When the parent attempts to Confirm the bundle Then the system detects the conflict during commit and aborts the transaction And all holds are released And the parent is informed the bundle is unavailable and is offered 2–3 alternative bundles within 3 seconds And events are emitted: bundle_conflict_detected and bundle_rolled_back with details of conflicting slots And no appointments are written to the calendar
Hold Expiration Frees Slots and Expires Offer
Given bundle holds are created with a 5-minute TTL When the TTL elapses before confirmation Then all holds are released and slots become publicly available within 10 seconds And the confirmation link returns an offer_expired state (HTTP 410) And no appointments are created And an audit event hold_expired is recorded with the affected slot IDs and group ID
Downstream Reminders and Provider Notifications Post-Commit
Given a successful atomic confirmation of the bundle When the commit completes Then patient-facing confirmation messages are queued within 30 seconds per appointment And reminder schedules are generated per practice rules and visible in the reminders queue And provider notifications are sent via configured channels with the booking group ID referenced And failures in downstream messaging do not affect booking state but are logged with retry policies and audit events
End-to-End Audit Trail and Correlation
Given any bundle confirmation attempt (success or failure) When the workflow executes Then events are emitted for each step: holds_created, confirm_initiated, write_back_attempted (per slot), bundle_committed or bundle_rolled_back, notifications_enqueued And each event includes timestamps (UTC), practice ID, group ID, correlation ID, and minimal necessary PHI per HIPAA And events are retained for 24 months and are queryable by practice ID and group ID And an audit report for a group ID can be exported in under 10 seconds
Consent, Privacy, and Audit Controls
"As a compliance officer, I want consent, privacy controls, and auditable records for family-based scheduling so that the practice can meet HIPAA obligations while using Sibling Stacker."
Description

Manage guardian consent for multi-child communications, including verification of the relationship and authorized channels. Minimize PHI in outbound offers and reveal details only after secure authentication when required. Encrypt data in transit and at rest, enforce role-based access within SmileCue, and maintain comprehensive audit logs of offer generation, viewing, and booking events. Provide admin tools to review, revoke, or update consent and purge family linkages on request.

Acceptance Criteria
Guardian Verification and Consent for Multi-Child Messaging
Given a guardian record is associated with multiple children and at least one child lacks verified relationship and active consent When Sibling Stacker prepares a multi-child offer Then the system blocks offer generation and initiates the guardian verification flow And verification requires a single-use, 10-minute token and successful 6-digit OTP to an on-file channel And the consent capture requires per-child selection of authorized channels (SMS, Email, Voice), an e-sign attestation, and capture of timestamp, IP, and user agent And upon success, consent status per child and per channel is set to Active with recorded version and expiration And upon failure or timeout, no offer is generated and an audit event is recorded
Channel Authorization and Opt Preferences Enforcement
Given an outbound message is to be sent for a sibling bundle When evaluating each child and channel Then the system sends only via channels with Active consent for that child And channels with Opted Out or Revoked status are excluded from delivery And if no authorized channel exists for a child, that child is excluded from the offer without disclosing their existence And a suppression audit event with reason code is recorded And revocations take effect for new sends within 5 minutes And any queued messages on revoked channels are canceled prior to dispatch
PHI Minimization in Outbound Sibling Stacker Offers
Given an outbound SMS/email/voice offer is composed prior to guardian authentication When generating message content Then the message includes only practice name, generic family phrasing (e.g., "your children"), count of bundles, date(s) and time windows, and a secure short link And the message does not include child names or initials, DOB, procedure type, provider name, operatory, MRN, or other PHI And the link contains no PHI in path or query and uses a random 128-bit token And tokens are single-use and expire in 10 minutes
Secure Detail Reveal After Guardian Authentication
Given a guardian opens the secure short link When they authenticate with OTP to an on-file channel within the token TTL and pass rate limits (max 5 attempts/hour; CAPTCHA after 3 failures) Then the UI reveals child names, providers, exact time slots, and room assignments for the offered bundles And on booking, selected slots are confirmed atomically across children or none are booked on failure And sessions auto-expire after 5 minutes idle or 15 minutes absolute And failed or expired attempts reveal no PHI and return a generic error
Role-Based Access Controls for Consent and Family Linkages
Given users have roles Admin, Front Desk, Clinician, and Support When accessing consent artifacts and family linkage data Then only Admins can create, revoke, update, or purge consent and linkages And Front Desk can view consent status and resend verification links but cannot edit or export artifacts And Clinicians can view consent status read-only; Support can view log metadata but not PHI or artifacts And authorization is enforced at API and UI layers; unauthorized requests return 403 and are audited And least-privilege access is verified with automated tests per role for read, write, export, and purge endpoints
End-to-End Audit Logging for Offer and Consent Lifecycle
Given lifecycle events occur (offer generated/viewed/authenticated/booked/canceled; consent created/updated/revoked; family linkage created/purged) When any such event is processed Then an immutable audit record is written with event type, actor (user ID or system), target IDs (guardian, child, offer), UTC timestamp, IP, user agent, outcome, and reason code And audit logs are stored in append-only WORM storage with retention of at least 6 years And admins can filter, search, and export logs by date range, event type, actor, and outcome And logs are tamper-evident via cryptographic hash chaining, with verification jobs running daily
Data Encryption In Transit and At Rest
Given data moves between clients, services, and storage When transmitting any data Then TLS 1.2+ with strong ciphers and HSTS is enforced; HTTP is redirected or blocked And at rest, databases, object storage, and backups holding consent, linkage, or offer data are encrypted with AES-256 using a managed KMS And encryption keys are rotated at least every 12 months and upon compromise; access is limited via least privilege And application secrets are stored in a secure vault; backups are encrypted and tested for restore quarterly And automated quarterly checks validate cipher suites, certificate validity, and encryption status with alerts on failure
Exception Handling & Regeneration Flow
"As a front-desk coordinator, I want the system to regenerate options or hand off to me with full context when something changes so that I can keep families scheduled without starting from scratch."
Description

Detect and resolve failures or changes such as slot loss at confirmation, provider cancellations, or no response. Automatically regenerate fresh bundles within policy limits or route the case with full context to the front desk for manual follow-up. Coordinate with waitlists and recall campaigns to avoid double-booking and message fatigue. Apply throttling and retry rules, and provide clear guardian notifications when options change.

Acceptance Criteria
Auto-Regeneration on Slot Loss at Confirmation
Given a parent selects a sibling bundle and taps Confirm When the calendar API returns a conflict for any slot Then the system regenerates up to 2 fresh bundles within 15 minutes using the original constraints and excluding the conflicted times And the regenerated bundles contain 2–3 options that meet policy constraints or fewer if fewer exist And prior offer links are invalidated immediately and display "Offer expired" with a request-new-options action And a single consolidated update is sent to the guardian within 60 seconds containing reason code "SlotLost" and a link to the new offers And if no viable bundles can be generated, the case is routed to the front desk with full context and no guardian message promises unavailable times
Provider Cancellation After Offer Sent
Given an open offer references a provider who cancels affected availability When the cancellation is ingested Then all impacted offers are marked invalid within 30 seconds and their links return "Offer changed" And the system attempts regeneration once within 10 minutes constrained to the original date range and family preferences And the guardian receives a notification within 60 seconds explaining the change with reason code "ProviderCanceled" and a link to the new options or an acknowledgement that the team will follow up And if regeneration yields no options, the case is routed to the front desk immediately with priority if any appointment time was within 48 hours
No-Response Throttling and Escalation
Given a guardian has an outstanding offer When no response is received Then a maximum of 2 reminders are sent at 6 hours and 20 hours after the initial offer And no more than 3 scheduling messages (offer + reminders) are sent to the guardian within any rolling 24-hour window, with at least 4 hours between messages And after the final reminder, the case is paused for 72 hours to prevent fatigue and is routed to the front desk if the target appointment date is within 7 days And all scheduled reminders are automatically canceled if the guardian responds or a provider change invalidates the offer
Waitlist and Recall Coordination to Prevent Double-Booking
Given siblings are on a waitlist or active recall campaign When generating or regenerating bundles Then times currently held by waitlist offers or recall booking in progress for the same family are excluded from consideration And only one active scheduling thread exists per family; new outreach closes or supersedes older threads and migrates context And confirmation writes are guarded by a cross-campaign idempotency key to prevent duplicate bookings across waitlist/recall and Sibling Stacker And communication cadence enforces a combined limit of 3 outbound scheduling messages per guardian per 24 hours across all campaigns
Atomic Booking and Calendar Writeback Failure Handling
Given a guardian confirms a multi-appointment bundle When writing appointments to the calendar Then all appointments are persisted atomically; if any write fails, no appointments remain booked and any holds are released within 60 seconds And transient write failures are retried up to 3 times with exponential backoff of 2s, 10s, and 30s before escalation And duplicate confirm submissions within 10 minutes are ignored using an idempotency key, ensuring no double-bookings And on final failure, the guardian is notified within 60 seconds with a non-PHI message indicating "We couldn't confirm all slots; our team will follow up," and the case is routed to the front desk with error details
Full-Context Routing to Front Desk for Manual Follow-Up
Given auto-regeneration is exhausted or errors persist When routing to the front desk Then a case is created within 2 minutes containing patient names, guardian contact, attempted times, failure reasons, provider/room constraints, attempt counts, and links to regenerate And the case SLA is set based on urgency (within 48 hours = High) and appears in the front desk queue with a unique case ID And the guardian receives a message within 60 seconds confirming a human will assist; no additional automated offers are sent until the case is closed And all actions on the case are audit-logged with timestamps and user/automation IDs
Clear Guardian Notifications When Options Change
Given any change invalidates a previously sent offer When a new offer is generated Then the guardian message clearly states the reason code ("SlotLost", "ProviderCanceled", or "SystemError") and highlights what changed And messages contain only the minimum necessary information (no diagnosis or PHI) and honor the guardian's channel preference; fallback to SMS if the primary channel fails after 1 attempt And localized templates are used per guardian language setting; if unavailable, default to English And links in old messages are expired immediately; accessing them shows a friendly "Offer expired" screen with a button to view new options

Smart Split

Lets caregivers confirm the parts of a family bundle that work and seamlessly reschedule only the conflicting child. Suggests smart alternatives that keep as many siblings together as possible, preserving confirmed slots and reducing back-and-forth. Families get flexibility; staff keep the schedule stable.

Requirements

Caregiver Partial Confirmation Flow
"As a caregiver, I want to confirm which of my children’s appointments we can keep and flag a conflict for only the ones that don’t work so that I don’t have to reschedule the entire family."
Description

Provide a secure, mobile-first experience that lets caregivers confirm or decline individual appointments within a family bundle without affecting confirmed siblings. Via a HIPAA-compliant, tokenized link, caregivers can review each child’s appointment details, mark which ones work, flag conflicts for specific children, and optionally provide constraints (preferred days/times, provider, proximity) for rescheduling. Supports multiple caregivers with role-based access, deduplicates duplicate responses, and enforces link expiration and quiet hours. Presents a confirmation summary prior to submission and writes results into SmileCue’s conversation timeline for staff visibility. Localized content, accessibility compliance, and minimal PHI exposure are required to align with SmileCue’s messaging and security standards.

Acceptance Criteria
Secure Tokenized Link Access and Expiration
Given a caregiver receives a tokenized URL for a family bundle, When the URL is inspected, Then it contains no PHI or directly identifying patient data. Given the token is within the configured validity window, When the caregiver opens the link, Then the partial confirmation flow loads and the session is initialized for that family bundle. Given the token is expired or invalid, When the caregiver opens the link, Then no PHI is displayed, an expired/invalid message is shown, and the server returns 401/410 with the event logged.
Partial Confirmation Without Affecting Confirmed Siblings
Given a family bundle with multiple child appointments, When the caregiver marks some children as Confirm and others as Needs reschedule, Then only the selected children are updated and all other siblings’ appointments remain unchanged. Given a sibling appointment is already confirmed, When the caregiver changes another child’s status, Then the confirmed sibling’s slot is preserved and is neither canceled nor moved. Given a mobile device viewport (320–768 px), When the caregiver performs per-child actions, Then controls are fully usable by touch and content is readable without horizontal scrolling.
Capture Rescheduling Constraints per Child
Given a child is marked as Needs reschedule, When the caregiver opts to provide constraints, Then inputs for preferred days/times, provider, and proximity are presented and captured per child. Given constraints are entered, When the caregiver submits, Then constraints are validated (required format/ranges), optional fields may be left blank, and invalid inputs trigger inline errors preventing submission. Given a valid submission, When the backend processes the request, Then constraints are persisted and associated with the specific child’s appointment request for staff review.
Multi-Caregiver Role-Based Access and Deduplication
Given multiple caregivers with assigned roles and child-level permissions, When a caregiver accesses the flow, Then they can only view and respond for children they are authorized to manage; unauthorized children are hidden or read-only. Given the same caregiver submits identical responses multiple times (e.g., double-tap or refresh), When the system processes the submissions, Then only one final record per child is stored and duplicates are ignored (idempotent processing). Given two caregivers submit responses for the same child, When their roles and permissions are evaluated, Then the system applies configured role-based precedence to determine the accepted final state and logs both events for audit.
Quiet Hours Enforcement
Given practice quiet hours are configured, When a caregiver completes the flow during quiet hours (practice local time), Then no outbound SMS/email/voice messages are sent to the caregiver and any such notifications are queued until quiet hours end. Given staff notifications are enabled, When a submission occurs during quiet hours, Then updates are recorded in-app (e.g., timeline) without triggering external channels that violate quiet hours. Given automated reminders could be triggered by this action, When scheduling messages, Then the send times respect the configured quiet hours window.
Pre-Submission Confirmation Summary
Given the caregiver has set statuses for one or more children, When proceeding to Review, Then a summary lists each child with permitted identifiers, the selected action (Confirm or Needs reschedule), and any entered constraints, with Edit controls per child. Given the summary is displayed, When the caregiver’s locale and device accessibility settings are applied, Then all text is localized and the screen meets WCAG 2.1 AA semantics for labels, focus order, and keyboard/touch operation. Given the caregiver taps Confirm, When submission succeeds, Then a success state is shown and the summary becomes read-only; on failure, error messaging explains what to fix without exposing additional PHI.
Timeline Writeback and Audit Trail
Given a successful submission, When processing completes, Then SmileCue’s conversation timeline is updated with structured entries per child including final status (Confirmed/Needs reschedule) and any constraints summary, with timestamps and caregiver role, excluding unnecessary PHI. Given the same submission is received more than once, When writing to the timeline, Then idempotency prevents duplicate entries and instead updates or ignores duplicates as configured. Given staff view the conversation, When they open the timeline, Then the new entries are visible and filterable/searchable by child and status for operational clarity.
Conflict-aware Reschedule Suggestions
"As a caregiver, I want the system to suggest new times for the conflicting child that keep siblings together when possible so that our visits stay convenient and coordinated."
Description

Implement a scheduling engine that generates ranked reschedule options for only the conflicting child while maximizing sibling togetherness and schedule stability. The engine evaluates constraints such as same-day availability, back-to-back slots, provider preferences, room/chair capacity, insurance and age restrictions, procedure duration, buffer times, and clinic hours. It scores and returns the top options (e.g., 3 best matches) in real time, minimizing disruptions to confirmed siblings. Supports temporary slot holds, avoids lunch/blocked times, respects caregiver time-of-day preferences, and integrates with SmileCue’s adaptive branching to present options in-channel (SMS/email/voice via secure link).

Acceptance Criteria
Real-time Top-3 Conflict-Aware Suggestions
Given a family bundle with one child in conflict and others confirmed When Smart Split is invoked for the conflicting child Then the engine returns up to 3 ranked reschedule options within 1500 ms And each option targets only the conflicting child while preserving all other family appointments unchanged And the response includes for each option: start time, end time, date, provider, room/chair, score, and reason codes
Preserve Sibling Appointments and Schedule Stability
Given confirmed sibling appointments in the bundle When reschedule suggestions are generated Then no option modifies, cancels, or reorders any confirmed sibling appointment And no option requires moving non-family patient appointments And no option introduces double-booking or overbooking of resources
Constraint Compliance: Provider, Capacity, Insurance, Age, Duration, Buffers, Hours, Blocks
Given patient, procedure, and clinic configuration data are available When suggestions are generated Then every suggested slot satisfies: provider qualified for procedure and matches provider preference if set; insurance eligibility for patient/procedure verified; age restrictions met at appointment time; procedure duration plus required buffers fits within the slot; clinic hours observed; lunch/blocked times avoided; and required room/chair capacity available for the full duration And if at least one compliant same-day slot exists, at least one suggestion is same-day And if caregiver marked back-to-back as required, all suggestions place the conflicting child within 0–10 minutes of a confirmed sibling on the same day
Caregiver Time-of-Day Preferences and Fallback Labeling
Given a stored caregiver time-of-day preference window When suggestions are generated Then at least one suggestion aligns with the preferred window when compliant slots exist And if no compliant slots match the preferred window, suggestions are the nearest alternatives by time proximity and are labeled as Outside Preferred Time And each option includes a preferenceAlignment flag (true/false)
Temporary Slot Holds with Concurrency Safety
Given suggestions are returned to the caregiver When options are generated Then each suggested slot is placed on a soft hold for 5 minutes And a held slot cannot be booked by others; conflicting attempts return a slot_on_hold error And holds are released immediately upon decline, confirmation of a different option, or hold expiration And all hold create/release events are audit-logged with user/session ID, timestamps, and option identifiers And hold operations are idempotent and handle duplicate requests without creating duplicate holds
In-Channel Presentation via Adaptive Branching
Given an outreach is sent via SMS/email/voice with a secure link When the caregiver opens the link Then the top suggestions render within 1 second after page load and display time, provider, proximity to sibling appointments, and any preference/constraint labels And upon selecting an option, the appointment is confirmed, the held slot is committed, and confirmations are sent to caregiver and clinic within 2 seconds And declining all options triggers a follow-up branch offering to request a call or view more dates And the secure link is one-time use and expires after 24 hours or upon successful confirmation
Scoring, Ranking, and Explainability
Given the scoring engine is configured When suggestions are generated Then options are sorted in descending score, with ties broken by earliest start time then shortest delta to sibling appointment start And each option includes its score and at least three reason codes (e.g., same-day, back-to-back, provider match) And for identical inputs within a session, scores are deterministic And an A/B test flag can switch between scoring models without changing the constraints filter
Confirmed Slot Preservation & Atomic Reschedule
"As an office manager, I want confirmed sibling appointments to remain locked while rescheduling the conflicting child so that the schedule stays stable and errors are prevented."
Description

Ensure that confirmed sibling appointments remain locked while rescheduling the conflicting child through transactional safeguards. Use temporary holds and optimistic locking to prevent double-booking, and apply changes atomically—either all updates succeed or none do—with automatic rollback on failure. Handle concurrency with staff edits and other caregiver actions, include timeout policies for stale holds, and present clear conflict resolution paths. Emit structured events for auditability and notifications to staff if manual intervention is required. This preserves schedule stability and reduces cascade changes that create back-and-forth.

Acceptance Criteria
Atomic reschedule keeps sibling confirmations intact
Given a family bundle with two confirmed siblings (A, B) and one conflicting child (C) When the caregiver reschedules only C via Smart Split Then A and B remain confirmed and unchanged (same provider, date/time, operatory) And C is booked into the selected alternative slot And the operation commits atomically so that either all changes are persisted or none are And booking version numbers increment only upon successful commit And the caregiver sees a single success confirmation for the whole operation
Optimistic locking blocks override on concurrent staff edit
Given staff has the calendar open and the caregiver begins a reschedule for C When staff attempts to modify A or B during the caregiver’s in-flight transaction Then the update is rejected due to version mismatch using optimistic locking And the API responds with HTTP 409 Conflict and the latest resource version And the UI prompts staff to refresh before retrying And no partial changes are applied to any appointments
Temporary hold prevents double-book during caregiver review
Given the caregiver selects a candidate slot for C When the slot is selected Then the system places a temporary hold on that slot for 5 minutes scoped to the family bundle and session And the held slot is excluded from other availability searches and booking attempts And the hold is released immediately on confirmation, cancellation, timeout, or session end And attempts to place overlapping holds on the same slot are rejected And hold creation and release are logged with correlationId
Automatic rollback on downstream failure
Given external calendar/EHR write fails or times out during commit When the reschedule transaction detects the failure Then all tentative changes are rolled back and prior appointments (A, B, C) are fully restored And all temporary holds are released And the caregiver sees an error message with a non-destructive retry option And no orphaned or partial appointments remain in the system And the failure is recorded in the audit log with correlationId and error code
Stale hold timeout and caregiver messaging
Given a temporary hold exists for C When the 5-minute TTL elapses without confirmation Then the hold auto-expires and the slot reappears in availability within 2 seconds And any attempt to confirm after expiry is blocked with a clear message to retry selection And the UI refreshes availability to show current options And the expiration is logged with correlationId
Clear conflict resolution on real-time contention
Given a competing booking is confirmed by staff for the caregiver’s held or intended slot When the caregiver attempts to confirm C Then the system presents a conflict resolution screen with alternatives: next-closest time same day, same provider next day, different provider same time And previously confirmed siblings (A, B) remain unchanged And selecting an alternative creates a new hold and proceeds to atomic commit And aborting the flow releases any holds and restores the prior state
Structured audit events and staff notifications for intervention
Given any reschedule attempt for C via Smart Split When the flow starts, holds change, commit succeeds or fails, or manual intervention is required Then the system emits events: RescheduleStarted, HoldPlaced, HoldReleased, RescheduleCommitted, RescheduleRolledBack, ManualInterventionRequired And each event includes: correlationId, familyBundleId, appointmentIds, actorType, timestamp, previousStateHash/newStateHash And no PHI (e.g., names, DOB, contact info) is present in event payloads And ManualInterventionRequired triggers a staff inbox notification within 10 seconds with a deep link to resolve And events are idempotent and delivered at-least-once
Adaptive Smart Split Messaging (SMS/Email/Voice)
"As a caregiver, I want clear, secure messages that guide me through confirming and rescheduling parts of a family bundle across SMS, email, or voice so that I can complete it quickly on any device."
Description

Create branching communication templates that detect family bundles and invite caregivers to confirm or split appointments through a secure, tokenized link. Support SMS, email, and voice (IVR) paths with consistent content, minimal PHI in-channel, and full consent/DND management. Include reminder nudges, escalation timing, delivery monitoring, retry logic, throughput throttling, localization, and accessibility. Leverage SmileCue’s existing adaptive workflows to tailor tone and cadence based on caregiver responses and past behavior, while logging all steps for HIPAA-compliant audit trails.

Acceptance Criteria
Family Bundle Detection and Secure Smart Split Link
Given a caregiver has 2 or more appointments on the same calendar day at the same practice with a shared caregiver contact ID, When a reminder workflow triggers, Then the system groups the appointments into a single family bundle and generates one secure tokenized link for that bundle. Given a bundle link is generated, Then the token has ≥128 bits of entropy, is bound to the bundle ID and caregiver ID, is single-use per final action submission, and expires at the earliest appointment start time or 7 days after issuance, whichever comes first. Given an outbound SMS or email for a family bundle, Then the message includes the practice name, appointment date(s) and count, and the secure link, and excludes full child names, DOB, procedure names, provider names, and insurance information. Given the caregiver opens the secure link, Then the landing page lists each child’s name, date/time, and provider and offers Confirm All, Confirm Selected, and Reschedule Selected actions. Given the caregiver confirms selected appointments, Then confirmed appointments remain unchanged and only the selected appointments enter rescheduling, preserving confirmed slots.
Cross-Channel Content Parity and IVR Flow
Given templates exist for SMS and email, Then equivalent IVR prompts exist with content-parity for options and key information. Given a caregiver receives a voice call, When they press 1 to Confirm All, 2 to Confirm Selected, or 3 to Request Reschedule, Then the system records the selection and performs the same actions as the secure link workflow, and sends a follow-up secure link via an allowed channel when a split is required. Given the caregiver provides no DTMF input within 5 seconds, Then replay the menu up to 2 times; on no response, end the call and, if voicemail is reached, leave a generic callback message with the practice number and no PHI. Given the same reminder event is sent across channels, Then placeholders, appointment counts, and date information are consistent between SMS, email, and IVR outputs.
Consent and Do-Not-Disturb (DND) Enforcement
Given the caregiver has not provided explicit SMS consent, Then the system does not send SMS and selects an allowed channel instead. Given the caregiver has unsubscribed from email or is on voice DNC, Then the system does not send via those channels and records the reason. Given the caregiver replies STOP to an SMS, Then the system immediately sets SMS DND = true for that number, sends a confirmation message, and logs the consent state change with timestamp and source. Given consent is captured or updated (e.g., SMS double opt-in), Then the system stores consent status, timestamp, collection method, and terms version and uses the updated state for all subsequent sends. Given a user attempts to override DND to send a message, Then the system blocks the send and displays a compliance error; no bypass is permitted.
Delivery Monitoring, Retry Logic, and Throughput Throttling
Given an outbound message is queued, Then the system records message GUID, channel, template ID/version, practice ID, intended send time, and deliver-by time. Given a transient delivery failure occurs, Then retry up to 3 times with exponential backoff at 5, 15, and 45 minutes; on final failure, mark Failed and escalate once to an alternate allowed channel if available. Given normal operations, Then enforce per-practice throttles of SMS ≤ 20 messages/second, Email ≤ 200 messages/minute, and Voice ≤ 10 concurrent calls; if limits are reached, queue messages and deliver within the deliver-by window. Given the provider returns delivery receipts, Then update message status to Delivered within 60 seconds of receipt; otherwise display Sent with last update time. Given the rolling 5-minute failure rate for a practice/channel exceeds 5%, Then reduce the throttle by 50% automatically and send an operational alert.
Adaptive Cadence, Tone, and Escalation with Quiet Hours
Given a caregiver confirmed via SMS within 2 hours in at least 3 of the last 5 family bundles, Then select SMS as the primary channel for the next bundle and limit nudges to one additional reminder if no engagement. Given the caregiver did not engage via SMS in the last 3 bundles but opened email in at least 2 of them, Then select Email as the primary channel and send a backup SMS only at T-24h if consented and still no engagement. Given a new reminder sequence for a bundle, Then schedule sends at T-72h (initial), T-48h (nudge if no engagement), and T-24h (escalation to alternate allowed channel if still no engagement), and suppress all further sends upon any engagement (reply, link open, or IVR input). Given quiet hours are 8:00pm–8:00am in the caregiver’s time zone, Then no sends occur during quiet hours unless the earliest appointment in the bundle is within 12 hours, in which case schedule the next send for 8:00am local time. Given tone variants exist (concise ≤ 160 characters; detailed ≤ 320 characters), Then assign the concise variant to caregivers who historically confirm within 2 hours; otherwise assign the detailed variant.
Localization and Accessibility Compliance
Given a caregiver’s language preference is Spanish (es-US), Then send SMS/email/IVR using es-US templates and localize date/time formats accordingly. Given a required translation is missing, Then fall back to en-US and log a missing-translation warning with template ID and locale. Given the landing page renders, Then it complies with WCAG 2.1 AA for color contrast (≥4.5:1), keyboard navigation, focus order, and screen reader labels on actionable elements. Given IVR is active, Then set TTS speed between 150–170 words per minute, offer “Press 9 to repeat,” confirm selections before finalizing, and support timeouts with reprompts. Given an SMS body exceeds 160 GSM-7 characters, Then segment with UDH for reassembly or shorten per carrier constraints; ensure links are valid and clickable on common devices.
HIPAA Audit Logging and Export
Given any message lifecycle event occurs (compose, queue, send, deliver, fail, retry), Then record an immutable audit entry with timestamp (UTC), actor/system ID, caregiver ID, channel, template ID/version, practice ID, bundle ID, token ID, consent snapshot, and PHI classification. Given a caregiver interaction occurs (link open, selection, IVR input), Then log the event with outcome, device type if known, user agent hash, and IP truncated to /24, without storing full IPs. Given an authorized admin requests an audit export by bundle ID or date range, Then generate a signed CSV within 60 seconds and make it available behind RBAC for 24 hours; all export access is logged. Given the audit retention policy is 6 years, Then audit entries are retained ≥6 years and are tamper-evident via hash chaining; any modification attempt is detectable. Given a user without AuditViewer role attempts to access audit data, Then access is denied and the attempt is logged.
Staff Smart Split Review Console
"As an office manager, I want a console to review, approve, or adjust Smart Split proposals with full context and audit history so that I can maintain control and resolve edge cases efficiently."
Description

Deliver an in-app console where staff can visualize family bundles, see caregiver selections, and review proposed reschedules with a side-by-side diff of original vs. proposed appointments. Provide one-click approve, adjust, or decline actions, manual rescheduling tools, reason codes, and note-taking. Include filters (by date, provider, location), conflict reason tagging, and workload views. Surface risk indicators (e.g., low availability, repeated reschedules) and maintain a complete audit trail of changes. Integrate seamlessly with the existing schedule view and conversation timeline to reduce context switching and speed resolution.

Acceptance Criteria
Bundle Visualization with Caregiver Selections
Given I open the Smart Split Review Console from a family conversation or schedule entry When the console loads Then I see the full family bundle with each member’s name, appointment type, provider, location, chair (if applicable), date/time, duration, and current status And the caregiver’s selections from Smart Split are displayed per member (Confirmed/Needs Change/No Preference) And members with conflicts are visually flagged with a conflict reason chip And the bundle header summarizes total members, confirmed, pending review, and proposed changes And loading completes within 2 seconds for bundles of up to 6 members and within 4 seconds for up to 12 members And time zones are displayed consistently with the practice’s time zone settings
Side-by-Side Diff of Original vs Proposed Appointments
Given a bundle has at least one proposed change When I select a member with a proposed reschedule Then I see a side-by-side view showing Original vs Proposed values for date, start time, duration, provider, location, chair, operatory, and appointment type And all changed fields are highlighted while unchanged fields are de-emphasized And preserved sibling slots are indicated with a “kept together” badge And a “Show differences only” toggle hides unchanged fields And hovering a highlighted field shows the reason for change (e.g., provider conflict) And leap-year/daylight-savings transitions show correct local times in both columns And the diff renders within 300 ms after selection
One-Click Approve, Adjust, or Decline with Reason & Notes
Given I am reviewing a proposed change When I click Approve Then the proposed appointments are committed atomically to the schedule, confirmations are sent via the caregiver’s selected channels (SMS/email/voice), and the bundle status updates to Confirmed where applicable And Approve completes within 3 seconds or clearly indicates progress with a spinner and completes within 10 seconds worst case And an audit entry is written with action=Approve and includes before/after values When I click Adjust Then the manual reschedule tools open pre-populated with the proposed context, and a Reason Code (from a configured list) and a free-text Note are required before saving When I click Decline Then I must select a Reason Code and may enter a Note, the caregiver is notified with a templated message, and no schedule changes are applied And all actions enforce optimistic concurrency: if the source slots changed since load, I am prompted to refresh and retry And on any failure, no partial changes persist and a clear error is shown with a retry option
Manual Rescheduling Tools with Smart Alternatives
Given I choose to Adjust a member’s appointment When the manual rescheduler opens Then I see a ranked list and calendar view of available slots prioritized to keep siblings together and match appointment duration and type And I can filter by date range, provider(s), location(s), chair, and days/times of week And selecting a candidate slot updates the proposal preview and the side-by-side diff in under 500 ms And scheduling rules are enforced (provider availability, room/operatory capacity, travel buffers, appointment-type duration, insurance blocks) And conflict reason tagging is required if I pick a slot that separates siblings And low-availability risk is indicated when fewer than 3 sibling-capable bundles exist in the next 14 days And saving commits the adjustment and triggers the same confirmation/audit flows as Approve
Filtering, Workload Views, and Conflict Tags
Given I am in the console list view of pending bundles When I apply filters for date range, provider(s), and location(s) Then the results update within 1 second on cached data and 3 seconds on first load, showing only matching bundles And I can filter by conflict reason tags (e.g., Provider Unavailable, School Hours, Transportation) and by risk indicators And a workload view shows counts of pending bundles by staff assignee and by provider, with aging buckets (<24h, 24–72h, >72h) And clearing filters restores the full list And my last-used filters persist for my user session and are restored on next visit
Risk Indicators and Complete Audit Trail
Given I am reviewing a bundle When risk conditions are met Then a Low Availability badge appears when fewer than 3 sibling-capable options exist in the next 14 days And a Repeated Reschedules badge appears when any member has 3 or more reschedules in the past 60 days And hovering a badge reveals the underlying metric used And every action (view, approve, adjust, decline, message sent) records an immutable audit entry with timestamp, user, action, before/after values, reason code, and note And audit entries are visible inline and exportable to CSV by users with the proper role And audit entries cannot be edited or deleted by any user
Seamless Integration with Schedule View and Conversation Timeline
Given I am in the review console When I open the schedule view from an appointment chip Then the schedule opens in a side panel or split view focused on the correct provider, location, and date/time without navigating away And returning to the console preserves my scroll position, filters, and any unsaved proposal changes (or prompts to Save/Discard if needed) When I open the conversation timeline Then the thread scrolls to the Smart Split interaction and displays related messages/confirmations And deep links reopen the console to the same bundle and selected member And all cross-view interactions complete in under 1 second on cached data and 3 seconds on first load
PMS Sync & Audit for Split Changes
"As a practice administrator, I want Smart Split changes to sync reliably to our practice management system with auditable records so that our source of truth remains accurate and compliant."
Description

Integrate Smart Split operations with leading practice management systems (e.g., Dentrix, Eaglesoft, OpenDental) to apply partial confirmations and reschedules as atomic, version-locked updates. Map family/guarantor relationships, procedures, providers, and insurance constraints accurately. Implement idempotent writes, retry/backoff for transient failures, and reconciliation jobs to detect drift. Store detailed before/after snapshots with timestamps, user/system actor attribution, and reason codes for HIPAA-compliant auditability. Provide alerting and rollbacks when third-party updates fail to ensure the external source of truth remains consistent.

Acceptance Criteria
Atomic Partial Confirm and Single-Child Reschedule Applied to PMS
Given a family bundle where the caregiver confirms Sibling A and reschedules Sibling B And a valid PMS version token vN exists for the bundle When Smart Split submits the update to the PMS Then the PMS applies Sibling A confirmed and Sibling B rescheduled as a single atomic operation or not at all And the PMS version advances from vN to vN+1 only on success And Sibling A’s appointment ID and time remain unchanged And Sibling B’s appointment reflects the selected time, provider, and operatory And if the operation fails, no partial change is visible in the PMS and the version remains vN And SmileCue refreshes from the PMS and matches the resulting state within 5 seconds
Idempotent Write with Version Lock
Given the same Smart Split update is retried using the same idempotency key and PMS version token vN When the PMS receives duplicate requests due to timeouts or client retries Then the change is applied at most once in the PMS And subsequent duplicate requests return a stable 200/OK or 409/Conflict without creating additional appointments or confirmations And SmileCue records a single business audit entry and links all retries to it Given the PMS version token is stale (vN-1) When the update is submitted with If-Match vN-1 Then the write is rejected with a version conflict and no changes are applied And SmileCue fetches the latest PMS state and prompts recomposition before reattempting
Accurate Mapping of Family, Provider, Procedure, and Insurance Constraints
Given a family with guarantor G and children C1 and C2, assigned providers P1/P2, procedures with CDT codes, and active insurance plans with frequency limits When Smart Split applies a partial confirm/reschedule Then appointments are linked to the correct PMS patient IDs for C1/C2 and guarantor relationships remain intact And provider IDs and operatory/resource IDs map 1:1 to PMS entities And procedure codes are translated to PMS-specific code sets without loss And insurance validation prevents scheduling that violates frequency/interval limits and returns reason code INS_FREQUENCY_CONFLICT And on validation failure, no changes are applied to the PMS
Transient Failure Handling with Exponential Backoff
Given the PMS API returns 5xx responses or network timeouts during an update When Smart Split submits the change Then the client retries with exponential backoff and jitter for up to 4 attempts within 60 seconds And each retry reuses the same idempotency key and intended PMS version token And if any retry succeeds, the operation is recorded as a single successful change And if all retries fail, the operation is marked failed and no side effects exist in the PMS
Reconciliation Job Detects and Resolves Drift
Given a scheduled reconciliation job runs every 15 minutes And SmileCue stores local Smart Split outcomes for affected appointments When the PMS state differs from SmileCue (status, time, provider, procedure, or version) Then the job detects and flags the drift within the same run And attempts repair using the latest PMS version token with idempotent writes And records an audit entry with reason code RECON_DRIFT_FIX for each repaired item And if repair fails, the job raises an alert and leaves the PMS unchanged
HIPAA-Compliant Audit Trail with Before/After Snapshots
Given any Smart Split update attempt (success, retry, failure, or reconciliation) When the attempt is processed Then an immutable audit record is written within 1 second containing: UTC timestamp, tenant, actor (user ID or system), idempotency key, PMS entity IDs, reason code, and before/after snapshots of all changed fields And audit records are tamper-evident via hash chaining And audit records are retained for at least 6 years And authorized users can retrieve an audit record by ID within 2 seconds
Alerting and Rollback Ensure PMS Consistency
Given a PMS update results in partial effects or a version conflict during Smart Split When inconsistency is detected during or after the update Then the system performs compensating actions to restore the PMS to the last consistent state or aborts before any commit And SmileCue reverts any local optimistic state to match the PMS And an alert is sent within 1 minute to designated staff channels containing family identifiers, affected appointments, correlation ID, and error category And the incident is visible in the UI with a retriable action
Smart Split Analytics & Reporting
"As a practice owner, I want reports that show how Smart Split affects confirmations, kept siblings together, and no-shows so that I can measure ROI and optimize operations."
Description

Produce dashboards and exportable reports that quantify Smart Split impact, including confirmation rate lift, no-show reduction, sibling-togetherness rate, average time-to-resolution, caregiver channel preference, and staff time saved. Support cohorting by practice, location, provider, and appointment type; enable A/B testing of suggestion strategies; and surface anomaly alerts (e.g., unusually low availability). Ensure data minimization and de-identification for HIPAA compliance, with configurable retention policies. Expose metrics via in-app charts and secure APIs to inform continuous optimization.

Acceptance Criteria
Dashboard Metrics Accuracy, Coverage, and Freshness
- Given 90 days of Smart Split activity exists, when a user opens the Analytics dashboard for a selected date range, then tiles and trend charts show: confirmation rate lift, no-show reduction, sibling-togetherness rate, average time-to-resolution, caregiver channel preference distribution, and staff time saved. - Given a reference dataset computed by the data team for the same cohort and window, when the dashboard loads, then each metric matches the reference within ±0.5% relative error (or ±30 seconds for time metrics). - Given data ingestion is ongoing, when viewing the dashboard, then the “Last updated” timestamp is visible and the data freshness is ≤ 15 minutes at p95. - Given the user switches granularity (daily/weekly/monthly), when charts render, then rollups are accurate and totals/averages reconcile within ±0.5% to the underlying table queries. - Given the user changes the date range, when charts reload, then metrics exclude appointments outside the range and p95 render time is ≤ 2 seconds for cached queries and ≤ 5 seconds for cold queries.
Cohort Filtering by Practice, Location, Provider, and Appointment Type
- Given the user has permissions to multiple entities, when they multi-select practice(s), location(s), provider(s), and appointment type(s), then all metrics recompute to reflect only the selected cohort. - Given cohort filters are applied, when the user refreshes or shares the URL, then the exact filters persist via URL state and user preference storage. - Given an empty-result cohort, when filters yield zero eligible appointments, then a zero-state appears with 0 values and no errors. - Given the user compares cohorts, when up to 3 cohorts are defined, then side-by-side views render deltas (absolute and %) for each key metric within p95 3 seconds. - Given RBAC is enforced, when a user lacks access to a practice/location/provider, then it is not selectable and its data is excluded from aggregates.
Exportable Reports and Scheduled Delivery
- Given a user selects a date range and cohort, when exporting CSV or JSON, then the file is generated within 120 seconds for up to 2,000,000 rows; larger exports stream with progress and complete without timeout. - Given an export is generated, when the file is opened, then it contains only de-identified fields and metrics with this minimum schema: date, practice_id, location_id, provider_id, appointment_type, confirmations, confirmation_rate_lift, no_shows, no_show_reduction, sibling_togetherness_rate, avg_time_to_resolution_seconds, channel_preference_breakdown, staff_time_saved_minutes. - Given practices have timezones, when dates/times are rendered, then values are in the practice timezone and the timezone is included in metadata. - Given scheduled exports are configured, when the cadence triggers (daily/weekly/monthly), then a delivery is sent to the chosen destination (SFTP, secure email link, or webhook) and an audit log records success/failure with retry on transient errors (up to 3 attempts). - Given export links are distributed, when accessed after 24 hours, then signed URLs are expired and access is denied (HTTP 403).
Metrics API Security and Contract
- Given an API client with OAuth2 client-credentials and scope analytics.read, when it calls /v1/analytics/smart-split endpoints with valid filters, then the API returns 200 with metrics conforming to the published OpenAPI schema, including cursor pagination and date granularity options. - Given API usage limits, when a client exceeds 100 requests per minute, then the API returns HTTP 429 with a Retry-After header and no PHI leakage in the body. - Given principle of data minimization, when metrics are returned, then entities are referenced only by opaque IDs and no names, phone numbers, emails, or free text fields are present. - Given observability requirements, when API calls are made, then access logs capture client_id, scope, filters, timestamp, and status code; logs are retained per the tenant’s retention policy. - Given API evolution, when a breaking change is needed, then a new version (e.g., v2) is introduced and v1 remains functional until deprecation window elapses (minimum 6 months).
A/B Testing of Suggestion Strategies
- Given multiple suggestion strategies are configured, when an eligible Smart Split interaction occurs, then traffic is randomized per configured allocation with persistent bucketing per caregiver for 30 days. - Given an interaction is bucketed, when outcomes occur, then exposure, assignment, and outcomes (confirmation, no-show, sibling-togetherness, time-to-resolution) are logged atomically with timestamps. - Given sufficient sample size, when the experiment dashboard loads, then per-variant metrics and uplift vs control are displayed with 95% confidence intervals and sample sizes. - Given an operator pauses or stops an experiment, when the change is saved, then routing updates within 5 minutes and is reflected in audit logs. - Given allocation health monitoring, when sample ratio mismatch exceeds 2% absolute for >1 hour, then an alert is raised to the experiment owner via in-app and email.
Anomaly Alerts for Availability and Metric Deviations
- Given baselines from the last 8 weeks, when availability or key metrics deviate beyond configured thresholds (e.g., >3σ or >20% week-over-week), then an alert is generated within 10 minutes of detection. - Given alert channels are configured, when an alert fires, then notifications are delivered via in-app banner, email, and optional webhook with deduplication suppressing repeats for 60 minutes. - Given an alert is viewed, when a user acknowledges or resolves it, then state transitions and user identity are captured in an audit log. - Given historical labeled incidents, when the detector is backtested, then false positive rate is <2% and recall is >80% on the validation set. - Given the metric normalizes for 24 hours, when evaluation runs, then the alert auto-resolves and no further notifications are sent.
HIPAA Compliance: Data Minimization, De-identification, and Retention
- Given analytics views, exports, and APIs, when data is presented, then no PHI is included (no names, phone numbers, email addresses, or free text); only aggregates, timestamps, and opaque IDs appear. - Given caregiver channel preference, when reported, then it is shown only as aggregate distributions without exposing individual-level preferences. - Given tenant-configured retention (30–730 days), when data exceeds its retention period, then raw analytics events are hard-deleted within 24 hours and backups within 30 days, with deletion jobs auditable. - Given role-based access control, when an unauthorized user attempts to access analytics or exports, then access is denied and the attempt is logged. - Given compliance automation, when pre-release checks run quarterly and pre-deploy, then any detection of PHI fields in analytics datasets fails the pipeline and notifies the compliance channel.

Caregiver Cascade

Routes each family message to the right caregiver by child, then escalates to a secondary contact if there’s no response—respecting language, channel, and time-of-day preferences. Builds on permissions to ensure the correct guardian is engaged while boosting confirmation rates with thoughtful fallbacks and a clear audit trail.

Requirements

Per-Child Caregiver Association & Permission Enforcement
"As an office manager, I want caregiver routing to respect per-child permissions so that only authorized guardians receive communications."
Description

Create and maintain a robust data model that maps each child to one or more caregivers with explicit roles (e.g., primary guardian, secondary guardian, legal guardian, emergency contact) and permission constraints (e.g., custody restrictions, no-contact flags). Ingest and continuously sync caregiver relationships and constraints from the practice PMS/EHR, with conflict detection and admin override workflows. At send time, evaluate permissions to determine the eligible caregiver(s) for each message, blocking delivery to unauthorized contacts. Support households with multiple children, ensuring the correct guardian is selected per child and appointment. Provide an admin UI to review and correct mappings, and emit structured events for downstream logging and analytics. Enforce HIPAA minimum-necessary principles and role-based access control for viewing and editing caregiver data.

Acceptance Criteria
Send-Time Permission Evaluation Blocks Unauthorized Contacts
Given a child with caregivers A (Primary), B (Secondary), C (No-Contact), and D (Custody-Restricted until a set date) And an appointment reminder message M for that child When the system evaluates eligible recipients at send time Then only caregivers with active permission for the child and message type are included (A and/or B) And caregivers with no-contact or active custody restriction are excluded (C, D) And a decision record includes a reason code per caregiver (e.g., ALLOWED_PRIMARY, BLOCKED_NO_CONTACT, BLOCKED_CUSTODY) And the evaluation completes within 300 ms per child And a DecisionEvaluated event is emitted with child_id, appointment_id, considered_caregiver_ids, allowed_ids, blocked_ids, reason_codes, request_id, and timestamp
Primary Guardian Selection Per Child in Multi-Child Household
Given a household with children X and Y, each with different primary guardians And a message targeted to child X’s appointment When recipient selection runs Then the primary guardian for child X is selected and Y’s guardian is not And if X has no eligible primary guardian, an eligible secondary guardian is selected instead And selected recipients honor their language, channel, and time-of-day preferences And no recipient from another child’s mapping is included
Custody Restriction and No-Contact Enforcement
Given caregiver C1 has a no-contact flag for child Z And caregiver C2 has a custody restriction active between start_time and end_time When any outbound message for child Z is prepared during that interval Then C1 and C2 are excluded from all delivery channels And exclusion reason codes are recorded per caregiver And message preparation logs and previews redact PHI to the minimum necessary for blocked recipients
PMS/EHR Sync Ingestion and Conflict Detection
Given the PMS/EHR updates caregiver roles or permissions for a child When the scheduled sync runs Then new caregivers are created, existing ones updated, and removed ones deactivated with effective timestamps And conflicting data (e.g., two primary guardians, role mismatch, contradictory permission flags) is detected and recorded as a conflict with source identifiers and field deltas And production mappings are not auto-changed when a conflict exists until an admin resolves it And the sync completes processing the change within 5 minutes of detection And a SyncResult event is emitted with counts for created, updated, deactivated, conflicts, and errors
Admin UI Review and Override Workflow
Given a caregiver-mapping conflict exists for a child And a user with role Office Manager or higher opens the Admin UI When the user chooses Resolve and applies an override Then the system requires a reason and saves an immutable audit log with before/after values, user_id, timestamp, and source And the effective mapping updates immediately with a new version number And a MappingOverridden event is emitted with child_id, affected_caregiver_ids, fields_changed, reason_code, and user_id And users without sufficient RBAC permissions cannot access the override screen (403)
Structured Event Emission and Audit Trail Completeness
Given any send-time decision, sync result, override, or permission change occurs When the event pipeline processes the record Then a structured event is published within 60 seconds to the analytics bus And events include: event_type, child_id, caregiver_id(s), appointment_id (if applicable), role, permission_flags, decision, reason_code, user_id (if applicable), request_id, occurred_at, emitted_at, schema_version And PHI is redacted to the minimum necessary (IDs and role labels only; no names or full contact details) And 99.9% of events over a rolling 24 hours are successfully delivered (DLQ < 0.1%)
RBAC and Minimum Necessary Access Controls
Given a user attempts to view or edit caregiver mappings When the user lacks the required role permissions Then access is denied with HTTP 403 and the attempt is logged with user_id, child_id, timestamp, and purpose_of_use And users with read-only roles see redacted caregiver info (IDs, role, permissions) without contact details And users with edit roles can view full details and make changes; all read/write access is logged And API and export endpoints enforce field-level filtering to the minimum necessary by role
Preference-Aware Channel & Language Selection
"As a caregiver, I want to receive messages in my preferred language and channel so that I can quickly understand and respond."
Description

Store and honor per-caregiver preferences for communication channel (SMS, email, voice) and language, with practice-level defaults and per-message overrides. Auto-select localized templates and dynamic content based on the caregiver’s language, including right-to-left support and TTS voice selection for calls. Provide mechanisms to capture and update preferences via caregiver responses, practice staff UI, and API. Validate channel feasibility (e.g., mobile-capable number for SMS) and gracefully fall back to the next preferred channel or default when needed. Integrate with the template service to ensure message personalization, token safety, and consistent branding across channels and locales, improving comprehension and response rates.

Acceptance Criteria
Resolve Channel and Language with Overrides
Given practice defaults channel=email and language=en-US And caregiver preferences channel priority=[SMS, email, voice] and language=es-MX And a per-message override sets language=fr-FR and does not set channel When the system prepares a message for the caregiver Then the selected language is fr-FR if a fr-FR template exists; otherwise es-MX if available; otherwise en-US And the selected channel is the first in the caregiver’s priority list (SMS, then email, then voice) And the final selection stores resolution_source per attribute (override|caregiver|practice)
Validate Channel Feasibility and Fallback
Given caregiver channel priority=[SMS, email, voice] And the caregiver phone is a landline, the email is deliverable, and voice is permitted When the system attempts to send via SMS first Then SMS is deemed infeasible due to non-mobile and is not sent And the system attempts email and sends successfully if not suppressed/bounced And if email is undeliverable, the system attempts voice And if no channels are feasible, the message is not sent and is flagged with reason=no_feasible_channel and shown to staff And at most one send attempt is made per channel for this message
Localized Templates, RTL, and TTS Voice Selection
Given the caregiver language is ar (Arabic) And localized templates exist for ar and en-US When the system renders SMS, email, and voice variants Then ar templates are selected for all channels And SMS/email content renders right-to-left with correct punctuation mirroring And voice calls use an Arabic TTS voice configured for ar And all personalization tokens resolve; if any token is missing/unsafe, sending is blocked and an error is logged And dates, numbers, and pluralization follow ar locale rules And branding (logo, headers, footers) matches practice branding across channels and locales
Update Preferences via Caregiver Response
Given a caregiver replies to an outgoing message with a command (e.g., "LANG ES" or "CHANNEL EMAIL") or clicks a secure preference link When the system parses and validates the request Then the corresponding preference is updated on the caregiver profile And a confirmation message is sent in the newly selected language/channel where applicable And the change is persisted with actor=caregiver, source=message_response, and timestamp And the updated preference is applied to the next message generated for that caregiver And invalid/unsupported values trigger a help response without changing preferences
Manage Preferences via Staff UI and API
Given a staff user with caregiver.update_prefs permission edits a caregiver When they set channel priority=[voice, SMS] and language=fr-CA and save Then inputs are validated (supported language code, ordered unique channels, prerequisite contact info) And the update is saved and visible on refresh And an audit entry is recorded with actor=staff, source=UI, old→new diff, and timestamp And a preferences.updated event is emitted to the message bus When an API client calls PUT /v1/caregivers/{id}/preferences with the same values Then the API returns 200 with the stored preferences And invalid payloads return 400 with field-level errors; unauthorized/forbidden return 401/403
Template Integration, Personalization Safety, and Consistent Branding
Given a message uses the template service for SMS, email, and voice When the system composes the message Then the correct localized template_id is referenced for the resolved language And all required tokens are present and type-safe; missing tokens fail the composition with a descriptive error before send And dynamic content (names, dates, appointment details) is correctly injected and escaped And all channels include the practice’s approved branding elements and footer text for the locale And a preview/render endpoint returns 200 with fully resolved content per channel before send
Delivery Audit Trail for Selection and Fallback
Given a message is prepared and delivered (or not) under this requirement When delivery processing completes Then an immutable audit record is stored with caregiver_id, patient_id, selected_channel, selected_language, resolution_sources, feasibility_check_results, fallback_reason (if any), template_id, tts_voice_id, and timestamps And the record is retrievable via Audit UI and GET /v1/audit/messages?message_id={id} And records are append-only and retained for ≥6 years And logs avoid PHI in plain text and enforce HIPAA access controls
Quiet Hours & Smart Send Windows
"As a practice admin, I want reminders sent only within acceptable hours for each caregiver so that we respect preferences and improve response rates."
Description

Respect caregiver-defined quiet hours and preferred contact windows in conjunction with practice-level contact policies. Automatically schedule sends within allowed windows relative to appointment time, accounting for caregiver time zone, daylight saving changes, and regional regulations. Provide urgent override rules (with justification capture) and throttling to avoid message bursts. Offer configuration for school hours avoidance where applicable. Expose eligibility checks and next-send predictions to the UI and API so staff can see when messages will go out. This reduces complaints, improves engagement, and keeps contact timing compliant with TCPA/CTIA and practice policies.

Acceptance Criteria
Schedule within caregiver quiet hours and practice policy intersection
Given caregiver quiet hours are 21:00–08:00 and preferred window is 10:00–12:00 in America/New_York And practice policy allows 09:00–19:00 local And an appointment is on 2025-10-14T11:00:00-04:00 with a T-24h reminder When the system calculates the send time Then the send is scheduled on 2025-10-13 between 10:00 and 12:00 local, never outside 09:00–19:00 or within 21:00–08:00 And the scheduled timestamp and the windows considered are recorded for audit
Localize scheduling with time zone and DST shifts
Given caregiver timezone is America/Los_Angeles And an appointment is on 2025-11-03T09:00:00-08:00 (post DST fallback) And a T-24h reminder is configured When the system schedules the reminder across the DST change on 2025-11-02 Then exactly one send is scheduled at 2025-11-02T09:00:00-08:00 local And no duplicate or missed sends occur due to the 25-hour day And all applicable quiet hours and practice windows are still enforced
Enforce TCPA/CTIA quiet hours by region and channel
Given recipient region is US and channel is SMS or Voice And caregiver preferred window would allow sends before 08:00 or after 21:00 local When the system validates the next send Then no SMS or Voice message is sent outside 08:00–21:00 local time And if preferences conflict, the stricter of regulatory, practice, and caregiver windows is applied And the reason "Regulatory quiet hours" is recorded when a time is disallowed
Urgent override requires justification and audit
Given a message is currently ineligible due to quiet hours or policy windows And a staff user with "Override Quiet Hours" permission initiates an urgent send When the user provides a justification category and a free-text reason of at least 10 characters Then the message is sent immediately regardless of quiet hours And the audit log captures user ID, role, timestamp, prior blocking rules, justification category, and reason text And UI/API surfaces an override flag and audit reference on the message record And if permission is missing or justification is incomplete, the override is rejected with 403/422
Throttle to avoid message bursts across channels
Given multiple messages for the same caregiver household are eligible within a short period When scheduling across SMS, Email, and Voice Then enforce throttles: max 1 SMS per caregiver per 60 seconds, max 2 SMS per 10 minutes, and max 3 total messages across all channels per 10 minutes (non-urgent) And defer excess messages to the next allowed slot within policy windows while preserving priority (confirmation > reminder > marketing) And record deferrals with next_send_at and reason "Throttled"
Avoid school hours when configured
Given "Avoid school hours" is enabled with Mon–Fri 08:00–15:00 in the child's local timezone And the message category is non-urgent And a T-24h reminder would fall within 08:00–15:00 on a school day When the system calculates the next send Then the send is moved to the nearest allowed time outside 08:00–15:00 that still precedes the appointment and respects other windows And if no pre-appointment slot exists, schedule the previous weekday after 15:00 local and record reason "School hours avoidance"
Expose eligibility and next-send prediction via UI and API
Given a staff user views an appointment's outreach plan in the UI or calls GET /v1/messages/eligibility with identifiers When quiet hours, practice policies, and preferences are evaluated Then the response includes: eligibility (true/false), next_send_at (ISO 8601 with timezone offset), channel, recipient timezone, blocking_rules[], and calculation timestamp And the UI displays the same next_send_at and blocking reasons with a "Why" panel And predictions recalculate and refresh within 5 seconds after a relevant configuration change
Response-Driven Cascade with Escalation SLAs
"As a hygienist, I want messages to escalate to a secondary caregiver after a defined wait if the primary doesn’t respond so that appointments get confirmed without manual calls."
Description

Implement a policy-driven cascade that sends the initial message to the primary caregiver, waits a configurable interval for a response, and escalates to a secondary caregiver if no qualifying response is received. Allow per-practice and per-campaign configuration of wait times, maximum steps, and stop conditions. Parse responses (keywords, links, buttons) to determine state transitions (confirmed, reschedule, decline) and terminate the cascade once a resolution is reached. Coordinate across siblings to prevent redundant outreach when a single response covers multiple children or appointments. Surface real-time cascade status in the UI and record each decision for auditability. This reduces manual follow-up and increases confirmation rates.

Acceptance Criteria
Primary-to-Secondary Escalation After Configured Wait SLA
Given an appointment with a designated primary and secondary caregiver and an active cascade, When the initial message is sent to the primary at time t0, Then the system starts a timer equal to the effective wait interval and displays a "Waiting for response" state. Given no qualifying response is received before t0 + wait_interval, When the timer expires, Then the system sends the next step to the secondary caregiver using their top-ranked allowed channel within 5 seconds and marks the cascade step "Escalated". Given a qualifying response is received from any caregiver before timer expiry, Then the cascade transitions to the resolved state and no escalation message is sent. Given the maximum steps is reached without a qualifying response, Then the cascade stops automatically and sets outcome "Unresolved - Max Steps" without sending further messages.
Campaign-Level Overrides of Practice Defaults
Given practice defaults (wait=60m, max_steps=2, stop_conditions=confirm|reschedule|decline) and a campaign configured (wait=30m, max_steps=3), When a cascade is created under that campaign, Then the effective configuration equals the campaign values and is logged in the audit record. Given a cascade in progress, When the practice default is changed, Then the in-progress cascade continues with its existing effective configuration and new cascades use the updated defaults. Given a campaign has no explicit value for a setting, When the cascade is created, Then the effective configuration inherits the practice default for that setting. Given an admin updates a campaign setting, When a new cascade is created after the change, Then the audit trail shows the new effective configuration values.
Response Parsing for State Transitions and Termination
Given inbound responses via SMS, email link/button, or voice DTMF, When the content matches configured intents (Confirm: "C","YES","Confirm", link/button confirm; Reschedule: "R","Resched", link/button reschedule; Decline: "N","No","Cancel", link/button decline) case-insensitive and trimmed of whitespace, Then the system sets the corresponding state and terminates the cascade immediately within 3 seconds. Given a non-qualifying response (free text, emoji, unknown), When received, Then the system sends a single clarification message per cascade step and keeps the timer running; no termination occurs. Given multiple inbound messages arrive in close succession, When the first qualifying intent is processed, Then later messages in the same cascade are ignored for state changes and are recorded in the audit trail as "Post-resolution". Given a qualifying response arrives after escalation but before the secondary responds, Then the cascade outcome reflects the first qualifying response and stops further outreach.
Household/Sibling Coordination to Prevent Redundant Outreach
Given siblings with appointments within a configured coordination window (e.g., same day) and linked to the same household, When a caregiver confirms "All" via a multi-appointment link/button or selects all appointments in the confirmation page, Then all linked cascades are resolved as Confirmed and pending/scheduled messages to other siblings are canceled. Given a caregiver confirms only one specific appointment, When processed, Then only that appointment's cascade resolves and other siblings remain active. Given any one sibling's cascade reaches a resolved outcome that is marked household_coverage=true, Then no additional escalation steps are sent for other siblings within the coordination window. Given previously scheduled sends for siblings are canceled due to household coverage, Then the UI and audit trail reflect the cancellation reason "Covered by sibling response".
Respect Language, Channel Order, and Quiet Hours
Given caregiver preferences for language, channel order, and quiet hours, When sending any cascade step, Then the message is localized to the caregiver's language, sent via the highest-ranked allowed channel, and not sent during quiet hours. Given an escalation timer expires during the caregiver's quiet hours, When the next step would send, Then the send is deferred to the next allowable minute after quiet hours and the UI shows the adjusted "Next action at" timestamp. Given all preferred channels are temporarily unavailable, When a step must send, Then the system attempts the next allowed fallback channel defined by practice policy and records the reason for fallback. Given conflicting preferences across caregivers, When escalating, Then the system applies the preferences of the targeted caregiver for that step.
Real-Time Cascade Status in Staff UI
Given a staff user opens the appointment detail, When a cascade is active, Then the UI shows current state, recipient, channel, last event timestamp, next action ETA countdown, and remaining steps. Given any cascade event occurs (send, delivery, response, escalation, cancel), When it is recorded, Then the UI updates within 5 seconds and a manual refresh reflects the same data. Given a staff user cancels a cascade from the UI, When confirmed, Then all pending sends are canceled, status becomes "Canceled by Staff", and no further messages are sent. Given network latency or backend delay, When the UI cannot fetch updates, Then it displays a non-blocking warning and retries every 10 seconds until successful.
Complete Audit Trail of Cascade Decisions
Given any cascade is created, When events occur, Then each event is logged with timestamp (UTC), actor (system/caregiver/staff), message ID, channel, language, intent parsed, previous state, next state, effective config snapshot, correlation IDs (appointment_id, household_id, campaign_id), and outcome. Given an auditor exports the log for a cascade, When the export is generated, Then it contains an ordered, immutable record of all events and decisions, including SLA timers and deferments, with no PII beyond allowed HIPAA-safe identifiers. Given a dispute on whether an escalation occurred on time, When reviewing the audit trail, Then the timestamps show the timer start, expiry, and send time within ±5 seconds of expected, or record the deferment reason (quiet hours, channel outage). Given a caregiver opts out (STOP), When processed, Then the audit trail records opt-out intent, halts the cascade, and flags future outreach per compliance rules.
Multi-Channel Failover & Bounce Handling
"As a scheduling coordinator, I want undelivered messages to automatically switch to an alternate channel so that families still receive time-sensitive reminders."
Description

Monitor delivery outcomes via carrier and email provider webhooks and automatically fail over to an alternate channel when delivery fails, is blocked (e.g., DND), or remains undelivered beyond a threshold. Support voicemail drops for voice fallback and track email bounces, spam complaints, and SMS error codes with mapped retry logic. De-duplicate notifications per caregiver to prevent spam, enforce STOP/UNSUBSCRIBE compliance, and annotate each attempt with outcome metadata. Provide configuration for channel order, retry counts, and cooldowns, with visibility in the UI for staff to see what happened and why. This maximizes deliverability while maintaining compliance and user trust.

Acceptance Criteria
SMS Failure Triggers Email Failover to Primary Caregiver
Given a scheduled reminder is sent via SMS to the primary caregiver and the carrier webhook returns a permanent failure or blocked/DND code When the failure event is received and processed within 60 seconds Then the system schedules an email to the same caregiver as the next configured channel within 2 minutes And the SMS attempt is marked Failed with provider message-id, error code, and timestamp And the email attempt metadata references the failed SMS message-id And no SMS retry is attempted for permanent failures
Undelivered Timeout Triggers Voice Fallback with Voicemail Drop
Given an email attempt has no Delivered (or Bounce) webhook received within the configured undelivered timeout (e.g., 30 minutes) When the timeout elapses Then the system attempts a voice call to the caregiver per configured channel order and drops voicemail if the call is unanswered after 20 seconds And the voicemail audio matches the practice-configured template for the appointment type and language And the system records call status (answered, busy, no-answer, voicemail-dropped), provider call SID, and duration And the email attempt is marked Timed Out with timeout value recorded
Email Bounce and Spam Complaint Retry Mapping
Given an email bounce webhook (5xx) or spam complaint event is received for a caregiver address When the event is classified as permanent Then the system suppresses future email attempts to that address for 90 days and triggers failover to the next channel within 2 minutes And metadata captures bounce type (hard/soft), SMTP/status code, provider event-id, and complaint flag And soft bounces (4xx) are retried up to the configured count with exponential backoff cooldowns And no more than one retry is in-flight at any time per caregiver per appointment
Caregiver-Level De-duplication Across Channels
Given multiple reminder attempts for the same appointment could target the same caregiver across channels within a 10-minute window When a failover is initiated or parallel attempts are queued Then only one notification per caregiver per appointment is sent within the de-dup window And suppressed attempts are recorded with suppression reason and reference to the winning attempt And de-dup keys on caregiver-id + appointment-id + template-variant to avoid false positives
STOP/UNSUBSCRIBE Compliance and DND Enforcement
Given a caregiver replies STOP to SMS or clicks an email unsubscribe link When the unsubscribe event is processed Then all future outbound messages on that channel to that caregiver are blocked within 60 seconds And an optional confirmation message is sent only where permitted and configured And any attempted send on a blocked channel is prevented with a compliance error and no provider/API call is made And failover honors consent; only channels with valid consent and outside DND hours are used
Configurable Channel Order, Retries, Cooldowns, and Error Mapping
Given a practice configures channel order [SMS, Email, Voice], retry counts (e.g., SMS:0, Email:2, Voice:1), cooldowns (e.g., Email retry:15m), and per-channel undelivered timeouts When a delivery failure, block, or timeout occurs Then the next allowed channel is selected according to the configured order and caregiver preferences (language, channel, time-of-day) And retries and cooldowns are applied exactly as configured, with validation preventing invalid combinations at save time And provider error codes are mapped to retryable vs permanent categories per spec, with retryable errors retried and permanent errors not retried And configuration changes take effect for new workflows within 5 minutes and are captured in an audit log
UI Audit Trail and Outcome Metadata Visibility
Given staff open the communication details for an appointment When viewing the message timeline Then the UI displays each attempt with channel, timestamp, status (Queued, Sent, Delivered, Failed, Timed Out, Suppressed), provider identifiers, and error codes And shows the rule that triggered any failover or suppression (e.g., DND, permanent failure, timeout) And supports filtering by caregiver and channel, with all timestamps shown in practice local time and UTC on hover And the entire sequence can be exported as a JSON or CSV audit report
Unified Audit Trail & Compliance Export
"As a compliance officer, I want a complete, exportable audit trail of caregiver routing decisions and communications so that we can satisfy HIPAA audits and incident reviews."
Description

Produce an immutable audit trail for every communication, capturing the selected caregiver(s), permission checks and results, preference evaluations, templates used (versioned), message content metadata, timestamps, delivery receipts, response events, and cascade decisions. Provide secure search, filtering, and export (CSV/PDF) with redaction controls and role-based access. Implement retention policies aligned with HIPAA and practice requirements, including tamper-evident storage and event signing. Expose audit views in the UI and via API for compliance officers and administrators, enabling rapid incident review and regulatory audits without exposing unnecessary PHI.

Acceptance Criteria
Immutable Event Logging for Caregiver Cascade
Given a Caregiver Cascade communication is initiated for a patient with multiple guardians When permissions and preferences are evaluated and messages are sent across channels Then an immutable audit event is written containing: communication_id, tokenized_patient_id, caregiver_ids, selected_primary_caregiver_id, selected_secondary_caregiver_id, permission_check_result and source, preference_evaluation_inputs and result, template_id, template_version, content_metadata (content_hash, language, channel, PHI_tags), cascade_path, timestamps (created_at, sent_at, delivered_at, responded_at), delivery_receipts, response_events, actor_id, event_signature, previous_event_hash And the write is append-only and any update/delete attempt via UI/API/DB returns 409 and emits tamper_attempt with actor_id and timestamp And the event’s signature verifies with platform KMS keys and the hash chain links to the previous_event_hash And for a test batch of 100 sent messages, 100 audit events exist and are available for query within 2 seconds of send
Role-Based Audit Access & PHI Redaction
Given a signed-in user requests audit views via UI or API When the user role is ComplianceOfficer Then full audit fields are visible with a PHI redaction toggle defaulting to redacted and unredaction requires explicit toggle and is logged with reason And access is granted (200) and an access_audit event is recorded with user_id, role, filters, redaction_state When the user role is Admin Then metadata and minimal PHI are visible by default; requesting unredacted view prompts for justification and requires scope audit.read.unredacted; without scope returns 403 When the user role is Staff or below Then responses are redacted-only and attempts to unredact return 403 and are logged When the request is unauthenticated or from a disallowed IP Then access is denied with 401/403 and no data is leaked
Secure Search & Filter with Performance Guarantees
Given an authorized user opens the Audit UI When they filter by date range, patient token, caregiver, channel, language, template_version, delivery status, cascade outcome, or permission result Then results return within 2 seconds at P90 for up to 10,000 matching events and reflect the active redaction state And search indexes store only allowed metadata (no raw message bodies or unredacted PHI) and queries are logged as access_audit events And pagination supports cursor-based navigation with stable ordering by created_at desc, then event_id
Export to CSV/PDF with Redaction, Watermark, and Integrity
Given an authorized user requests an export with current filters and redaction state When CSV is selected Then the file includes a header (export_id, requester, timestamp, filters, redaction_state), UTF-8 with BOM, RFC 4180-compliant quoting, SHA-256 checksum, and detached signature; row count matches on-screen results When PDF is selected Then each page is watermarked “Confidential — HIPAA” with export_id and includes the same header metadata and an embedded signature; layout preserves row integrity across pages And the export is delivered via a time-limited signed URL (expires <= 15 minutes), over TLS 1.2+, and an export_created audit event is recorded And requesting unredacted exports requires scope audit.read.unredacted; otherwise export is redacted
Retention Policy, Legal Hold, and Purge Auditability
Given the default retention period is 6 years and a practice-specific override may be configured (>= regulatory minimum) When the nightly retention job runs Then audit events older than the effective retention period are purged and a signed, immutable tombstone record is written containing event_id, purge_reason, purge_timestamp, actor=system And active legal holds prevent purge of matching records until the hold is released; holds and releases are auditable events And after purge, restored backups do not reintroduce purged content; integrity checks pass on the remaining hash chain
API Audit Access with OAuth Scopes and Rate Limits
Given an API client with OAuth2 client credentials and scope audit.read.redacted When it calls GET /audit/events with filters and page_size=500 Then the response is 200 with redacted fields, a next_cursor when more results exist, ETag, and completes within 500 ms at P90 for up to 1,000 events When the client requests unredacted data without scope audit.read.unredacted Then the response is 403 When request rate exceeds 60 requests/minute per client Then further requests return 429 with Retry-After And error responses include correlation_id and are recorded as access_audit events
Consent & Opt-Out Management per Caregiver and Channel
"As a caregiver, I want simple opt-in and opt-out controls per channel with clear records so that I control how and if I’m contacted about my child."
Description

Track and enforce consent at the caregiver-and-channel level, including double opt-in for SMS where required. Record consent source, timestamp, and method; honor STOP/UNSUBSCRIBE and equivalent keywords; and provide clear re-consent flows with logging. Block non-transactional outreach when consent is missing, while allowing strictly transactional messages if permitted by policy. Provide staff tools and API endpoints to review and update consent states with audit notes, and integrate consent checks into routing, cascade, and failover logic. Ensure alignment with TCPA/CTIA, CAN-SPAM, and HIPAA minimum-necessary practices to prevent unauthorized contact and maintain trust.

Acceptance Criteria
SMS Double Opt-In per Caregiver and Channel
Given a caregiver phone number is captured or updated and double opt-in is required, When the system sends an opt-in SMS and the caregiver replies YES, START, or Y within 24 hours, Then SMS consent=true for that caregiver and number, a confirmation SMS is sent with program name and HELP/STOP instructions, and source/method/timestamp are logged. Given no valid confirmation is received within 24 hours or the caregiver replies NO or STOP, When the pending consent is evaluated, Then SMS consent=false remains and non-transactional SMS is blocked; the event is logged with reason. Given staff attempts to set SMS consent active via UI or API, When saving, Then the system records source and method, sets state=pending, and requires confirmation from the caregiver device before activating; until then, non-transactional SMS remain blocked.
Email Unsubscribe and Re-Consent Flow
Given a caregiver clicks the one-click unsubscribe link in a non-transactional email, When the link is visited, Then email_marketing_consent=false is set immediately for that caregiver-address, a confirmation page is shown, and the change is logged with source=email_link and timestamp. Given email_marketing_consent=false for a caregiver, When a non-transactional email send is attempted, Then the system blocks the send, logs prevented_send with reason=missing_consent, and returns an error to caller. Given a caregiver initiates re-consent via the preference center, When they confirm via a verification link sent to that email, Then email_marketing_consent=true is set, confirmation email is sent, and both request and verify events are logged with IP and user agent. Given a transactional email is queued, When policy allows transactional without marketing consent, Then the system allows the send only if the message is flagged transactional and content meets minimum-necessary rules; otherwise it is blocked and logged.
Consent Metadata Logging and Audit Trail
Given any consent state change for any caregiver-channel, When the change is saved, Then an immutable audit record is created with caregiverId, patient link, channel, address/number (hashed), old_status, new_status, source, method, actor (userId/API key), IP, UTC timestamp, reason/note, and evidence pointer (fileId/messageId). Given staff filters audit records by caregiver, channel, and date range, When the query is executed for up to 10,000 records, Then results return within 2 seconds and can be exported as CSV with consistent headers. Given a client with consents:read_audit scope calls GET /consents/audit with valid parameters, When records exist, Then the API returns paginated, signed results with a checksum per page to detect tampering.
Consent Gate in Caregiver Cascade and Failover
Given a cascade is initiated for a child’s appointment, When selecting the next recipient and channel, Then only caregiver-channel pairs with consent=true for the intended message type are eligible; if the primary caregiver/channel lacks consent, the engine evaluates the next preferred channel or escalates to a secondary caregiver with proper permissions; all decisions are logged. Given all caregiver-channel pairs lack consent for non-transactional messages, When the cascade runs, Then no messages are sent, a manual follow-up task is created, and the prevented cascade is logged with reasons. Given a caregiver has revoked SMS via STOP, When the cascade runs, Then SMS is excluded for that caregiver but other consented channels (e.g., email, voice) remain eligible per preferences.
Transactional vs Marketing Enforcement and HIPAA Minimum Necessary
Given a message is flagged transactional (e.g., appointment reminder), When caregiver marketing consent is missing but policy permits transactional, Then the system allows the send only if the content matches an approved template with no diagnosis/procedure details and adheres to minimum-necessary; the policy check outcome is logged. Given a message is flagged marketing or mixed content, When explicit consent for that channel is absent, Then the system blocks the send and logs prevented_send with classification=marketing and reason=missing_consent. Given staff attempts to override a blocked send, When they lack the required RBAC permission, Then the override is denied; When they have permission, Then a justification note is required and a re-consent workflow is triggered where applicable, with all actions logged.
Staff UI and API for Consent Review/Update with RBAC and Notes
Given an authorized staff member opens a caregiver profile, When viewing the Consent tab, Then per-channel statuses (SMS, email, voice), source, method, timestamps, and last change notes are displayed with masked identifiers; edit actions are gated by RBAC. Given staff updates a consent state, When saving, Then they must select source and method and enter an audit note (minimum 15 characters); for SMS the state becomes pending and a confirmation message is sent to the device; activation requires a valid keyword reply; all changes are logged. Given an API client with consents:write scope posts to POST /consents with valid payload, When processed, Then the consent is created/updated with appropriate state (pending/active), a consent.updated webhook is emitted, and the API returns 200 with the current state; invalid payloads return 4xx with error details.
Keyword Handling and CTIA/TCPA Compliance for SMS
Given an inbound SMS contains STOP, STOPALL, UNSUBSCRIBE, CANCEL, END, QUIT, ALTO, CANCELAR, FIN, or PARAR (case/spacing-insensitive), When processed, Then SMS consent=false is set for that caregiver-number under the program, a single opt-out confirmation is sent, and further non-transactional SMS are blocked; the event is logged with source=inbound_keyword. Given an inbound SMS contains START, YES, or UNSTOP after an opt-out, When processed, Then SMS consent=true is set, a confirmation message with program name and HELP/STOP instructions is sent, and the re-consent is logged with timestamp and device identifier. Given an inbound SMS contains HELP or AYUDA, When processed, Then the system sends a HELP response including program name, brief description, message frequency, carrier disclaimer, support contact, and STOP instructions; responses are rate-limited to 1 HELP per minute per number.

Bundle Prep

Combines pre-visit instructions, forms, and consents for all children into one secure link with per-child tabs. Auto-applies identity verification for PHI, collects signatures once when allowed, and nudges caregivers on what’s missing. Parents complete everything in minutes; day-of delays and paperwork bottlenecks disappear.

Requirements

Single Secure Family Link Delivery
"As a caregiver with multiple children scheduled, I want one secure link for all pre-visit tasks so that I can complete everything quickly without juggling multiple messages."
Description

Generate and deliver a unique, expiring, tokenized link that bundles all pre-visit instructions, forms, and consents for all scheduled children in a household. The link is sent via SmileCue’s channels (SMS and email) using response-driven branching to choose best channel and timing. Supports one-click access with automatic session creation, configurable expiry, revocation, and resend. Associates the link with the caregiver’s contact record and upcoming appointments, merges multiple appointments within a defined window, and enables cross-device resume. Tracks delivery, open, and per-child completion metrics. Integrates with SmileCue’s messaging to pause outreach once completed and with security controls to gate PHI behind identity verification.

Acceptance Criteria
Best-Channel Single Secure Family Link Delivery
Given a caregiver has at least one SMS-capable number and one email on their SmileCue contact record and has two or more upcoming appointments for children within the configured merge window And response-driven branching rules are active When a family bundle link is requested by the scheduler or nightly automation runs Then the system generates exactly one unique, tokenized URL for that caregiver covering all eligible appointments at that time And the token contains at least 128 bits of entropy and is not embedded with PII And the link is associated to the caregiver contact record and all eligible appointment IDs And initial delivery is sent via the channel selected by branching rules at the scheduled time And on hard-delivery failure on the first channel, the system retries via the alternate channel within 5 minutes And delivery and open events are recorded with timestamp, channel, template ID, and provider message IDs
Configurable Expiry and Post-Expiry Handling
Given the practice has set a link expiry to N days (1 <= N <= 60) in practice settings And a family link was generated at T0 in the practice’s timezone When the link is accessed at T > T0 + N days Then access is blocked with an “Link expired” screen that reveals no PHI And the token is marked expired and cannot be used to create a session And an audit log entry is created with actor=anonymous, reason=expired, token ID, and IP And staff can override expiry per link to any value in the allowed range, and the UI displays the new expiry timestamp
Revocation and Resend Rotation
Given a staff member clicks “Revoke link” for a caregiver in the SmileCue UI When revocation is confirmed Then the existing token is invalidated within 60 seconds and all future requests with that token return “Link revoked” without PHI And a new tokenized link is generated and can be copied or resent via SMS/email with a single action And all subsequent deliveries reference only the new token And audit logs capture revocation with user ID, timestamp, and reason
Appointment Merge and Household Bundling
Given children A and B share a caregiver contact and have appointments within the configured merge window When a family link is generated Then the bundle contains per-child tabs for each eligible child and all associated pre-visit items And if an additional appointment for a linked child is scheduled within the merge window before link expiry, the bundle reflects the new appointment upon next access without issuing a new token And if a child is unlinked from the caregiver, that child’s tab is removed on subsequent access And different caregivers in the same household receive distinct links that include only the children linked to their own contact records
One-Click Access, Session Creation, and PHI Gating via IDV
Given a caregiver clicks the family link When the landing page loads Then a session is automatically created and bound to the token and device fingerprint And no PHI or editable form fields are displayed until identity verification (IDV) succeeds per practice policy And after successful IDV, PHI-gated content is unlocked and signatures can be collected And when practice rules allow a single guardian signature for siblings, one signature applies to all relevant child forms and is recorded once with cross-references And after 3 failed IDV attempts within 15 minutes, access is temporarily locked for 30 minutes and an audit entry is created
Cross-Device Resume and Concurrency
Given a caregiver partially completes the bundle on Device A When the same link is opened on Device B before expiry Then the caregiver’s progress (completed forms, signatures, uploads) is visible and no duplicate tasks are presented And the caregiver can continue from the last incomplete step without redoing IDV if within the active session window And if simultaneous edits occur, the most recent submission wins and the other session is notified to refresh with a non-destructive warning
Completion Tracking and Outreach Pause Integration
Given the practice defines completion as “all required items completed for all bundled children” When the caregiver completes the bundle Then the system records delivery, first open timestamp, per-child completion timestamps, and total time-to-complete And a “bundle_completed” event is emitted to SmileCue Messaging within 60 seconds to pause further reminders for the included appointments And if the bundle is partially complete, only nudges for missing items are sent; if fully complete, all remaining outreach for those appointments is suppressed And completion metrics are available in reporting with filters by practice, caregiver, and date range
Per-Child Tabbed Workflow
"As a parent of multiple children, I want a clear tabbed view for each child so that I can see what’s done and what’s missing per child at a glance."
Description

Present a unified Bundle Prep experience with per-child tabs, progress indicators, and validation states. Shared household and insurance information is captured once and propagated to all children, while child-specific forms (e.g., medical history) remain scoped to each tab. Supports adding/removing a child from the bundle when appointments change, autosave and resume, required field enforcement, and inline guidance for pre-visit instructions. Ensures WCAG AA accessibility, mobile-first responsiveness, and localization-ready labels. Emits granular events for analytics, and exposes a summary screen that highlights outstanding items per child prior to final submission.

Acceptance Criteria
Per-Child Tab Navigation and Scoping
Given a bundle with 3 children, When the caregiver selects a child tab, Then only that child’s forms and saved values are shown; shared sections are displayed once outside the tabs. Given the caregiver edits a child-specific field in Child A, When they view Child B, Then Child B does not reflect Child A’s change. Given the caregiver switches tabs, When they return to a tab, Then the prior input state and validation messages for that tab are preserved.
Shared Household & Insurance Propagation
Given the caregiver completes the Household and Insurance section, When they open any child tab, Then each child shows those shared values pre-populated and read-only within child views. Given the caregiver updates a shared value after completing one or more child tabs, When they navigate to any child tab, Then the updated value is reflected for all children without overwriting child-specific fields. Given the caregiver attempts to override a shared-only field within a child tab, Then the UI directs them to the shared section and prevents per-child overrides.
Per-Child Progress Indicators, Validation, and Inline Guidance
Given Child A has 10 required fields and 2 are incomplete, When viewing the tab bar, Then Child A’s tab displays a “Needs Attention” state with count 2. Given all required fields for a child are complete and valid, When viewing the tab bar, Then that child’s tab displays “Complete” and the child’s progress indicator reads 100%. Given a required field is empty or invalid, When the field loses focus or the caregiver attempts to proceed, Then an inline error with actionable guidance appears next to the field and the first invalid field receives focus. Given a pre-visit instruction has an info icon, When the caregiver taps or focuses it, Then an inline guidance panel expands with the instruction text and can be dismissed via click or ESC. Given the caregiver corrects an invalid field, When the value becomes valid, Then the error clears and progress updates within 500 ms.
Add/Remove Child from Bundle
Given the caregiver selects “Add Child”, When they enter the child’s basic details and confirm, Then a new child tab is created with shared data prefilled and child-specific forms blank. Given the caregiver selects “Remove Child” for Child C, When they confirm removal, Then Child C’s tab and data are removed, overall progress recalculates, and submission availability updates accordingly. Given the provider cancels Child D’s appointment server-side, When the bundle syncs, Then Child D’s tab is removed within 5 seconds and the caregiver sees a non-blocking toast notification.
Autosave and Resume
Given the caregiver is filling forms online, When they stop typing or change a field, Then autosave occurs within 5 seconds or on field blur, whichever comes first. Given the caregiver closes the browser, When they reopen the same secure link, Then all previously autosaved data is restored within 2 seconds of load. Given the device is offline, When the caregiver edits fields, Then changes are saved locally, a “Saved offline” indicator is shown, and the data syncs to the server within 5 seconds of reconnection.
Submission Summary with Outstanding Items and Analytics Emission
Given the caregiver opens the Summary screen, When not all children are complete, Then the Summary shows a per-child list of outstanding required items with counts and deep links that navigate to the exact field when selected. Given all children are complete and valid, When on the Summary screen, Then a “Ready to Submit” state is shown and the Submit action is enabled. Given the caregiver attempts to submit with outstanding items, When they click Submit, Then submission is blocked, the Summary displays the blocking items, and focus moves to the first unresolved item. Analytics: When the caregiver performs key actions (tab_viewed, field_changed, validation_error, autosave_success|failure, child_added, child_removed, summary_viewed, submission_attempted, submission_blocked, submission_succeeded), Then an analytics event is emitted with properties: bundle_id, caregiver_session_id, child_id (nullable for shared), form_key, field_key (when applicable), locale, device_type, timestamp (ISO 8601), outcome, error_code (optional), without transmitting PHI values; events are batched and delivered at most every 10 seconds (or 20 events), and queued/retried offline up to 24 hours.
Accessibility, Mobile Responsiveness, and Localization Readiness
Given keyboard-only navigation, When interacting with tabs and forms, Then focus order is logical, focus is visible, and all controls are operable without a mouse. Given a screen reader is enabled (VoiceOver, TalkBack), When navigating tabs and error messages, Then tab names and statuses are announced, required fields are indicated, and errors are read via aria-live politely. Given color contrast auditing, When measured, Then text and interactive elements meet WCAG 2.2 AA contrast ratios (>= 4.5:1 normal text; >= 3:1 large text and UI components). Given small screens (>= 320px width), When viewing the workflow, Then the layout is responsive, no horizontal scroll is required, and interactive targets meet a minimum 44x44 px touch size. Given a non-English locale (e.g., es-419), When labels and messages are loaded, Then all user-facing text is sourced from locale files, renders without truncation or overlap, and date/time/number formats follow the locale.
Adaptive Identity Verification (PHI Gate)
"As an office manager, I want caregivers to verify their identity before accessing PHI so that our practice remains compliant and patient data stays protected."
Description

Apply risk-based identity verification before exposing or transmitting PHI within the bundle. Supports configurable verification tiers (e.g., SMS one-time code, email magic link confirmation, caregiver and child DOB match, and optional document/ID scan for higher risk scenarios). Rate-limit attempts, detect anomalies, and record verification outcomes. Enforce minimum necessary data exposure until verification passes. Provide fallback verification paths for edge cases (e.g., guardianship variations) with office approval workflow. All verification events are captured in the audit log and surfaced to staff.

Acceptance Criteria
Risk-Based Tier Selection & Enforcement
Given a configurable verification policy with risk signals and tier thresholds is active for Bundle Prep When a caregiver opens a bundle link Then the system evaluates signals (device fingerprint, IP geolocation, prior verification age, contact match) and selects Tier 1, 2, or 3 per policy And the selected tier and reason codes are stored with the bundle session And the UI displays only the steps required for the selected tier And the tier can be escalated if new risk is detected during the session but cannot be downgraded And PHI remains gated until the selected tier is successfully completed
Tier 1/2 Verification Flows (SMS OTP, Email Magic Link, DOB Match)
Given policy is configured with OTP length=6, OTP expiry=10 minutes, max OTP attempts=5, magic-link expiry=15 minutes, verification TTL, and DOB attempts=3 When the caregiver chooses SMS OTP at Tier 1 Then a one-time 6-digit code is sent to the phone on file within 5 seconds p95 and the phone is masked in UI except last 2 digits And the code is valid for 10 minutes, single-use, and cannot be tried more than 5 times per hour per phone and per bundle And on correct code entry, the caregiver is marked Verified for the bundle for the configured TTL When the caregiver chooses Email Magic Link at Tier 1 Then a single-use link with 15-minute expiry is sent to the email on file and cannot be reused And clicking the link opens the bundle and marks the caregiver Verified When Tier 2 is selected Then, in addition to Tier 1, the caregiver must enter their DOB and the selected child’s DOB to exactly match the record within 3 attempts or the session is escalated or locked per policy And all successes, failures, and lockouts are recorded with timestamps and attempt counts
Tier 3 High-Risk Document/ID Scan Verification
Given policy requires Tier 3 for high-risk sessions When the caregiver is prompted to complete an ID verification Then the system accepts a live capture or upload of a government-issued ID and a selfie per policy and validates name and DOB against the record And processing returns a pass/fail decision within 60 seconds p95 or times out gracefully with retry messaging And on pass, the caregiver is marked Verified for the bundle; on fail or timeout after 3 attempts, the session is routed to fallback office approval And all verification artifacts are stored securely, access-controlled, and referenced in the audit log without exposing images in the staff list view by default
Minimum Necessary Data Exposure Prior to Verification
Given a caregiver opens a bundle without having passed verification When the bundle loads Then only non-PHI context (practice name, appointment date/time, child first-name initial) is visible And all API endpoints that include PHI return 403 NotVerified with no PHI in payloads, pre-signed URLs are not created, and downloads are disabled And after verification success, the same endpoints return 200 with permitted PHI and UI reveals previously gated sections And any outbound communications triggered from the bundle prior to verification contain no PHI
Rate Limiting, Lockout, and Anomaly Detection
Given policy values for rate limits (OTP sends/phone/hour=3, OTP verify attempts/session=5, DOB attempts/session=3, document attempts/session=3) and lockout duration=15 minutes When limits are exceeded Then additional requests are blocked with generic messaging, no further codes are sent, and the session is locked for 15 minutes And per-IP and per-device global limits (e.g., 20 OTP sends/IP/hour) are enforced concurrently When anomalies are detected (e.g., country mismatch, impossible travel, device fingerprint change mid-session) Then the system escalates the session to a higher tier or blocks verification per policy, and an alert is created for staff review And all events include structured reason codes for analytics and audit
Fallback Verification with Office Approval Workflow
Given a caregiver cannot complete automated verification (e.g., guardianship variation, unmatched contact info) When the caregiver selects Request Office Approval and provides a reason and optional documents Then a task is created in the staff portal with bundle link, patient(s), caregiver details, and submitted evidence And authorized staff can Approve or Deny with a reason; approval grants verified access for a policy-configured window for the specific bundle And the caregiver is notified of the decision, and all actions are logged with actor identity and timestamps And approvals bypass only the remaining verification steps; other bundle rules remain enforced
Audit Logging & Staff Visibility
Given any verification-related event occurs When the event is recorded Then an immutable audit entry is stored with fields: bundle_id, caregiver_id, patient_id(s), event_type, tier, outcome, reason_code(s), attempt_count, timestamp (UTC), device_id, truncated IP, policy_version, channel And staff can view verification status and event history on the bundle detail screen with filters by outcome and date range And exports include the same fields, omit PHI beyond minimum necessary, and are access-controlled by role And audit entries are available within 5 seconds of the event p95
Smart Consent Reuse & Signature Minimization
"As a caregiver, I want to sign shared consents once so that I avoid repeating identical signatures for each child."
Description

Determine which consents and acknowledgments can be applied once across siblings (e.g., financial responsibility) versus those requiring per-child signatures (e.g., treatment consent) based on practice policy and jurisdiction. If a valid prior consent exists within policy windows, pre-acknowledge and exclude from the bundle or request confirmation of no changes. Capture a single legally compliant e-signature and programmatically apply to eligible documents with per-child tokens, timestamps, and version identifiers. Handle re-collection when forms are updated, and support in-office fallback for exceptions.

Acceptance Criteria
Policy-Based Consent Categorization
Given practice policy configuration and jurisdiction rules are loaded And a caregiver is preparing a bundle that includes two or more children When the system assembles the consent and acknowledgment checklist Then each consent template must be classified as family-wide (one per family) or per-child according to the configured mapping And only one instance of each family-wide consent is presented to the caregiver And a separate instance of each per-child consent is presented for each child And the classification decision is recorded with policy version, jurisdiction, and timestamp
Valid Prior Consent Auto-Reuse
Given a previously signed consent exists for the caregiver that matches the current template ID and is within the validity window defined by policy and jurisdiction When the bundle is generated Then the consent is marked as satisfied and excluded from required actions And a badge is shown to the caregiver stating "Previously signed on <date>" with a link to view the prior consent And the reuse event stores original signature metadata (signer, timestamp, IP, device, template version) and the reuse timestamp And if policy requires reconfirmation, when the caregiver confirms "no changes," a confirmation timestamp and user agent are recorded And if the caregiver indicates changes, the consent is returned to the checklist for re-signing
Single Signature Application to Eligible Documents
Given at least one eligible family-wide consent requires signing And the caregiver has passed identity verification When the caregiver applies a single e-signature Then the signature is applied to all eligible family-wide documents in the bundle And per-child tokens are generated linking the signature to each child's record where required And a signature envelope is stored including signature ID, intent confirmation, disclosure acceptance, timestamp, IP, device fingerprint, per-document hash, per-child tokens, and template version IDs And non-eligible documents remain unsigned and are queued for separate per-child signatures
Version Change or Expiry Triggers Re-Collection
Given a previously signed consent exists but the validity window has expired or the current template version differs from the signed version When the bundle is generated Then the prior consent is not reused And the updated consent is included in the checklist and clearly labeled "Updated" with a link to a change summary And any unaffected consents remain reused without action And the new signature record references the new template version and supersedes the prior record
Identity Verification Gate for PHI and Signing
Given the bundle contains PHI or any consent requires e-signature When the caregiver opens the secure link Then the system must require identity verification per policy (e.g., SMS OTP, DOB+ZIP, KBA) before displaying PHI or enabling signing And failed attempts are counted and the session is locked after the configured threshold (default 5) with a practice notification And the verification method, result, and timestamp are recorded in the audit trail And upon successful verification, access is granted for the session duration defined by policy
In-Office Fallback and Reconciliation
Given a caregiver cannot complete e-signature remotely or an exception is flagged by staff When staff selects "In-Office Fallback" for the consent and captures an in-office e-signature (tablet) or uploads a scanned paper form Then the system attaches the signature or document to the correct consent template and associated child(ren) And updates the bundle status to reflect completion for the affected consents And records staff user ID, location, capture method, and timestamp And suppresses further remote requests for the completed consents
Completion Nudges & Deadline Reminders
"As an office manager, I want targeted nudges that point caregivers to incomplete items so that we minimize day-of paperwork and delays."
Description

Automate response-driven reminders that reference exactly what is missing per child and deep-link the caregiver back into the correct tab/section. Orchestrate multi-channel outreach (SMS, email, optional voice) with quiet hours, frequency caps, and stop rules upon completion. Surface a staff dashboard to view bundle status, trigger manual nudges, and override deadlines. Provide templated, localized content that dynamically lists outstanding items, and report on conversion rates, completion time, and no-show reduction attributable to Bundle Prep.

Acceptance Criteria
Multi-Channel Orchestration with Quiet Hours and Caps
Given a bundle has outstanding items and the caregiver has SMS and email reachable When the reminder scheduler runs Then send at most 1 SMS and 1 email per caregiver per 24 hours for this bundle And respect quiet hours set to 20:00–08:00 practice local time by deferring sends to the next allowed window And escalate to voice only if no engagement occurs within 48 hours and the caregiver has opted into voice calls And stop all outreach immediately once all required items are completed And cap total outreach to a maximum of 5 attempts per bundle across all channels And record delivery, bounce, open (email), click, reply, and call answer events with timestamps And if the caregiver replies STOP/UNSUBSCRIBE to SMS, cease SMS outreach for this bundle and future bundles and record opt-out And if the caregiver replies HELP to SMS, return a configurable help message without counting against the frequency cap
Deep-Link to Missing Items per Child/Section
Given a caregiver receives a reminder for an incomplete bundle When they open the deep link Then the Bundle Prep page opens with the correct child tab preselected and scrolled to the first incomplete section And the reminder message enumerates outstanding items per child by type (e.g., forms, consents, signatures) in plain text And once an item is completed, it is removed from the list in subsequent reminders And the deep-link token is single-use, expires in 24 hours or upon bundle completion (whichever comes first) And requesting a new link invalidates prior unused tokens
Identity Verification for PHI Access
Given the bundle contains PHI-protected items and the caregiver follows a deep link When identity verification is required Then prompt for a one-time code delivered to the phone or email on file (configurable by practice) And allow 3 attempts before a 15-minute lockout And upon successful verification, grant a session valid for 30 minutes of activity And log verification outcomes (success/failure, channel, timestamp, user agent, IP) for audit And do not require verification for non-PHI summaries (e.g., generic reminder text)
Deadline Reminders and Staff Overrides
Given a bundle has a due date tied to the appointment When the bundle remains incomplete Then send deadline reminders at T-72h, T-24h, and T-2h respecting quiet hours and frequency caps And stop scheduling further reminders once the bundle is complete And if staff overrides the due date, recalculate all future reminders accordingly And record overrides with user, timestamp, old value, new value, and reason And if the due date passes without completion, send one final past-due reminder at the next allowed window and mark the bundle Past Due And do not send additional reminders after Past Due unless a staff member reopens the bundle
Staff Dashboard: Status, Manual Nudges, and Controls
Given a staff user opens the Bundle Prep dashboard When viewing a family bundle Then display per-child completion percentage, count of outstanding items by type, last outreach event, and next scheduled outreach time And allow the user to send a manual nudge by selecting channel(s) with a real-time preview of the resolved template and deep link And manual nudges respect quiet hours unless the user explicitly overrides with a required reason And provide controls to override bundle due date and to cancel or resume automated outreach And update the outreach history and next scheduled outreach immediately after a manual nudge or control change
Templated, Localized Content with Dynamic Lists
Given templates exist for SMS, email, and voice When generating a reminder Then render templates in the caregiver’s preferred language if available (at minimum en-US and es-US), else default to en-US And dynamically insert child names and up to 5 outstanding items; if more than 5, append “and X more” And ensure SMS content fits within 160 characters per segment by truncating the list before the deep link when necessary And for voice, use TTS with SSML and offer “Press 1 to receive the link by SMS” if a mobile number exists And provide a preview in the staff dashboard showing the fully-resolved content per channel prior to sending
Outcomes Reporting and Attribution
Given a practice selects a date range in Reports When viewing Bundle Prep outcomes Then show number of bundles initiated, percent completed before due date, median and p90 time-to-complete from first nudge, and last-touch channel conversion rates And attribute reductions in no-shows to Bundle Prep using delta vs. the prior 3-month baseline with methodology displayed And allow CSV export of the aggregated metrics and underlying bundle-level records And update dashboards within 24 hours of data changes And ensure counts reconcile with source bundle records within ±1% tolerance
EHR/PMS Mapping & Pre-Fill
"As an office manager, I want forms to pre-fill from our system and sync back automatically so that staff avoid manual data entry and errors."
Description

Integrate with leading dental EHR/PMS systems to pull existing household and patient data for pre-fill and to push completed forms, consents, and signatures back as structured data and tamper-evident PDFs. Implement configurable field mappings, patient matching rules (name, DOB, contact), and duplicate detection flows. Support error queues with admin review and retries, sandbox/testing environments, and per-practice configuration. Ensure per-child data segregation and correct attachment to upcoming appointments and patient records.

Acceptance Criteria
Pull Household and Patient Data for Pre-Fill from Supported EHR/PMS
Given a practice is connected to a supported EHR/PMS and a caregiver opens a Bundle Prep link after passing identity verification When the system requests household and patient records for each child in the family Then mapped fields pre-fill for each child with at least 95% fill rate where source data exists, and unmapped/empty fields remain blank without errors And the pre-fill completes within 2 seconds p95 for cached connections and 8 seconds p95 for uncached requests And an audit event is recorded per child with source system, timestamp, and correlation ID And a failure for one child does not block pre-fill for other children, with failed children routed to the error queue
Push Completed Forms and Consents as Structured Data and Tamper-Evident PDFs
Given a caregiver submits Bundle Prep for one or more children When the submission is processed Then structured data is pushed to the EHR/PMS according to the active field mapping with 100% of required fields written or the item placed in the error queue with a validation error And a tamper-evident PDF per child per form is generated with an embedded X.509 digital signature (SHA-256) and RFC 3161 timestamp and uploaded to the patient record And the EHR/PMS receives both the structured payload and the PDF, returning persistent identifiers that are stored on the submission record And transient failures retry up to 3 times with exponential backoff (1m, 5m, 15m) before queuing for admin review And an audit trail entry links submission ID, EHR object IDs, signer identity, and checksum of the PDF
Configurable Field Mappings per Practice
Given a practice admin edits the EHR/PMS field mapping for Bundle Prep When the admin saves a new mapping version Then the mapping is validated for required targets, data types, enumerations, and regex constraints, blocking save on errors with inline messages And the mapping is versioned with metadata (version, editor, timestamp, change note) and can be rolled back to any prior version And pre-fill and push operations immediately use the latest Active version; Draft versions are not applied to production flows And the admin can run a sandbox test using sample patients that shows a side-by-side preview of source values and target fields before activation And mappings are scoped per practice and per vendor instance, without affecting other practices
Patient Matching and Duplicate Detection Flow
Given Bundle Prep needs to attach data to an existing patient in the EHR/PMS When matching using first name + last name (case-insensitive exact), date of birth (exact), and at least one contact method (phone E.164 or email exact) finds a single record Then the patient is auto-selected and used for pre-fill and push And when multiple candidates meet criteria or the match score (fuzzy name threshold >= 0.85) yields more than one candidate Then the flow is marked as Duplicate Review Required and no data is pushed until an admin resolves the match And the admin can confirm the correct patient or create a new patient (if enabled) with all actions fully audited And once resolved, the decision is persisted for the household to avoid re-review within 90 days unless demographics change
Error Queue with Admin Review and Retry
Given a pull or push operation fails due to network, mapping validation, or vendor API error When the failure is detected Then an error item is created within 30 seconds containing correlation ID, patient(s), practice, operation type, error code/message, and redacted payload/response And the system performs up to 3 automatic retries with exponential backoff; after final failure, the item status is Needs Review And an admin can update mappings or fix data, then trigger Retry which replays with the same correlation ID and records outcome And successful retries move the item to Resolved with a link to resulting EHR objects; repeated failures retain full history And admins can filter the queue by vendor, practice, error type, time window, and bulk-retry transient errors
Sandbox Environment Data Flow Parity
Given a practice is connected to a vendor sandbox environment When running end-to-end Bundle Prep with sample patients Then pre-fill and push use sandbox endpoints and credentials exclusively, with no PHI leaving sandbox And validation rules, mappings, and response handling behave identically to production for the same inputs And nightly smoke tests read/write at least 3 representative patients per supported vendor and must pass 100%; failures create Pager/Email alerts within 5 minutes And every audit entry includes the environment flag (sandbox|production) and vendor API version And switching environments is controlled by configuration and feature flags without code changes
Per-Child Data Segregation and Correct Appointment Attachment
Given a household Bundle Prep includes multiple children with upcoming appointments When submissions are processed Then each child’s data is stored, pushed, and attached independently with zero cross-child field leakage (verified by automated tests over 200 multi-child cases) And for each child, attachments target the earliest upcoming appointment within 30 days for the matched patient; if none, attach to the patient record only And if multiple appointments exist on the same day, attach to the earliest start time And the final record contains the EHR patient ID, appointment ID (if any), and form identifiers, all visible in the audit trail And incorrect patient or appointment attachment rate must be 0 in test runs and <0.1% in monitored production over a rolling 30 days
Compliance & End-to-End Audit Trail
"As a compliance officer, I want complete audit trails and secure document packaging so that we can prove consent validity and meet regulatory requirements."
Description

Enforce HIPAA-aligned security controls (encryption in transit/at rest, least-privilege access, retention policies) and ESIGN/UETA-compliant e-signature capture. Maintain immutable audit logs for link creation and delivery, identity verification attempts, content views, edits, signatures, IP/device fingerprints, and content versions. Produce tamper-evident document packages with cryptographic hashes and time-stamps. Provide export tools for compliance reviews and legal requests, with role-based access in the staff portal.

Acceptance Criteria
Audit Trail: Bundle Prep Link Lifecycle (Creation to Submission)
Given a staff user with role "Scheduler" creates and sends a Bundle Prep link, When the link is generated and delivered via SMS and/or email, Then an immutable audit entry is recorded with eventType=create, actorId, actorRole, familyId, linkId, deliveryChannels, messageIds, timestamp (UTC ISO 8601 with ms), requestId, prevHash, and entryHash (SHA-256), And subsequent events (delivery, open, identityVerificationAttempt, tabView, formEdit, signatureStart, signatureComplete, submission) append entries with monotonic sequence numbers and hash chaining. Given the audit log API, When querying by linkId, Then events return in chronological order within 500 ms for up to 500 events and are read-only; any write attempt returns 403 and is logged with actorId and reason. Given distributed services, When timestamps are generated, Then they are NTP-synchronized and differ by no more than ±100 ms and are stored in UTC.
E-Signature Compliance: Parental Consent Across Multiple Children
Given the signer has passed identity verification, When the signer executes an e-signature, Then the system captures signerName, contact (email/phone), disclosure versionId and acceptance timestamp, intent-to-sign checkbox, signature type (typed/drawn), signature image/vector hash, IP address, device fingerprint, UTC timestamp, and binds a signatureId to the document contentHash and signer identity, And a signature certificate PDF is generated and attached to the record. Given a consent allowed once per family, When applying to multiple children, Then signature reuse requires explicit confirmation and logs the mapping of childIds; Given a consent required per child, When signing, Then reuse is blocked and enforced per child. Given the document content version changes prior to submission, When attempting to finalize, Then the signer must re-accept disclosures and re-sign; the prior signature remains in the audit for the previous version but is not applied to the new version.
Tamper-Evident Package: Cryptographic Sealing and Versioning
Given a caregiver submits the Bundle Prep packet, When the final package is generated, Then the system produces a PDF/A bundle containing all forms/consents and an audit appendix, computes a SHA-256 hash, obtains an RFC 3161 trusted timestamp, embeds both in file metadata and a seal page, stores the hash separately, and records the package entryHash in the audit log. When any package is downloaded, Then the presented file hash matches the stored hash; a mismatch blocks download and logs a tamper alert. Given a post-submission amendment flow, When edits are made, Then a new immutable version is created with a new hash and timestamp; prior versions remain unchanged, linked, and accessible to authorized roles only.
Compliance Export: Legal/Regulatory Package with RBAC
Given a user with role "Compliance Officer" or "Practice Owner" completes 2FA, When they request an export by linkId or date range, Then within 2 minutes a ZIP is generated containing the final package PDF, raw form data JSON, full audit log (JSON and CSV), signature certificates, hash manifest, and an access report, And the download link is single-use, tied to that user, and expires in 24 hours. Given a user without the required role, When requesting an export, Then the system returns 403 Forbidden with error code RBAC_EXPORT_DENIED and logs actorId, IP, and reason. Given an export is generated, When it is accessed or expires, Then each event is recorded with userId, IP, device fingerprint, timestamp, and outcome (downloaded/expired).
Retention and Purge: PHI Data with Hash Registry
Given an organization retention policy of N days, When a package reaches expiry, Then PHI documents and raw data are purged within 24 hours, a non-PHI hash registry record (linkId, finalHash, createdAt, purgedAt) is retained, and a purge event is logged. When purged content is requested by any user, Then the API returns 410 Gone with error code CONTENT_PURGED and no PHI payload. Given backups exist, When retention executes, Then purge is propagated to backups within 30 days and the backup purge completion is auditable. Given a litigation hold is applied, When the item reaches its retention date, Then purge is skipped, the hold (reason, actorId, timestamp) is logged, and exports remain available only to Compliance Officer and Practice Owner roles.
Least-Privilege and Encryption Enforcement
Given defined roles (Scheduler, Hygienist, Dentist, Office Manager, Compliance Officer), When accessing audit logs or document packages, Then only authorized roles can view PHI, non-authorized roles see masked PII fields, 2FA is required for Compliance Officer and Practice Owner, and every access event is logged with userId, IP, device fingerprint, and timestamp. When data is transmitted between clients and services, Then TLS 1.2+ with strong ciphers is enforced and HSTS is enabled; When data is at rest, Then AES-256 encryption is configured for databases and object storage; encryption keys are in a managed KMS with rotation at least every 90 days and access limited by IAM. Given an external TLS scan, When endpoints are evaluated, Then they achieve an A grade on an SSL Labs equivalent test and no plaintext endpoints are exposed.

Bundle Waitlist

Tracks multi-slot openings and recommends family candidates that can fill adjacent times in one move. Offers parent-friendly swap options that keep siblings together and auto-updates the calendar on confirmation. Cancellations turn into efficiently filled blocks, protecting revenue and reducing scramble.

Requirements

Adjacent Slot Bundling Engine
"As an office manager, I want the system to automatically detect multi-slot openings so that I can quickly place families together without manual calendar scanning."
Description

Continuously monitors provider calendars to detect contiguous openings that can accommodate multi-appointment family bundles. Normalizes appointment lengths by type (e.g., hygiene, exam) and provider constraints, assembling candidate blocks that keep siblings adjacent with minimal gaps. Respects clinic hours, operatory/equipment availability, provider assignments, and buffer rules. Exposes a service that emits bundle opportunities with block size, time window, provider/room map, and expiration. Supports real-time updates on cancellations/reschedules and prevents race conditions via optimistic locking, short hold windows, and idempotent operations.

Acceptance Criteria
Contiguous Block Detection
Given a provider calendar with free slots 10:00-10:30 and 10:30-11:00 and monitoring enabled When the engine processes the schedule update Then it emits a contiguous block opportunity spanning 10:00-11:00 with block_size=2 Given a single 60-minute free slot and scheduling_increment=30 minutes When the engine normalizes the slot into adjacent units Then it emits a block_size=2 contiguous opportunity of two 30-minute units Given any availability change event (create, update, cancel) When it is applied to the calendar store Then new or updated contiguous blocks are identified and persisted within 2 seconds
Appointment Length Normalization
Given appointment types Hygiene=30m and Exam=20m and provider buffer_after_each=5m and scheduling_increment=5m When building bundle candidates Then normalized durations are Hygiene=35m and Exam=25m and each is rounded up to the 5m increment Given a provider with scheduling_increment=10m and an appointment of 23m base + 4m buffer When normalizing Then the normalized duration is 30m and is used for block sizing and adjacency Given appointment types requiring pre/post buffers per provider policy When normalizing Then total bundle length includes all required buffers and does not violate provider constraints
Minimal-Gap Sibling Bundle Assembly
Given two siblings needing back-to-back 30m visits and available slots 09:00-09:30 and 09:30-10:00 on eligible providers/rooms When evaluating bundles Then the engine assembles a candidate with max_gap=0 between siblings (excluding required buffers) and marks it valid Given adjacent slots with a gap exceeding configured max_gap=5m When evaluating bundles Then the candidate is rejected and not emitted Given multiple valid bundles for the same family When ranking opportunities Then the engine orders them by ascending total idle_gap and earliest start_time
Resource and Hours Compliance
Given clinic hours 08:00-17:00 local time When generating opportunities Then all block start and end times (including buffers) fall within clinic hours Given operatory rooms and equipment with existing reservations When mapping provider_room for a bundle Then no overlap or double-booking occurs for room_id or equipment_id across the block Given any required resource is unavailable for any unit of the block When evaluating the candidate Then the opportunity is not emitted
Opportunity Emission and Expiration
Given a detected bundle opportunity When emitting via the service Then the payload includes block_id (UUID), block_size (int), start_time, end_time, time_window, provider_room_map, expiration_ts, calendar_version, and created_at Given detection of a new opportunity When emitted Then consumers receive the event within 1 second and expiration_ts = created_at + hold_window (default 5 minutes) unless overridden by configuration Given expiration_ts is reached without a hold When processed by the engine Then the opportunity transitions to expired and is not reservable
Real-time Updates Handling
Given a cancellation that frees slots on a provider calendar When received by the engine Then new or updated bundle opportunities reflecting the new contiguous blocks are emitted within 2 seconds Given a reschedule or new booking overlaps an existing opportunity When processed Then overlapping opportunities are revoked and an event with expiration_reason=conflict is emitted Given an already-emitted opportunity is updated due to calendar change When re-emitted Then block_id remains constant and calendar_version increments by 1
Concurrency Control and Idempotency
Given two clients attempt to hold the same block with the same calendar_version When processed concurrently Then only one hold succeeds and the other receives a conflict without creating a duplicate hold Given a client retries a hold request with the same idempotency_key within 2 minutes When processed by the service Then the response is identical to the original and no additional state changes occur Given a hold is granted on an opportunity When the hold_window (default 5 minutes) elapses without confirmation Then the hold is automatically released and the opportunity becomes available or expires per policy
Family Linkage & Eligibility Matching
"As a scheduler, I want the system to match open blocks with eligible families so that we fill time with the right visit types and avoid rework."
Description

Leverages PMS synchronization to identify household relationships, guardians, and sibling groupings, pairing them with recall status, due appointment types, insurance constraints, and provider preferences. Applies eligibility rules so only compatible visit types are bundled, honoring age-specific durations, sedation/equipment needs, and provider or operatory requirements. Maps guardian contacts and consent flags, supports time-of-day preferences, lead-time thresholds, and travel constraints. Produces a filtered, validated list of eligible family candidates per detected block.

Acceptance Criteria
Sync Household & Guardianship from PMS
Given the PMS contains households with guardians, siblings, and consent flags When the nightly full sync runs Then SmileCue creates/updates household records linking guardians and dependents with correct relationship types and effective dates Given the PMS updates guardianship or sibling membership When the delta sync runs Then SmileCue reflects changes within 5 minutes and preserves prior relationships as inactive with timestamps Given a minor has consent=false and no linked guardian with consent=true When generating eligible candidates for a block Then the minor is excluded with reason code CONSENT_REQUIRED
Eligibility Filtering for Multi-Slot Family Bundle
Given a detected continuous block of adjacent slots with defined operatory and resource availability When evaluating a family group for bundling Then only combinations whose total scheduled duration exactly equals the block length are considered eligible Given appointment types have age-specific durations and equipment/sedation needs When matching members to the block Then only candidates whose requirements can be satisfied by the block's operatory and resources are included; others are excluded with resource-specific reason codes Given insurance rules and recall/due status per member When validating appointment types Then only covered and currently due appointment types are included; non-covered or not-due are excluded with INSURANCE_NOT_COVERED or NOT_DUE
Provider and Operatory Preference Matching
Given each patient has provider preferences (preferred and acceptable) When assigning providers within the block Then only providers in the acceptable list are used; if preferred is unavailable but acceptable exists, the bundle remains eligible; otherwise exclude with PVD_UNAVAILABLE Given procedures require specific operatories When matching to a block Then only blocks in operatories meeting those requirements are eligible; otherwise exclude with OP_REQ_MISMATCH Given siblings require mutually exclusive providers When the conflict cannot be resolved within the same block Then exclude the bundle with PVD_CONFLICT and do not partially schedule
Time-of-Day, Lead-Time, and Travel Constraints
Given a guardian's time-of-day preferences When evaluating a block Then the bundle is eligible only if the block start falls within at least one preferred window; otherwise exclude with TIME_PREF_MISMATCH Given lead-time thresholds per member or appointment type When matching to near-term blocks Then exclude blocks that begin sooner than the configured lead time with reason LEAD_TIME Given a guardian has existing appointments before/after the proposed bundle and a required travel buffer When validating schedule fit Then ensure buffer >= required minutes; otherwise exclude with TRAVEL_BUFFER
Guardian Contact Selection and Consent Enforcement
Given multiple guardian contacts with priorities and communication preferences When producing a candidate bundle Then select the primary contact by priority and permitted channel; if unreachable, apply fallback in order until a valid contact is found Given a procedure requires explicit consent When validating eligibility Then include only if consent flag is true and not expired; otherwise exclude with CONSENT_MISSING Given the guardian confirms the proposed bundle When confirmation is received Then auto-update the calendar and create all linked appointments atomically; on failure, roll back and notify with a single error code
Candidate List Output per Detected Block
Given processing for a detected block completes When generating output Then return a list of eligible family bundles including household ID, member IDs, appointment types, assigned provider, operatory, start/end times, and eligibility reason codes Given some families are ineligible When output is generated Then include an exclusion list with per-member failure reasons and top-level bundle exclusion code Given multiple eligible bundles exist When ranking candidates Then sort by highest fill rate, preference fit score, and soonest due date; break ties by proximity to preferred time and then by shortest total idle time
Performance and Auditability
Given a block with up to 50 candidate families When eligibility evaluation runs Then processing completes within 2 seconds at P95 and 5 seconds at P99 Given any eligibility decision is made When logging Then create an immutable audit entry with timestamp, inputs, rule set version, rules applied, and outcomes Given a rule configuration change is deployed When subsequent matches occur Then decisions reference the correct rule set version and previous decisions remain replayable with their original version
Bundle Ranking & Fairness Rules
"As a practice owner, I want outreach to target the best candidates fairly so that we maximize confirmations without spamming families."
Description

Implements a configurable scoring model that prioritizes candidates by likelihood to confirm (historical responsiveness, lead time), revenue impact, clinical urgency, and fairness rotation to avoid over-contacting the same families. Enforces contact frequency caps, quiet hours, opt-out status, and Do Not Disturb windows. Provides deterministic tie-breaking, reason codes, and auditability of scores. Supports A/B testing of weights and emits metrics for fill rate, time-to-fill, and outreach volume.

Acceptance Criteria
Weighted Scoring Across Likelihood, Revenue, Urgency, and Bundle Fit
Given a scoring config with weights for responsiveness, lead_time, revenue_impact, clinical_urgency, fairness_rotation, and bundle_fit and a candidate family with corresponding attributes When the ranking engine computes scores Then the total score equals the sum of (normalized_component_value × configured_weight) for all components and is normalized to a 0-100 scale And changing a single component weight produces a proportional change in total score while other inputs remain constant And scores are identical across repeated runs with the same inputs and config version And candidates missing a component receive the defined neutral default for that component as per config
Fairness Rotation and Contact Frequency Caps Enforcement
Given caps daily=N, weekly=M, monthly=K and a family’s outreach history within those windows When preparing the ranked outreach list Then any family whose next outreach would exceed a cap is excluded with reason 'FrequencyCap' And families contacted more recently than the configured rotation interval are de-prioritized by applying the fairness_rotation penalty specified in config And the cap applies across channels (SMS, email, voice) and across siblings within the same family bundle And all inclusions/exclusions are reflected in the audit log
Quiet Hours, Opt-Out, and Do Not Disturb Compliance
Given practice and patient time zones, quiet_hours, and family-level DoNotDisturb windows and opt-out flags per channel When generating eligible outreach windows and the ranked list Then candidates in a quiet hour or DND window are excluded with reason 'QuietHours' or 'DND' and a next_eligible_at timestamp is computed And any channel marked opted-out is not used and is recorded with reason 'OptOut' And no message is queued or sent during disallowed times And compliance decisions are deterministic and auditable
Deterministic Tie-Breaking for Equal Scores
Given two or more candidates with equal total scores after rounding rules When producing the final order Then the order is resolved deterministically by applying tie-breakers in this priority: earliest last_contacted_at, higher revenue_impact, earlier waitlist_joined_at, then ascending family_id And repeated runs with the same inputs yield the same order And the applied tie-breaker and compared values are recorded per candidate
Score Auditability and Reason Codes
Given a ranking run for one opening or bundled openings When the engine completes scoring Then for each candidate an audit record is stored with timestamp, config_version, experiment_arm, input attributes, normalized component values, weights, total score, eligibility flags, and any exclusion reason codes And audit records are immutable and retained for at least 90 days And an authorized user can retrieve an audit record by run_id or family_id within 2 seconds P95
A/B Testing of Scoring Weights and Stable Assignment
Given an active experiment with control and variant weight sets and a 50/50 split When a ranking request is processed Then the request is assigned to an arm using a stable hash of practice_id + family_id + experiment_id And the selected arm’s weights are used for scoring and persisted in the audit record And assignment remains stable across retries within the experiment window And disabling the experiment routes all traffic to control within 1 minute
Metrics Emission for Fill Rate, Time-to-Fill, and Outreach Volume
Given cancellations and subsequent fills are processed by the waitlist When a block is filled or expires Then metrics events are emitted with practice_id, opening_id, experiment_arm, fill_rate numerator/denominator, time_to_fill_ms, outreach_attempts_count, outreach_sent_count, outreach_confirmations_count, and timestamp And time_to_fill_ms is measured from cancellation_at to confirmation_received_at And metrics are delivered to the analytics sink within 60 seconds P95 and have a schema version
Parent-Friendly Swap Options (SMS/Web)
"As a parent, I want simple swap options that keep my kids together so that scheduling is convenient and I make fewer trips."
Description

Delivers mobile-first flows that present parents with adjacent-time options, including swapping an existing single appointment into a new bundled block that keeps siblings together. Provides one-click deep links from SMS/email to a secure web view with HIPAA-compliant masking, showing times, provider roles, total visit duration, and any prep notes. Validates holds in real time and refreshes options if availability changes. Localizes content, supports English/Spanish, and meets accessibility standards (WCAG AA).

Acceptance Criteria
Secure Deep Link Opens Masked Web View (SMS/Email)
Given a parent receives an SMS or email with a one-click deep link for swap options When they tap/click the link on a mobile device or desktop Then a secure web view loads over HTTPS with no PHI in the URL or page title And the session token is single-use and expires after 30 minutes or on first successful open, whichever comes first And patient identifiers are masked to first name and last initial (e.g., "Ava R.") And the view displays available times, provider roles, total visit duration, and any prep notes for each option And the layout is mobile-first responsive at 320–768 px without horizontal scroll
Show Adjacent-Time Bundled Options for Siblings
Given the practice has a configurable adjacency window (default 0–10 minutes between back-to-back slots) And a family has two or more siblings eligible for bundling When the parent opens the swap options web view Then the system lists bundled options that keep siblings together within the configured adjacency window And options are sorted by soonest date/time, then by shortest total visit duration And each option clearly shows start/end times for each child, provider role(s), total combined duration, and prep notes And if fewer than one option exists, a friendly message explains no bundled matches and offers to keep the current appointments
Confirm Swap from Single Appointment into Bundled Block
Given a child has an existing single appointment on the schedule And the parent selects a bundled option that overlaps or replaces the existing time When the parent taps Confirm Swap Then the system performs an atomic transaction that books all new bundled slots and releases the original slot(s) only on success And calendar conflicts or double-booking are prevented by server-side checks And on success, the parent receives an on-screen confirmation plus SMS/email confirmation within 60 seconds And the original appointment is canceled with linked reason "Swapped to Bundle" and the new bundled appointments reflect the family group
Real-Time Hold Validation and Dynamic Refresh
Given bundled options are displayed to the parent When the parent selects an option Then the system places a real-time hold on the underlying slots for 5 minutes and shows a countdown timer And if any slot becomes unavailable before confirmation, the hold fails, the UI refreshes within 3 seconds, and an informative message is shown without losing context And the list auto-refreshes when availability changes, no stale options can be confirmed, and disabled options are visually indicated
Localization English/Spanish and Preference Detection
Given the patient's preferred language is stored as English or Spanish And the deep link may include a language parameter When the parent opens the web view Then the UI language is set to the link parameter if present; otherwise to the stored preference; otherwise to device locale And all static and dynamic copy, buttons, error messages, date/time formats, and prep notes render in the selected language And the parent can toggle language between English and Spanish without losing state And missing translations fall back to English with no placeholder keys visible
Accessibility WCAG 2.1 AA Compliance in Swap Flow
Given a parent using screen reader or keyboard-only navigation accesses the web view When they navigate through the swap options and confirmation Then all interactive elements are reachable via keyboard in a logical focus order and have visible focus indicators And all content meets minimum color contrast of 4.5:1; touch targets are at least 44x44 px; and no critical information relies solely on color And form fields, buttons, and dynamic updates have appropriate labels, roles, names, and ARIA live regions for screen readers And the page is usable with system text scaling up to 200% without loss of functionality or content overlap
Calendar Sync, Atomic Update, and HIPAA Audit
Given the parent confirms a bundled swap When the booking completes Then the practice calendar is updated within 10 seconds, reflecting the new bundled block and released original slot(s) And an immutable audit log records timestamp, actor (parent link), affected appointment IDs, before/after times, and reason "Swapped to Bundle" with masked identifiers And downstream integrations/webhooks receive an event payload within 30 seconds And on any failure to update the calendar, all changes roll back and the parent sees a clear retry option without creating duplicates
One-Tap Bundle Confirmation & Real-Time Calendar Update
"As a front desk coordinator, I want bundle confirmations to automatically update the schedule so that I don’t have to manually adjust multiple appointments."
Description

Upon guardian confirmation, atomically books all included appointments across providers/rooms, cancels superseded slots, and triggers confirmation and pre-visit reminder flows. Integrates with PMS write-back APIs with idempotency keys and rollback to avoid partial bookings. Updates patient and guardian records with visit notes and maintains consistent appointment statuses. Emits events for analytics and updates waitlist states, ensuring calendar and communications remain in sync.

Acceptance Criteria
Atomic Multi-Appointment Booking Across Providers
- Given a guardian receives a bundle offer with N adjacent slots across providers/rooms and taps "Confirm" once When the system validates availability for all N slots at confirmation time Then it creates all N appointments in a single atomic transaction and returns success with a bundleId and N appointmentIds - And no appointment is created if any slot is unavailable or any creation step fails - And the total confirmation latency (tap to success response) is <= 3 seconds at p95 for internal calendar write, excluding PMS write-back
Idempotent One-Tap Confirmation
- Given the same bundle confirmation is submitted multiple times with the same idempotencyKey within 24 hours When processing duplicates Then exactly one bundle booking exists and all duplicate requests return 200 with the original bundleId and appointmentIds - And no duplicate communications, events, or waitlist changes are produced by duplicates - And idempotency keys are stored with a 24-hour TTL and are safely reusable after expiry without affecting prior bookings
Transaction Rollback on Partial Failure
- Given any step in booking or PMS write-back fails or times out (>10 seconds for PMS response) When processing the bundle confirmation Then all created appointments and holds for this bundle are fully rolled back within 30 seconds and the original availability state is restored - And the guardian is notified of the failure with a retry option, and no confirmation/reminder messages are sent - And an error event is emitted with idempotencyKey, failureReason, and correlationId for diagnostics
Real-Time Calendar Sync With PMS
- Given a successful bundle confirmation When internal calendar write completes Then all N appointments are visible on the SmileCue calendar within 1 second p95 with status "Booked" - And PMS write-back completes with HTTP 2xx and externalIds stored within 10 seconds p95 - And there is no status divergence between SmileCue and PMS at T+60 seconds (Booked/Cancelled/Rescheduled)
Superseded Slot Cancellation and Status Consistency
- Given the booked bundle supersedes existing appointments for any involved patients When the bundle is confirmed Then superseded appointments are cancelled with reason "Bundled Rebook" and freed capacity reflected on calendars and PMS within 10 seconds p95 - And no orphaned holds or double bookings remain for the involved providers/rooms - And affected patients/guardians receive a single consolidated notice describing the cancellations and new bundle times
Post-Confirmation Communications and Record Updates
- Given a successful bundle confirmation When communications are triggered Then one confirmation message per bundle is enqueued to the guardian within 15 seconds p95 via the selected channels (SMS/email/voice) - And pre-visit reminder jobs are scheduled per appointment according to practice templates without duplicates - And patient and guardian records are updated: upcomingAppointments list, guardian linkage to all appointments, and a visit-notes stub per appointment with bundleId
Waitlist and Analytics Event Updates
- Given a successful bundle confirmation sourced from the Bundle Waitlist When state is updated Then the selected family entries are removed from the relevant waitlists and overlapping holds for those times are released - And analytics events "bundle_booked" and "waitlist_filled" are emitted within 5 seconds p95 containing bundleId, appointmentIds, practiceId, patientIds, guardianId, and idempotencyKey - And the bundle offer is marked as "filled" and is not re-sent to the same guardian
Cancellation-Triggered Outreach Automation
"As a hygienist, I want cancellations to trigger smart outreach automatically so that my schedule stays full without constant phone calls."
Description

Transforms cancellations into bundle opportunities by immediately evaluating adjacent openings and launching adaptive SMS/email/voice outreach to top-ranked families. Uses compliant templates that minimize PHI, include secure links, and honor communication preferences, consent, and quiet hours. Implements retries with escalating channels, downgrades to single-patient fill if no family accepts within the hold window, and alerts staff only when manual intervention is needed.

Acceptance Criteria
Immediate Outreach on Cancellation
Given a patient cancellation is recorded and the calendar shows an adjacent opening When the cancellation event is saved Then the system evaluates adjacent openings for bundle opportunities within 10 seconds And ranks top family candidates using the configured scoring rules And sends the first outreach via the highest-ranked allowed channel within 60 seconds And places a temporary hold on the candidate block equal to the configured hold window And does not notify staff at this stage
Family Bundle Offer and Hold Window
Given a multi-slot (>=2) contiguous opening exists When outreach is sent to an eligible family with matching availability Then the offer bundles the contiguous times into a single action And the block is reserved exclusively for the family during the configured hold window And acceptance via the secure link books all bundled appointments atomically and updates the calendar within 5 seconds And expiration of the hold immediately releases the block
Template Compliance and Secure Links
Given SMS, email, and voice templates are configured When an outreach message is rendered Then no PHI beyond practice name, date/time window, and action instructions is included And patient names, diagnoses, and provider names are omitted And the message contains a single-use HTTPS link with a time-limited token that expires at hold-window end And link access enforces recipient verification per configuration And all message payloads and tokens are stored and transmitted using HIPAA-compliant encryption
Preferences, Consent, and Quiet Hours
Given each contact has recorded consent, channel preferences, and practice quiet hours are defined When selecting channels and scheduling outreach Then only channels with active consent are used And SMS/voice are suppressed during quiet hours; deferred to the next allowable window And email is deferred if disallowed during quiet hours per configuration And contacts with no allowable channels are skipped for this opening And inbound opt-out keywords immediately halt further SMS to that number
Escalating Retries and Channel Fallbacks
Given no response is received after the initial outreach and the hold window has remaining time When retry logic executes Then up to the configured maximum retries are attempted within the hold window across distinct channels in preference order And a minimum retry interval (>= configured minutes) is enforced between attempts And retries respect consent and quiet hours And retries cease immediately upon acceptance, decline, or opt-out And no duplicate message is sent to the same channel within the throttle window
Downgrade to Single-Patient Fill
Given the family hold window expires without acceptance When the reservation is released Then the system targets single-patient candidates to fill remaining slots within 30 seconds And sends outreach governed by the same compliance and retry rules And previously contacted family members are not re-contacted for the same opening And any filled slot immediately updates the calendar and leaves remaining slots open
Staff Notification Only on Exceptions
Given automation processed a cancellation event When all automated options are exhausted without filling the block, an error occurs, or a recipient requests human assistance Then a single actionable alert is sent to staff with a summary, links to candidate details, and next-best actions And no staff alert is sent if the block is auto-filled And the alert is delivered within 60 seconds of the triggering condition And the activity feed logs the automation outcome and alert status
Audit Logging & Access Controls for Bundled Scheduling
"As a compliance officer, I want detailed logs and permissions for bundled scheduling so that we meet HIPAA requirements and can investigate issues."
Description

Captures end-to-end audit trails for bundle detection, ranking decisions, holds, confirmations, swaps, and cancellations, including initiator identity, timestamps, and before/after state. Enforces role-based access controls so only authorized staff can view PHI and override holds. Provides exportable logs for HIPAA audits, configurable retention policies, and an admin dashboard to review changes and adjust settings with tracked history.

Acceptance Criteria
Audit Trail for Bundle Detection and Ranking
Given a multi-slot opening is detected by the system When bundle detection and candidate ranking run Then an immutable audit record is created with event_type="bundle_detected", bundle_id, slot_ids, initiator="system", timestamp in UTC ISO-8601 with millisecond precision, correlation_id, ranking_inputs summary, and ranked_candidates with scores And the audit record excludes message contents and stores only patient_id references with names masked And any attempt to modify or delete the audit record via UI or API returns 405 and is logged as event_type="audit_write_blocked"
Audit Logging for Holds, Confirmations, Swaps, and Cancellations
Given an authorized user performs hold, confirmation, swap, and cancellation actions on a bundled scheduling candidate When each action is executed (success or failure) Then an audit record is created per action with event_type in {"hold_placed","hold_expired","hold_overridden","confirmation_accepted","swap_proposed","swap_accepted","swap_declined","cancellation_processed","action_failed"}, actor_user_id, actor_role, ip_address, user_agent, timestamp, correlation_id, before_state, after_state, and error_code when applicable And records for a correlation_id are returned in chronological order by timestamp And retrieving by correlation_id returns exactly the expected count for the test case
Role-Based Access to PHI and Hold Overrides
Given users with roles Admin, Office Manager, Dentist, Hygienist, Front Desk, and Auditor When they view audit logs or exports Then Admin and Office Manager see full PHI while other roles see masked patient_name (first letter + asterisks), phone (last 4), email (first 3 + '***' + domain), and no message bodies And attempts by non-privileged roles to view unmasked PHI are blocked with 403 and logged as event_type="access_denied" When attempting to override a hold Then only Admin and Office Manager can execute the override after providing a reason of at least 10 characters and confirming; other roles receive 403 And all override attempts (success or denied) are logged with actor, timestamp, reason, and affected identifiers
Exportable Audit Logs for HIPAA Audits
Given an Admin filters audit logs by date range, event types, user, patient_id, and bundle_id When they request an export in CSV and JSON Then the system generates files containing only the filtered records with headers/fields matching the audit schema, signs each file with a SHA-256 checksum (and detached signature), provides a TLS-protected download link that expires in 15 minutes, and logs the export event And the export completes within 60 seconds for up to 100,000 records And checksum verification of the downloaded file matches; otherwise the export is marked failed and logged with error details
Configurable Retention Policies with Legal Hold
Given the default retention window is 6 years and is configurable between 3 and 7 years by an Admin When the Admin updates the retention window and creates legal holds for specific patient_id, correlation_id, or date ranges Then the new settings are saved, versioned, and logged with old_value and new_value, and the next scheduled purge time is displayed And the nightly purge at 02:00 UTC deletes only records older than the retention window that are not under legal hold, logs a purge summary (deleted_count, skipped_count, duration), and preserves held records And removing a legal hold makes affected records eligible for deletion on the next purge cycle
Admin Dashboard Change Review and Settings History
Given an Admin opens the audit dashboard When they filter by date range, event type, user_id, patient_id, bundle_id, and correlation_id Then results are paginated, sortable by timestamp, and each record shows a before/after diff view And time display can be toggled between UTC and the user's local timezone When the Admin changes a setting (e.g., retention window or redaction rules) Then the change requires re-authentication with MFA, is applied, and a settings_change audit record is created capturing who, when, old_value, new_value, and a reason And clicking Revert restores the prior value and logs a linked settings_change event And all dashboard views enforce RBAC masking for non-privileged roles

FitRank Match

AI ranks and sequences the best-fit waitlisted patients for each cancellation, factoring appointment length, provider/room constraints, insurance/pre-auth status, patient reliability, language/channel preference, and consent. The right person gets the first offer—fills faster, with fewer back-and-forths and higher show rates.

Requirements

Real-time Cancellation Triggering
"As an office manager, I want cancelled slots to automatically trigger a ranked list of candidates so that I can fill openings quickly without manual searches."
Description

On appointment cancellation or reschedule, automatically compile a candidate pool from the waitlist in under 30 seconds, factoring appointment type and length, provider and operatory availability, and schedule constraints. Pulls required data from SmileCue’s scheduling integrations and normalizes inputs for downstream ranking. Ensures PHI is handled in-memory and encrypted at rest, and sets the context for FitRank Match processing. Expected outcome: immediate candidate generation without manual intervention, enabling faster fill times.

Acceptance Criteria
Compile Candidate Pool Within 30 Seconds on Cancellation
Given an appointment is canceled via an integrated scheduler or SmileCue UI When the cancellation event is received by SmileCue Then the candidate pool is compiled within 30 seconds of event receipt And the pool considers appointment type, required duration, provider, operatory, and schedule constraints And processing status is recorded as "compiled" with correlationId and timestamp And no manual action is required to initiate compilation
Accurate Constraint Filtering for Type, Length, Provider, Operatory
Given a waitlist containing eligible and ineligible patients When compiling the candidate pool for a specific canceled slot Then 100% of included candidates meet appointment type, required duration, provider, operatory, and schedule constraints And 0 candidates violating these constraints are included And each excluded waitlist record is annotated with a machine-readable exclusion reason
Scheduling Integration Data Pull and Normalization Contract
Given scheduler integration credentials are valid When a cancellation or reschedule event occurs Then appointment type, duration, provider, operatory, location, startTime, endTime, and timezone are retrieved from the scheduler And fields are normalized into the canonical schema with required keys: appointmentTypeId, durationMinutes, providerId, operatoryId, locationId, startTime, endTime, timezone And if any required field is missing or unmapped, compilation is aborted and an error event with non-PHI detail and correlationId is logged and alerted And no context is emitted to downstream services for aborted compilations
PHI Protection: In-Memory Processing and Encrypted-at-Rest
Given candidate compilation is running When handling appointment and patient-linked data Then PHI is processed in-memory only and never written to logs, metrics, traces, or non-encrypted storage And any at-rest storage (e.g., caches, queues, job state) is encrypted using a FIPS-validated module And logs/metrics/traces contain only pseudonymous identifiers and redact PHI fields And automated scans of logs/metrics for PHI patterns report zero findings for processed events
Idempotent and Concurrency-Safe Trigger Handling
Given duplicate or out-of-order cancellation/reschedule events may be received When events with the same external eventId are processed Then at most one candidate pool is created per unique eventId And concurrent events for overlapping provider/operatory resources are serialized with locks to avoid race conditions And retries due to transient failures do not create duplicate pools or downstream emissions
FitRank Context Emission Post-Compile
Given a candidate pool has been successfully compiled When handing off to FitRank Match Then a context payload with normalized appointment fields and candidate references is emitted to the ranking queue/topic within 2 seconds of compile completion And the payload validates against the FitRankContext schema (current version) and includes correlationId and traceId And downstream acknowledgement is recorded; on NACK or timeout, up to 3 retries with exponential backoff are performed
Reschedule Event Support and Slot Reconciliation
Given an appointment is rescheduled, freeing the original time slot When the reschedule event is received Then a candidate pool is compiled for the freed slot using the same constraints as cancellation And no candidate pool is compiled for the newly booked slot And the audit log links the pool to the original appointmentId and the reschedule eventId
Multi-factor Ranking Engine
"As a scheduling coordinator, I want the system to rank waitlisted patients using multiple factors so that the best-fit patient receives the first offer."
Description

Compute a weighted score for each eligible waitlisted patient using appointment fit, provider/room constraints, insurance eligibility and pre-auth status, patient reliability history, language and channel preferences, and consent status. Supports configurable weights per practice and sensible defaults, handles missing data gracefully, and provides deterministic tie-breaking. Exposes an API returning top-N candidates with scores and reason codes.

Acceptance Criteria
Eligibility Pre-Filter for Waitlist Candidates
Given a cancellation with provider_id, appointment_type_id, and start/end time When the engine evaluates the practice's waitlist Then candidates lacking required outreach consent for any supported channel are excluded from scoring Given insurance eligibility and pre-authorization data When evaluating eligibility Then candidates with denied insurance or denied pre-authorization for the appointment_type are excluded; candidates with pending or unknown pre-authorization remain eligible for scoring Given practice association and blocklist status When evaluating eligibility Then only candidates belonging to the practice and not blocklisted are eligible for scoring
Practice-Specific Weights and Sensible Defaults
Given no custom weights exist for a practice When ranking Then the system applies default weights for factors: appointment_fit, provider_room_fit, insurance_preauth, reliability, language_match, channel_match Given a practice submits a weight configuration where each factor weight is within [0,1] and the sum of all weights equals 1.0 (±0.01 tolerance) When saving Then the configuration is accepted and immediately used for subsequent rankings in that practice Given a practice submits a weight configuration with missing required factors, unknown extra factors, any negative weight, or a total weight sum outside 1.0±0.01 When saving Then the request is rejected with a validation error and the last valid configuration remains active
Weighted Scoring and Reason Codes
Given eligible candidates and an active weight configuration When ranking Then each candidate's final_score equals the sum over factors of (weight × sub_score), rounded to 3 decimals Then sub_scores are computed as: appointment_fit ∈ [0,1] based on duration alignment and lead time; provider_room_fit ∈ [0,1] based on provider availability and room/equipment fit; insurance_preauth ∈ {1,0.5,0.3} for eligible, unknown, pending respectively; reliability ∈ [0,1] from historical confirmations/no-shows; language_match ∈ {1,0}; channel_match ∈ {1,0} when the preferred channel with consent is available Then the returned list is strictly ordered by final_score descending Then each candidate includes reason_codes where each entry contains factor_name, input_value, weight, sub_score, and weighted_contribution
Graceful Handling of Missing Factor Data
Given a candidate is missing non-eligibility factor data (e.g., no reliability history) When ranking Then the engine imputes a neutral sub_score of 0.5 for that factor and adds a reason code "imputed" with the factor_name Given multiple factors are missing When ranking Then scoring proceeds without error and all available factors are used; a final_score is still computed and returned Given eligibility data (consent) is missing or pre-authorization is contradictory/unknown with denied indicators When ranking Then the candidate is excluded with reason "ineligible_missing_or_conflicting_eligibility"
Deterministic Tie-Breaking for Equal Scores
Given two or more candidates have identical final_score to 3 decimals When ranking Then ordering is determined by this fixed sequence: higher reliability sub_score, earlier waitlist_created_at timestamp, lower patient_id (lexicographic) Given the same request is executed multiple times with unchanged inputs When ranking Then the order of tied candidates is identical across runs Then a reason code "tie_break_applied" is included for any candidate whose position was decided by tie-breakers
Top-N Candidates API Response Contract
Given a request POST /api/v1/rankings/top with JSON body { cancellation_id, top_n } and top_n ∈ [1,100] When processed Then the response status is 200 and contains up to top_n candidates ordered by rank starting at 1, or an empty list if none are eligible Then each candidate item includes patient_id, rank, final_score, and reason_codes[] Given top_n ≤ 0 or > 100 or cancellation_id is missing/invalid When calling the API Then the response is 400 with a descriptive validation error and no ranking is computed
Consent-Aware Omnichannel Offer Orchestration
"As a patient communications coordinator, I want offers to be sent via the patient’s preferred, consented channel with automatic timeouts so that openings are filled quickly and compliantly."
Description

Send time-bound offers to the top-ranked patient through their preferred, consented channel (SMS, email, voice) with automatic fallback to secondary channels. Holds the slot for a configurable window, processes responses (confirm, decline, no response), and auto-advances to the next candidate when needed. Includes rate limiting, quiet hours, opt-out enforcement, and localization by language. Reduces back-and-forth and increases show rates.

Acceptance Criteria
Primary Consented Channel Offer Dispatch
Given a cancellation creates an open slot and a ranked top candidate exists And the candidate has an active consented preferred channel And current time is outside configured quiet hours And per-patient and per-practice rate limits are not exceeded When the system dispatches the offer Then the offer is sent via the preferred consented channel within 60 seconds of slot creation And the message contains slot date/time, provider, location, and clear confirm/decline instructions And a hold is placed on the slot for the configured window (e.g., 15 minutes) starting at dispatch time And the hold expiration timestamp and dispatch metadata are recorded in the audit log
Automatic Fallback to Secondary Consented Channel
Given an offer was attempted on the preferred channel And the patient has at least one additional consented channel When the preferred channel delivery hard-fails (e.g., carrier bounce, email bounce) Then the system sends the same offer to the next-ranked consented channel within 60 seconds of failure And logs the fallback reason and new channel Given an offer on the preferred channel receives no response for the configured intra-candidate retry delay (e.g., 5 minutes) and the hold window is still active When a secondary consented channel exists and rate limits/quiet hours allow Then the system sends a single follow-up offer on the next-ranked consented channel And total attempts per candidate do not exceed the configured max-attempts-per-candidate within the hold window
Auto-Advance on Decline or No Response
Given an active held slot with an outstanding offer When the patient explicitly declines via any channel within the hold window Then the hold is immediately released And the candidate is marked Declined for this slot And the next ranked candidate is offered the slot within 60 seconds Given an active held slot with an outstanding offer When the hold window expires without a response Then the hold is released And the candidate is marked No Response for this slot And the next ranked candidate is offered the slot within 60 seconds And any pending messages for the expired offer are canceled
Response Processing - Confirm Booking
Given an active held slot with an outstanding offer When the patient confirms via supported inputs (e.g., YES/1/click-to-confirm) on any channel And the confirmation arrives before hold expiration Then the hold is converted to a booked appointment for that patient And all other in-flight offers for that slot are canceled And a confirmation message is sent on the same channel within 60 seconds And the appointment appears on the provider schedule with the correct provider/room constraints Given a confirmation arrives after hold expiration or after the slot is no longer available When the system processes the response Then the patient receives a message that the slot is unavailable and a link/option to rejoin the waitlist And no appointment is created
Quiet Hours and Rate Limit Enforcement
Given practice-level quiet hours are configured and it is currently within quiet hours When an offer would otherwise be dispatched Then the message is queued until quiet hours end And the hold start time is set to the actual dispatch time And no messages are sent during quiet hours Given per-patient and per-practice rate limits are configured When dispatching offers or follow-ups Then the system enforces caps (e.g., per-patient per-day, per-channel per-minute, global per-minute) And any suppressed sends are logged with suppression reason And suppressed messages are retried only when limits reset (if still relevant)
Opt-Out and Consent Enforcement
Given a patient has opted out or lacks consent for a channel When the system selects a channel for offer delivery Then that channel is excluded from selection And no message is sent on that channel Given a patient replies with a standard opt-out keyword on SMS (e.g., STOP, STOP ALL) or clicks email unsubscribe When the system receives the event Then channel consent is immediately revoked and persisted And a single confirmation of opt-out is sent where permitted And future orchestration for that patient excludes the opted-out channel
Localization by Language Preference
Given a patient has a preferred language on file When the system generates the offer message Then the locale-specific template for that language is used And dynamic fields (date/time, provider, instructions) are localized to the patient’s locale And the fallback language is the practice default if no template exists Given a patient responds in their preferred language using supported confirmation/decline intents When the system processes the response Then the intent is correctly recognized for that locale And the follow-up message is returned in the same language
Explainable Ranking & Staff Overrides
"As an office manager, I want to see why the system ranked patients and adjust the order when necessary so that I maintain control and trust the automation."
Description

Provide UI and API surfaces showing the top candidates with their scores and human-readable reason codes (e.g., “length match + provider available + pre-auth on file + high reliability”). Allow staff to pin, reorder, exclude, or manually add patients before sending offers, with all changes audited. Supports practice rules (e.g., block patients with repeated no-shows) and one-off overrides.

Acceptance Criteria
UI: Explainable Ranking List for a Cancellation
Given a cancellation slot with provider, room, and duration defined When a scheduler opens the FitRank Match view for that slot Then the UI displays the top 20 candidates by default (configurable between 5 and 50) including rank position, numeric score (0–100), and a human-readable reason text composed of weighted reason codes And each candidate includes only applicable reason codes among: length_match, provider_available, room_available, insurance_match, pre_auth_on_file/required, reliability_tier, language_match, preferred_channel_available, consent_on_file And candidates violating hard constraints (no consent, invalid insurance for provider, required pre-auth missing, conflicting provider/room) are excluded from the list And sorting is strictly by descending score; ties are broken deterministically by reliability tier, then last_confirmation_date (older first), then patient_id ascending And the view shows a data refresh timestamp and reflects re-ranking changes within 5 seconds of refresh
API: Rank List with Scores and Reasons
Given a GET request to /api/fitrank/candidates?slotId={id} with valid OAuth2 access token and practice scope When the waitlist size is ≤ 5,000 eligible records Then the API responds within 1000 ms p95 with HTTP 200 and JSON including: patientId, rank, score (0–100), reasons (codes[]), reasonText (human-readable), constraintFlags, eligibility (true/false) And if pre-authorization is required and missing, eligibility is false and reasons includes pre_auth_missing; the candidate is omitted when query param filter=eligible And ETag headers are returned; subsequent requests with If-None-Match return 304 when unchanged And a correlationId is included in the response for auditing and must be supplied in subsequent override requests And requests without sufficient permissions return HTTP 403 without PHI in the body and are audited
Staff Overrides: Pin, Reorder, Exclude, Add
Given the ranked candidate list is displayed and the user has role Scheduler or higher When the user pins a candidate Then the candidate is locked at the top in the order pinned (max 5 pins) and marked as Pinned, unaffected by auto re-ranking When the user reorders candidates via drag-and-drop Then the new order persists for the session and is used by the offer send sequence When the user excludes a candidate Then the candidate is removed from the send queue for this slot and the user must select a predefined reason or enter free text ≥ 10 characters When the user manually adds a patient by search Then the system validates eligibility; if violations exist, it requires explicit override confirmation before adding And each override action provides a confirmation step and an undo option available for 60 seconds
Practice Rules and One-Off Overrides
Given the practice rule "Block patients with 2+ no-shows in the last 12 months" is enabled When ranking candidates Then patients meeting that condition have eligibility=false and are excluded from auto-ranking And staff may apply a one-off override only if they enter a justification ≥ 15 characters and select a reason category; the candidate is marked override=true And legal/consent constraints are not overridable (e.g., no consent on file blocks sending) And practice rule configurations are versioned per location with effective timestamps, and changes apply on the next rank computation And any override expires automatically if no offer is sent within 24 hours of the change
Audit: Full Trace of Overrides and Sends
Given any user views, filters, pins, reorders, excludes, adds, overrides, or sends offers When the action is committed Then an audit entry is created capturing userId, role, timestamp (UTC), slotId, patientId (if applicable), previous value, new value, client IP, and correlationId And audit entries are immutable; corrections create append-only records without altering the original And Admin and Compliance roles can export audit logs to CSV or JSON for a selected time range And each offer send record stores the ordered list of attempted recipients, their responses/outcomes, and the final booked patient, linked to a ranking snapshot hash
Send Sequence Integrity
Given a finalized order after pins, reorders, exclusions, and adds When the user initiates Send Offers Then offers are sent in that exact order with throttling of one active offer at a time and a 10-minute timeout before advancing to the next candidate (configurable) And excluded candidates are never contacted And upon acceptance by any candidate, remaining pending offers are canceled, the slot is booked on the provider calendar, and the slot is locked to prevent double-booking And if all candidates decline or time out, the system optionally extends to the next 10 candidates when the Auto-extend setting is enabled And a snapshot of the final order with scores, reasons, and overrides is stored and linked to the appointment record
Performance, Access, and Error Handling
Given normal operating conditions When loading the ranked list in the UI with ≤ 200 candidates Then the content loads within 1.5 seconds p95 and displays a skeleton loader until data renders And any ranking service error shows a non-PHI message with a Retry option; detailed errors are suppressed from end users And access is restricted to users assigned to the location and provider team; unauthorized attempts return 403 and are audited And during service degradation, the system falls back to a FIFO waitlist view within 2 seconds with a banner indicating reduced functionality
Insurance & Pre-Auth Eligibility Gate
"As a billing coordinator, I want the system to verify eligibility and pre-auth before offers go out so that we avoid scheduling patients who cannot be seen."
Description

Validate insurance eligibility and pre-authorization status for the appointment type before sending an offer. Integrates with clearinghouse APIs/EDI where available, caches responses with TTL, and flags missing or expired pre-auth for staff review or automatic deprioritization. Prevents offers that would fail at check-in and reduces last-minute cancellations.

Acceptance Criteria
Eligibility Check Blocks Offer for Ineligible Patient
Given a patient candidate has eligibility status = "Ineligible" for the appointment date and procedure code from the clearinghouse response When FitRank evaluates candidates for a cancellation slot Then the patient is excluded from the offer candidate list and no offer is queued or sent And an exclusion reason code "INS_INELIGIBLE" is recorded in the candidate audit log with payer ID, plan ID, procedure code, and check timestamp And the next best eligible candidate is evaluated within 200 ms of the exclusion decision
Pre-Authorization Required and Missing/Expired
Given the appointment type requires pre-authorization and the patient's pre-authorization status is "Missing" or "Expired" And the slot start time is within the configured pre-auth lead time window (default 48 hours) When FitRank evaluates the candidate Then the candidate is excluded and no offer is queued And a staff review task "Pre-auth required" is created and linked to the patient and appointment within 5 seconds Given the slot start time is outside the configured pre-auth lead time window When FitRank evaluates the candidate with missing/expired pre-auth Then the candidate remains eligible but its rank score is reduced by the configured penalty (default 20%) And the candidate is flagged "Pre-auth missing/expired" in the match details
Clearinghouse API/EDI Eligibility Check and Resilience
Given payer clearinghouse integration is enabled and the patient has active insurance on file When an eligibility check is triggered Then the system sends an X12 270 or payer API request and receives a response within 6 seconds for at least 95% of requests And on failure or timeout, the system retries up to 2 times with exponential backoff (500 ms, 1500 ms) And if retries fail or the 271/response is non-parseable, the eligibility status is set to "Unknown" with reason "ELIG_COMM_FAILURE" and the candidate's rank score is reduced by 10%
Eligibility/Pre-Auth Caching with TTL and Invalidation
Given a cached eligibility/pre-auth result exists for the same patient, payer, appointment date, and procedure code And the elapsed time since retrieval is less than the configured TTL (default 24 hours) When an eligibility check is requested Then the cached result is returned and no external clearinghouse request is made And when the appointment date or procedure code changes, the cached result is invalidated immediately even if within TTL And when TTL expires, the next check performs an external request and refreshes the cache with a new expiry timestamp
Send-Time Revalidation Gate Prevents Bad Offers
Given a candidate was previously marked Eligible When an offer is about to be sent (60 seconds or less before send time) Then the system revalidates insurance eligibility and pre-authorization And if eligibility is now Ineligible or pre-authorization is Expired, the offer is blocked, an "OfferBlocked" event with reason code is recorded, and the next candidate is evaluated within 500 ms And the cancellation record shows a user-visible log entry with the block reason and timestamp
Staff Review Queue and Override Controls
Given a candidate is flagged for staff review due to Missing/Expired pre-authorization or "Unknown" eligibility When the review task is created Then it includes payer contact info, required CPT/ADA codes, and a pre-authorization documentation checklist And when a staff user selects "Override and Send" and enters a required text reason Then the system sends the offer, records the override reason, user ID, prior status, and timestamp in the audit log And when the task is resolved without override, the candidate remains excluded or deprioritized accordingly
Auditability and Operational Reporting for Eligibility Gate
Given eligibility gate decisions are made during candidate evaluation and offer send-time When decisions occur Then all decisions (Eligible, Ineligible, Unknown, PreAuthMissing, PreAuthExpired, OfferBlocked, Override) are recorded in an immutable audit log with correlation IDs and timestamps And daily metrics per practice are generated by 02:00 local time including counts of offers prevented due to ineligibility, candidates deprioritized, average eligibility check latency, cache hit rate, and retry rate And audit logs exclude PHI in plaintext; patient identifiers are stored only in the encrypted data store
Reliability Scoring & Outcome Feedback Loop
"As a practice owner, I want reliability to influence who gets first offers so that show rates improve over time."
Description

Maintain a patient reliability score derived from confirmations, attendance, no-shows, and on-time metrics, decayed over time. Feed outcomes from offers (accepted/declined/no response, show/no-show) back into the scoring model to continuously improve ranking accuracy. Provides practice-level controls for thresholds and weight of reliability in ranking.

Acceptance Criteria
Reliability Score Updates on Patient Events
Given patient P has a recorded reliability score S When P confirms an appointment via SMS, email, or voice Then P’s reliability score becomes S' where S' > S and the change is timestamped and attributed to event_id Given patient P has a recorded reliability score S When P attends and is marked "arrived on time" Then P’s reliability score increases and an "on_time" event is recorded Given patient P has a recorded reliability score S When P is marked "no-show" Then P’s reliability score decreases and a "no_show" event is recorded Given patient P has a recorded reliability score S When P is marked "late arrival" beyond the practice-defined threshold Then P’s reliability score does not increase and a "late_arrival" event is recorded Given duplicate delivery of the same source event (same source_event_id) When processed Then the reliability score is updated at most once (idempotent) and duplicates are ignored
Time Decay of Reliability Contributions
Given the practice sets the reliability decay half-life to 60 days When evaluating reliability today Then any event that occurred exactly 60 days ago contributes 50% of its original weight to the score Given the practice sets the reliability decay half-life to 60 days When evaluating reliability today Then any event that occurred 120 days ago contributes no more than 25% of its original weight Given no explicit practice configuration for decay exists When retrieving reliability settings via API Then the system returns the current default decay parameter and the same parameter is used in computation Given the practice updates the decay parameter from 60 to 30 days When the next scheduled recomputation runs Then all patient reliability scores reflect the new parameter within 15 minutes and historical contributions are reweighted without duplicating events
Offer Outcome Feedback Loop Updates Reliability
Given an offer to fill a cancellation is accepted by patient P and P shows to the appointment When the outcome is ingested Then P’s reliability score increases and an auditable "offer_accept_show" outcome is recorded Given an offer is accepted by patient P but P no-shows When the outcome is ingested Then P’s reliability score decreases and an "offer_accept_no_show" outcome is recorded Given an offer is declined by patient P When the outcome is ingested Then P’s reliability score is updated according to the model and an "offer_decline" outcome is recorded Given no response from patient P within the configured offer timeout When the outcome is ingested Then P’s reliability score is updated according to the model and an "offer_no_response" outcome is recorded Given a valid offer outcome event is received When processing Then the corresponding reliability update is visible in APIs and UI within 5 minutes Given the same offer outcome message is delivered more than once (same offer_id and outcome) When processed Then the reliability adjustment is applied at most once and duplicates are ignored
Reliability Weight Impacts FitRank Ordering
Given two waitlisted patients A and B with identical constraints except reliability where Score(A) > Score(B) and practice reliability_weight = 0.5 When a cancellation occurs and FitRank is computed Then A ranks ahead of B Given practice reliability_weight = 0 When a cancellation occurs and FitRank is computed Then the ranking order is identical to the baseline ordering without reliability and any ties are broken using non-reliability factors Given the practice sets a reliability_threshold T When FitRank is computed Then patients with Score < T are excluded from receiving offers until their score equals or exceeds T Given the practice updates reliability_weight or reliability_threshold When FitRank is recomputed Then the updated ranking and any exclusions are reflected in the UI and API within 5 minutes
Practice-Level Controls: Configuration, Validation, and Audit
Given a user with Practice Admin role When they set reliability_weight within [0.0, 1.0] and a non-negative reliability_threshold and save Then the settings persist and take effect for subsequent computations Given a user without Practice Admin role When attempting to modify reliability controls Then the action is denied with a 403 response or equivalent UI message Given reliability controls are modified When saved Then an audit log entry is created capturing actor_id, practice_id, field_name, old_value, new_value, and timestamp Given the settings retrieval endpoint is called When the practice has saved custom values Then the API returns the current reliability_weight, reliability_threshold, and decay parameter with effective timestamps Given invalid values (e.g., reliability_weight < 0 or > 1) When submitted Then the system rejects the change with validation errors and no changes are persisted
Cold Start and Late Data Handling
Given a new patient with no historical events When computing reliability Then the patient is assigned the neutral baseline score and is not penalized beyond the effects of threshold and weight settings Given historical events arrive late or out of order for a patient When recomputing reliability Then the final score matches the result of processing the complete set once and duplicate events are ignored Given a patient has no events within the decay horizon When computing reliability Then the score converges toward the neutral baseline
HIPAA-Compliant Audit & Consent Logging
"As a compliance officer, I want full audit trails of ranking decisions and communications so that we can demonstrate HIPAA compliance and resolve disputes."
Description

Record all FitRank Match decisions and communications, including inputs used for ranking, scores, offers sent, responses, staff overrides, consent status checks, and timestamps. Store audit logs securely with retention policies and export/search capabilities for compliance review. Ensures traceability, supports dispute resolution, and meets HIPAA and opt-in/opt-out requirements.

Acceptance Criteria
Ranking Decision Audit Log per Cancellation
Given a cancellation is created and FitRank Match runs When the ranking completes Then an audit log entry is written with a unique correlation_id for the run And the log includes cancellation_id, provider_id, room_id, appointment_length_minutes, run_started_at_utc, run_completed_at_utc, fitrank_model_version, input_feature_keys, ranking_algorithm_parameters, and candidate_patient_ids considered And for each candidate the log stores patient_id, eligibility_flags, score, position, and exclusion_reason if excluded And the log is appended within 2 seconds of run completion And no message body content or clinical notes are stored in this event
Offer Communication and Consent Snapshot Logging
Given the system prepares to send an offer to a ranked patient When the offer is dispatched via SMS, email, or voice Then an audit record is created with correlation_id, patient_id, channel, message_template_id, locale, send_timestamp_utc, delivery_provider_id, and delivery_status And a consent_snapshot is captured including treatment_opt_in, marketing_opt_in, channel_opt_in, consent_source, and consent_checked_at_utc And if consent is not active, the system does not send the offer and logs contact_prevented with reason=consent_not_active And the message body is not stored; only template_id and variable_keys with PHI values redacted And patient_language_preference and channel_preference at time of send are logged And patient responses (confirm, reschedule, decline, stop) are logged with response_timestamp_utc and response_channel and linked via correlation_id
Staff Override Audit Trail
Given a staff user adjusts the ranked sequence or selects a non-top-ranked patient When the override action is saved Then an audit event is recorded including user_id, user_role, action_type, timestamp_utc, previous_state (top 5 candidate_ids and scores), new_state, and override_reason (required, min 10 characters) And the event captures session_id and source_ip/device_id And the system validates permissions; if unauthorized, the change is blocked and an access_denied audit event is recorded And override events are immutable and appear in chronological order within the cancellation case history
Audit Log Search and Export for Compliance Review
Given a user with the AuditViewer role accesses the audit console When they search by any combination of date_range, cancellation_id, patient_id, user_id, or correlation_id Then matching results are returned within 3 seconds for up to 50,000 records with pagination And results show normalized columns including event_type, timestamp_utc, actor, subject_ids, and correlation_id And the user can export results to CSV or JSON up to 100,000 records and the export completes within 60 seconds And exports exclude message bodies and include export_metadata (requested_by, requested_at_utc, applied_filters, record_count, checksum) And exported files auto-expire after 7 days and are inaccessible thereafter
Retention, Security, and Access Controls for Audit Logs
Given audit logs are persisted in the system When storage and access are evaluated Then logs are encrypted at rest (AES-256 or KMS equivalent) and in transit (TLS 1.2+) And access is restricted via RBAC to roles Admin, AuditViewer, and System with least-privilege permissions And all access attempts (success/failure) are logged with user_id, timestamp_utc, source_ip, and action And default retention is 6 years, configurable per tenant (min 2, max 10) with documented effective policy And purge jobs enforce retention automatically, produce purge_audit events with counts and checksums, and are irreversible And backups follow the same encryption and retention policies
Tamper-Evidence and Timestamp Standards
Given audit events are written to storage When data integrity is checked Then each event has an immutable event_id (UUIDv7) and a monotonically increasing sequence_number per tenant And a hash_chain is maintained (event_hash = hash(prev_hash + event_payload)) And a daily integrity verification job validates the chain and emits an alert on any discrepancy And all timestamps are recorded in UTC ISO 8601 and system clocks are synchronized to NTP within 200 ms And clock drift exceeding 500 ms triggers an alert and pauses new audit writes until synchronization is restored

QuickChain Send

Time-boxed cascades auto-escalate offers to the next best candidate if there’s no reply within minutes. Includes temporary holds with visible countdowns and fairness rules to avoid spamming. Slots get filled quickly with zero staff clicks and a clear audit trail.

Requirements

Adaptive Candidate Ranking & Fairness Rules
"As an office manager, I want QuickChain to automatically choose the next best patient based on eligibility and fairness rules so that we fill openings quickly without over-messaging patients."
Description

Implements a ranking engine that selects the next best patient candidate for an open slot using configurable criteria (appointment type fit, proximity/lead time, patient reliability, contact preferences, insurance constraints, and consent). Enforces fairness controls including per-patient cooldowns, per-day/week contact caps, quiet hours, and exclusion lists to prevent spamming. Integrates with waitlists and patient profiles, honors opt-in/opt-out status, and supports segmentation by provider, operatory, and procedure. Provides admin-tunable policy settings with safe defaults and real-time eligibility previews.

Acceptance Criteria
Weighted Ranking Selects Next Best Candidate
Given an open slot with configured ranking weights and a waitlist of patients When the ranking engine evaluates candidates Then it computes a numeric score per candidate using the configured weights for appointment type fit, lead time proximity, patient reliability, contact preference match, insurance eligibility, and consent And it returns an ordered candidate list sorted by descending score And it excludes candidates failing hard constraints (no consent, insurance ineligible, appointment type mismatch) And for ties it selects the patient with earlier waitlist join time; if equal, the one with fewer contact attempts today; if still equal, a stable random order seeded per day And it persists the selected candidate, score, and factor breakdown to the audit log for the slot
Consent, Preferences, and Insurance Eligibility Enforcement
Given a patient who is opted out of messaging or lacks required consent When the engine considers the patient for any contact channel Then the patient is marked ineligible and no contact is sent And the ineligibility reason includes a consent code and channel-specific details Given a patient with channel preferences limiting contact to SMS and email When the engine selects a contact channel Then it only uses the allowed channels and excludes voice Given a patient with insurance constraints not matching the slot’s accepted plans When evaluating eligibility Then the patient is excluded with an insurance_ineligible reason
Fairness Controls: Cooldowns, Contact Caps, and Quiet Hours
Given tenant policies with per-patient cooldown of 12 hours, per-day cap of 2 contacts, per-week cap of 5 contacts, and quiet hours 20:00–08:00 in the practice’s time zone When a candidate has been contacted within the last 12 hours or has reached the daily/weekly cap Then the candidate is skipped and not contacted, with a skip reason recorded (cooldown_active, daily_cap_reached, or weekly_cap_reached) And when current time falls within quiet hours Then any message is deferred to the next allowed window and scheduled within 5 minutes after quiet hours end And no more than one contact attempt is made per candidate per open slot
Segmentation by Provider, Operatory, and Procedure
Given an open slot assigned to a specific provider (or mapped provider group), operatory, and procedure type When ranking candidates from the waitlist Then only patients whose profiles indicate eligibility for the provider/group, compatible operatory constraints, and matching procedure type are included And candidates failing any segmentation rule are excluded with a specific reason (provider_mismatch, operatory_mismatch, procedure_mismatch)
Admin Policy Settings: Safe Defaults, Validation, and Audit
Given a new tenant When no policies are configured Then safe default values are applied for all ranking weights and fairness limits Given an admin updates policy settings When values are within allowed ranges and pass validation Then the changes are saved, audited (old_value, new_value, user, timestamp), and take effect within 60 seconds across ranking and preview When values are invalid or out of range Then the update is rejected with a descriptive error and no changes are applied
Real-Time Eligibility Preview Consistency and Performance
Given an admin opens the eligibility preview for a specific slot When policies or filters are adjusted (weights, caps, segmentation) Then the preview list and reasons update within 500 ms on average and within 1,000 ms at p95 And the preview order and eligibility set exactly match the runtime ranking output when triggered within the same data snapshot
Temporary Holds and Auto-Escalation Respect Fairness
Given the selected candidate is contacted and a temporary hold of 7 minutes is placed on the slot When the hold is active and no reply is received Then the candidate remains excluded from further offers until the hold expires, and a visible countdown is shown in the audit trail And upon hold expiry, the next best eligible candidate is selected according to current ranking and fairness rules And if a reply is received before expiry, auto-escalation is canceled and the slot is reserved for the responder
Time-Boxed Escalation Scheduler
"As a scheduler, I want offers to auto-escalate on precise timers so that openings are filled fast without manual tracking."
Description

Provides precise, durable timers that auto-escalate offers to the next candidate when no response is received within a configured window (e.g., 3–10 minutes). Supports per-template timing profiles, business-hour windows, patient time zone awareness, overnight pauses, jitter to avoid synchronized bursts, and idempotent retries. Ensures chain state is persisted and resumes after outages. Integrates with calendar availability to verify slot is still free before each escalation hop.

Acceptance Criteria
Escalate After Configured No-Response Window
Given a QuickChain offer using a timing profile with escalation_window = 5 minutes and jitter = 0 seconds And the initial candidate is contacted at 10:00:00 in the patient's time zone And no reply is received by 10:05:00 When the escalation window elapses Then the next candidate is contacted at 10:05:00 ± 2 seconds And the previous candidate is marked "expired_no_response" And an audit event "escalated_to_next_candidate" is recorded with chain_id, hop number, and timestamp
Per-Template Timing Profiles Applied
Given template A has escalation_window = 3 minutes and template B has escalation_window = 9 minutes with jitter = 0 And chain A is initiated at T0 using template A; chain B at T1 using template B And neither candidate responds within their windows When the scheduler processes both chains Then chain A escalates at T0 + 3 minutes ± 2 seconds And chain B escalates at T1 + 9 minutes ± 2 seconds And the audit for each hop records the template_id and timing profile used
Respect Business Hours in Patient Time Zone
Given patient time zone = America/New_York and practice business hours are 08:00–18:00 in the patient's time zone And an offer is sent at 17:57 with escalation_window = 5 minutes And no reply is received by 18:02 When the scheduler evaluates the escalation Then no escalation is sent between 18:00 and 08:00 And the escalation is scheduled for 08:00 next business day ± 10 seconds And the audit records "deferred_outside_business_hours" with original_due_time and rescheduled_time
Overnight Pause and Resume Timers
Given patient time zone = America/Denver and business hours are 09:00–17:00 And an offer is sent at 16:56 with escalation_window = 5 minutes and jitter = 0 And no reply is received When the clock reaches 17:00 Then the timer pauses with remaining_time ≈ 1 minute recorded And at 09:00 next business day the timer resumes And the escalation fires at 09:01:00 ± 2 seconds And audit logs include pause_time, resume_time, and remaining_time_seconds
Jitter Applied to Escalations
Given a timing profile with escalation_window = 5 minutes and jitter_max = 30 seconds And 10 chains are initiated at T0 with no replies When escalations are due Then each escalation occurs at time T0 + 5 minutes + j where 0 ≤ j ≤ 30 seconds And at least 8 of the 10 escalations have distinct second-level timestamps And each hop's applied_jitter_seconds is recorded in the audit
Idempotent Retries and Outage Recovery
Given an escalation is due at 10:05:00 with idempotency_key assigned for hop N And the scheduler process restarts twice between 10:04:30 and 10:06:00 And the system clock continues normally When services recover Then exactly one escalation action is executed for hop N And if the due time passed during the outage, the escalation is sent within 5 seconds of service recovery And duplicate attempts are ignored as no-ops using the same idempotency_key And the chain state advances by one hop with a single "escalated_to_next_candidate" audit event
Calendar Availability Check Before Escalation
Given the target appointment slot is checked before each escalation hop And the slot becomes booked by another appointment 10 seconds before the due escalation When the escalation is due Then the scheduler revalidates availability within 1 second before sending And if the slot is unavailable, it cancels the remaining chain with status "slot_unavailable" and sends no further communications And an audit event "escalation_cancelled_slot_unavailable" is recorded with the calendar_event_id and timestamp
Temporary Hold with Visible Countdown
"As a hygienist, I want a visible countdown hold on offered slots so that I can see when a slot is reserved and avoid double-booking."
Description

Places a temporary hold on the appointment slot during each offer hop to prevent double-booking, with a visible countdown timer displayed in the staff calendar and, when applicable, on patient landing pages. Automatically releases holds on decline, expiry, or override, and converts holds into confirmed bookings on acceptance. Handles race conditions across channels and devices, logs hold lifecycle events, and gracefully reconciles conflicts if the slot is taken by another workflow.

Acceptance Criteria
Hold Placement and Visible Countdown on Hop Start
- Given an available appointment slot and a QuickChain hop is initiated for Patient A, when the offer is dispatched, then a temporary hold is created on that slot with a TTL equal to the hop’s configured hold duration. - Then the staff calendar displays a countdown timer (mm:ss) for that slot within 2 seconds of hold creation, showing the exact expiration time in the practice’s timezone. - And when Patient A opens the landing page link for the offer, then the same countdown (±1 second) is displayed within 3 seconds, synced to the same expiration. - And while the hold is active, staff booking controls for that slot are disabled and an explanation banner is shown referencing an anonymized patient identifier. - And only one active hold can exist per slot at any time.
Auto-Release and Conversion on Response
- Given a hold is active for Patient A, when Patient A accepts the offer before expiry, then the hold is atomically converted into a confirmed booking, the countdown is removed in the staff calendar and landing page within 2 seconds, and the slot status changes to Booked. - When Patient A declines before expiry, then the hold is released within 2 seconds, the calendar updates to available, and the QuickChain proceeds to the next hop, creating a new hold for the next candidate. - When the hold expires with no response, then the hold is automatically released at TTL with tolerance ≤1 second, the calendar updates within 3 seconds, and the QuickChain proceeds to the next hop. - When a staff user overrides the hold, then the hold is released immediately, a reason code is required and captured, and QuickChain behavior follows practice configuration (stop or proceed).
Race Conditions Across Channels and Devices
- Given two or more participants respond nearly simultaneously across different channels or devices, when conflicting accept actions occur for the same slot, then only the first valid transaction acquires the slot lock and succeeds; all subsequent actions return “slot no longer available,” release any related holds, and do not create a double booking. - And all clients (calendar and landing pages) reflect the resolved state within 3 seconds of resolution. - And all operations are idempotent; retrying the same response does not change the final outcome.
Conflict Reconciliation with External Booking
- Given an active hold exists and another workflow or manual action books the same slot, when the conflict is detected, then the system marks the hold as conflicted, releases it immediately, prevents any further hop offers for that slot, and notifies affected parties (staff banner and patient page message). - Then no double booking occurs; the slot remains with the external booking. - And an alert is logged and surfaced in the QuickChain audit for postmortem.
Hold Lifecycle Audit Trail
- Given holds are created, converted, or released, when any lifecycle event occurs (create; release: decline/expiry/override/conflict; convert to booking), then an audit entry is recorded with timestamp (UTC and local), user/system actor, reason code, QuickChain ID, Hop ID, Slot ID, and request correlation ID. - And audit entries are immutable, queryable by date range and identifiers, and exportable to CSV. - And all timestamps are monotonic and ordered per Slot ID.
Countdown Display Usability and Accuracy
- Given countdowns are shown on staff calendar and patient landing pages, when the timer updates each second, then the remaining time is accurate within ±1 second and reflects practice timezone with correct daylight saving adjustments. - And the display meets WCAG 2.1 AA for color contrast; screen readers announce time remaining via a polite aria-live region no more than once per second; keyboard users can focus and read the timer tooltip showing exact expiration timestamp. - And the patient page reveals only the minimum necessary information (practice name and appointment date/time) with no PHI beyond what is required to respond.
Multi-Channel Dispatch & Rate Limiting
"As a practice owner, I want QuickChain to send offers across the best channels while respecting limits so that patients are reached promptly without feeling spammed."
Description

Orchestrates SMS, email, and voice outreach per patient preferences and deliverability health. Falls back to an alternate channel on delivery failure and supports channel sequencing within each hop. Enforces per-patient and global rate limits, quiet hours, and practice-level throttles to maintain carrier compliance and patient experience. Tracks send status, link clicks, and call outcomes, with short links and branded sender profiles. Integrates with vendors (e.g., Twilio, SendGrid) behind a pluggable adapter layer.

Acceptance Criteria
Channel Preference Sequencing per Patient
Given a patient has saved channel preferences and permissions (e.g., SMS primary, Email secondary, Voice disabled) And a QuickChain hop is triggered for that patient When the system selects a channel for the first attempt Then it chooses the highest-ranked allowed channel whose deliverability health meets the configured threshold And it skips any channel the patient has opted out of or is marked undeliverable And it records the chosen channel and reasoning in the audit trail with timestamp and hop ID
Fallback on Delivery Failure within Hop
Given an attempt is sent on Channel A within a QuickChain hop And a definitive delivery failure is received or no delivery receipt arrives within the configured fallback window When the failure is detected or the window elapses Then the system attempts the next channel in the configured sequence for that hop And the fallback respects per-patient and global rate limits and quiet hours And the failure and fallback attempt are recorded in the audit trail linked to the same hop ID
Per-Patient and Global Rate Limit Enforcement
Given configured per-patient limits (messages per rolling 24h per channel and cross-channel) and global practice limits (messages per minute per channel) When a new send is evaluated Then the system blocks or defers any send that would exceed a configured limit And deferred sends are queued with a next-eligible-at timestamp and reason And dispatched messages never exceed the global limit within the measured windows And all blocks/deferrals appear in the audit trail with limit type and thresholds
Quiet Hours Compliance by Local Time
Given practice-level quiet hours and the patient's time zone are configured When a send is scheduled during quiet hours for that patient Then the system does not dispatch during quiet hours And it reschedules the send for the earliest allowed time while respecting the hop SLA and QuickChain ordering And any visible countdown timers are paused/updated to reflect the new schedule And the audit trail includes the quiet-hours deferral with local timestamps
Practice-Level Throttling and Burst Control
Given a practice has a configured throughput cap per channel (TPS) and a maximum concurrent calls cap When multiple sends become eligible simultaneously Then the dispatcher meters sends so observed throughput in 1-second and 60-second windows does not exceed caps And excess work is queued fairly across patients to avoid concentrating messages to a single patient And carrier 429/rate-limit responses trigger exponential backoff and temporary cap reduction until recovery And metrics expose current utilization, queue depth, and throttling actions
Tracking Sends, Clicks, and Call Outcomes with Branded Short Links
Given messages may contain URLs and branded sender profiles are configured When an SMS or email is sent Then all URLs are replaced with secure short links on the practice-branded domain including campaign/hop tracking parameters And click events are captured and attributed to the patient, hop, and channel within the configured callback SLA And call attempts record ring/no-answer/voicemail/live-connect outcomes with duration and disposition codes And all send, delivery, open/click, and call outcome events are queryable by hop ID in the audit trail
Pluggable Vendor Adapter and Failover
Given multiple vendor adapters are configured for a channel (e.g., Twilio primary, secondary provider fallback) And the primary vendor exhibits 5xx errors, latency above threshold, or error rate above the failover threshold within the observation window When dispatching new attempts Then the system switches to the secondary adapter for that channel until health recovers per the recovery threshold And idempotency is enforced to prevent duplicate sends for the same hop attempt And vendor requests/responses are normalized to a common event model with adapter name and correlation IDs And failover and recovery events are logged and surfaced in monitoring and the audit trail
Response Parsing & Branching Logic
"As a patient, I want to confirm or decline an offer with a simple reply so that I can quickly secure a time that works for me."
Description

Captures and interprets inbound responses across SMS (keywords and NLP), email (link actions), and voice (IVR DTMF) to determine acceptance, decline, or alternative requests. Applies deterministic branching rules first, then NLP fallbacks with confidence thresholds. Handles ambiguous replies with clarifying prompts, enforces opt-out keywords, and updates chain state atomically. On acceptance, locks and books the slot via scheduling APIs, sends confirmations, and stops the chain; on decline or timeout, escalates to the next candidate.

Acceptance Criteria
SMS Keyword Acceptance and Slot Booking
Given a candidate receives an SMS invite that holds a specific slot with a visible countdown When the candidate replies with "YES" (case-insensitive) before the hold expires Then the system validates the keyword by deterministic rule, without invoking NLP And the system atomically locks and books the slot via the scheduling API, receiving a 2xx response within 5 seconds And the chain state transitions to Accepted, a confirmation SMS and email are sent, and further chain messages are halted for all candidates of that slot And an audit trail entry is recorded with timestamps, message IDs, acceptance source=SMS, and scheduling API transaction ID And if the scheduling API returns non-2xx, the acceptance is rolled back, the hold is released, an error is logged, the candidate receives a failure notice, and the chain escalates to the next candidate
Email Link Decline and Escalation
Given a candidate receives an email invite containing unique Accept, Decline, and Alternative links When the candidate clicks the Decline link Then the system marks the candidate as Declined and immediately releases any active hold on the slot And the chain escalates to the next best candidate within 30 seconds and no further reminders are sent to the declined candidate for this slot And the action is idempotent: repeated clicks on the Decline link do not change state beyond the first transition And an audit trail captures email message ID, clicked URL, candidate ID, timestamp, and resulting chain transition
Voice IVR DTMF Mapping for Accept/Decline
Given a candidate answers an IVR call with prompts offering 1=Accept and 2=Decline When the candidate presses 1 Then the system records Accept via IVR, books the slot atomically through the scheduling API (2xx within 5 seconds), sends confirmation via SMS/email, and stops the chain When the candidate presses 2 Then the system records Decline, releases the hold, and escalates to the next candidate within 30 seconds When the candidate presses any other key or no key Then the system reprompts once and, if still invalid/no input, ends the call and sends a follow-up clarification SMS; no booking occurs And all IVR interactions (DTMF input, call IDs, timestamps) are logged in the audit trail
Ambiguous Reply Clarification and Resolution
Given an inbound SMS reply that is ambiguous or multi-intent (e.g., "maybe", "later", mixed accept/decline terms) and does not match deterministic rules When the NLP model classifies the intent with confidence below the configured threshold Then the system sends a clarification prompt within 60 seconds offering clear options (e.g., Reply YES to accept, NO to decline, 3 for alternate time) And if the candidate responds with a clear option within 5 minutes, the corresponding branch (accept/decline/alternate) executes and is logged And if no response is received within 5 minutes, the system treats the attempt as no decision, releases any hold, and escalates to the next candidate And all prompts and responses are linked in the audit trail with the parent chain ID
Deterministic Rules Precedence and NLP Fallback with Thresholds
Given an inbound message across SMS/email/voice When the content matches a configured deterministic rule (e.g., YES/NO/STOP keywords, accept/decline link, IVR DTMF) Then the deterministic branch is applied and the NLP classifier is not invoked for routing When no deterministic rule matches Then the NLP classifier runs and, if intent confidence ≥ configured threshold (default 0.85), the mapped branch executes And if intent confidence < threshold, a clarification prompt is sent and the chain waits for disambiguation before proceeding And each decision logs rule match status, model version, confidence score, and chosen branch in the audit trail
Opt-Out Keyword Enforcement and Chain Termination
Given a candidate sends an opt-out keyword (e.g., STOP, STOPALL, UNSUBSCRIBE) via any supported channel When the message is received Then the system immediately confirms the opt-out to the candidate, halts all current and future communications to that contact, and terminates their participation in the active chain And any holds on slots for that candidate are released, no escalation messages are sent to the opted-out contact, and the chain advances to the next candidate as needed And the opt-out is persisted at the contact level with timestamp, channel, and source, and is reflected in the audit trail
Timeout Escalation, Hold Release, and Concurrency Safety
Given a candidate has an active temporary hold and has not responded When the configured response window elapses without a valid accept/decline Then the system releases the hold, marks the candidate as Timed Out, and escalates to the next candidate within 30 seconds And if two candidates attempt to accept the same slot concurrently, only the first successful atomic booking succeeds; the other receives a "slot already filled" message and no double booking occurs And all state transitions use idempotency keys and are recorded with timestamps to provide a clear audit trail
Audit Trail & HIPAA-Compliant Logging
"As a compliance officer, I want a complete, HIPAA-compliant audit trail of every offer and response so that we can demonstrate accountability and resolve disputes."
Description

Creates an immutable, time-sequenced log of all QuickChain events including candidate selection rationale, messages sent, delivery results, holds, responses, escalations, and overrides. Minimizes PHI in logs, encrypts sensitive fields at rest and in transit, supports role-based access, and provides redacted views for support. Enables export by chain, slot, patient, or date range, with tamper-evident hashing and configurable retention aligned to HIPAA and practice policy. Surfaces a clear, filterable audit view in the UI.

Acceptance Criteria
Immutable Event Log for QuickChain Lifecycle
Given a QuickChain with one or more slots is started When the system performs actions (candidate selection, message send, delivery result, temporary hold start/end, response received, escalation, manual override, cancellation) Then an audit event is appended within 1 second with ISO-8601 UTC timestamp, chain_id, slot_id, event_type, actor (system|user_id|integration), rationale_code (for selections/escalations), and correlation_id And each event carries a sequential event_number scoped to chain_id with no gaps or duplicates under concurrent load up to 1,000 events/min And each event includes prev_event_hash and event_hash (SHA-256) forming a tamper-evident chain; daily root hash is anchored and verifiable via an integrity-check endpoint And updates are never in-place; corrections are new events referencing prior_event_id and change_reason And retry/idempotency keys prevent duplicate event records on at-least-once processing
PHI Minimization and Redaction in Logs
Given QuickChain messages and patient context are processed When audit events are written Then no full message body containing PHI is stored; only template_id and token keys; token values marked PHI are redacted (********) in stored event payloads And patient identifiers are limited to patient_uid and practice_uid; names, phone, email, and DOB are excluded or tokenized unless role permits view And automated leakage tests using seeded PHI samples detect zero occurrences of disallowed fields across 10,000 events And support-view APIs return redacted fields; admin/clinician views may unmask only via just-in-time access with reason_code and expiry And all redaction decisions are captured in event metadata (redaction_profile_id)
Encryption In Transit and At Rest with Managed Keys
Given any audit event is transmitted or stored Then TLS 1.2+ with modern ciphers is enforced on all network paths; attempts below TLS 1.2 are rejected and logged And event payloads at rest are encrypted with AES-256-GCM via KMS-managed envelope keys; key rotation occurs at least every 90 days and on-demand And decryption requires service identity with least-privilege IAM; failed decrypt attempts are denied and produce security alerts within 60 seconds And backups and exports use the same encryption guarantees
Role-Based Access and Redacted Support Views
Given users with roles Admin, Clinician, Support, and Auditor access the audit UI/API When fetching events Then RBAC enforces field-level permissions: Support sees redacted PHI fields; Auditor sees integrity metadata but no PHI; Admin/Clinician can request unmask with reason and time-bound grant And all access is MFA-gated; access attempts, grants, and denials are logged as audit events And response times remain under 500 ms P95 for 100k-event tenants while applying redaction And revoking a grant removes unmasked access within 60 seconds
Tamper-Evident Export by Chain, Slot, Patient, or Date Range
Given a user with export permission requests an audit export with filters (chain_id|slot_id|patient_uid|date_range) When the export is generated Then the result contains only events matching filters and role permissions, in chronological order And files are chunked at 100 MB with per-chunk SHA-256 and an overall manifest hash; manifest includes prev_anchor_hash for verification And the export is available as JSONL and CSV; download URLs expire in 15 minutes and require signed URLs And an integrity-verify tool validates hash chain continuity and manifest signature; verification passes for unmodified exports And export generation completes within 2 minutes for up to 1,000,000 events
Configurable Retention and Compliant Purge
Given tenant-level retention policies (e.g., 6 years default, overrides per event type) and legal holds When retention windows elapse Then purge jobs run daily, removing eligible events from primary and backups within 30 days while preserving integrity anchors and purge receipts And purged ranges are recorded as purge_receipt events with counts and hashes; legal holds and WORM periods prevent deletion And configuration changes are versioned and auditable; policy misconfigurations are flagged before activation
Filterable Audit View in UI
Given a user opens the QuickChain audit view When they filter by chain, slot, patient, event type, actor, outcome, or date range and search by correlation_id Then the grid updates within 700 ms P95 and shows time-sequenced events with sticky headers and infinite scroll/pagination And clicking an event reveals details with redacted fields per role and a link to related entities; timezone display respects user preference And the view indicates integrity status (hash verified/failed) and allows copy of event_id and correlation_id And accessibility meets WCAG 2.1 AA for keyboard navigation, focus, and screen readers
Manual Override & Safeguards
"As a front-desk lead, I want the ability to intervene in a QuickChain when necessary so that I can handle edge cases without breaking the workflow."
Description

Allows authorized staff to pause, resume, or cancel a chain; skip or pin a candidate; adjust timers; or manually assign the slot. Performs preflight safety checks to prevent sending to already booked or ineligible patients and resolves state cleanly on override, including releasing holds and notifying affected parties. Provides undo for recent actions and emits alerts when chains stall or exhaust the candidate pool, with recommended next steps.

Acceptance Criteria
Pause/Resume/Cancel Chain Controls
Given an active QuickChain with pending steps and an authorized user with "Override Chains" permission When the user clicks Pause Then the chain state changes to Paused within 2 seconds and no outbound messages, holds, or timer decrements occur while paused And the countdown clock on any existing holds is visually frozen and stored server-side When the user clicks Resume Then the chain resumes from the next pending step, timers are recalculated to account for the paused duration, and hold countdowns continue When the user clicks Cancel Then all pending messages are canceled, all holds are released immediately, affected candidates are notified per channel rules, and the chain state is Closed:Canceled And an audit trail entry is recorded for each action with user, timestamp, before/after state, and reason
Skip or Pin Candidate with Fairness Enforcement
Given a candidate at the top of the chain queue and an authorized user When the user selects Skip with a reason Then the candidate is moved out of the current cascade, the next eligible candidate is selected, and the skip reason is stored in the audit trail And fairness caps (e.g., max 2 outreach attempts per 24 hours per patient and per channel) are enforced so the skipped candidate is not re-contacted until eligible When the user selects Pin on a candidate Then that candidate receives a temporary hold on the slot with a visible countdown, competing candidates are suppressed, and the chain advances to confirmation for the pinned candidate And pin duration respects configured limits; when it expires without confirmation, the chain auto-advances to the next best eligible candidate
Adjust Chain Timers
Given a running chain with active countdowns and an authorized user When the user adjusts the reply window or escalation delay within the allowed min/max bounds Then the new timers take effect immediately, reflected in the UI countdown within 2 seconds and persisted to the server And any scheduled notifications are rescheduled without duplication, with zero messages sent earlier than the newly configured time And attempts to set timers outside bounds are rejected with inline validation messaging and no change to stored values
Manual Assign Slot and State Cleanup
Given an open slot in an active chain and an authorized user When the user manually assigns the slot to a specific patient Then the chain transitions to Filled:Manual, all pending messages for other candidates are canceled, all holds are released, and suppressed candidates receive appropriate cancellation notifications And the assigned patient is marked booked for that slot, preventing further outreach for that slot, and the appointment appears in the schedule within 5 seconds And the audit trail records the manual assignment with patient, user, timestamp, and affected candidate list And a preflight check confirms the selected patient is eligible and not already booked in the time window; if not eligible, the action is blocked with a specific error message and no state changes
Preflight Patient Eligibility and Conflict Checks
Given a candidate is about to receive an outreach as part of a chain step When preflight checks run Then the system verifies the candidate is not already booked for an overlapping time, is within communication consent and preferences, has valid contact routes, and meets eligibility filters (e.g., age, payer, provider constraints) And if any check fails, no message is sent, the candidate is marked ineligible with a machine-readable reason code, the audit trail is updated, and the chain proceeds to the next eligible candidate And duplicate contact detection prevents sending the same message to multiple channels for the same candidate within the same step unless configured, ensuring at most one outreach per step per candidate
Undo Recent Override Actions
Given the user performed a manual override action (pause, resume, cancel, skip, pin, timer change, manual assign) within the last 5 minutes When the user clicks Undo Then the system validates feasibility and reverts the chain to the prior consistent state, reapplying timers/holds/messages as appropriate without creating duplicate sends And if undo is not possible (e.g., slot filled by another patient), the system presents a clear reason and offers contextual next steps And an audit trail entry links the undo to the original action, including user, timestamp, and outcome
Stall and Pool Exhaustion Alerts with Recommendations
Given an active chain has no responses or state changes for N minutes (configurable) or exhausts its candidate pool When detection runs Then an alert is generated with the stall/exhaustion reason, time, and recommended next steps (e.g., extend reply window, widen eligibility), delivered via in-app banner and email to subscribed roles And the alert includes action buttons/deep links to apply the recommended remediation in one click, and records acknowledgement and resolution timestamps And duplicate alerts are suppressed within a cooling window, and alerts containing PHI are not sent via email; email versions are de-identified

ETA Guard

Checks real-time arrival feasibility (distance, traffic, weather, known availability) before sending an offer. Only patients who can realistically make it on time receive the message, cutting last-minute no-shows and avoiding frustrating, impossible asks.

Requirements

Real-time ETA Computation Engine
"As a scheduler, I want the system to verify a patient’s real-time ability to arrive on time so that we only send offers to patients who can actually make it."
Description

Compute per-patient arrival feasibility in under 2 seconds by aggregating live travel times (drive, transit, walk), traffic incidents, and weather impacts from multiple providers. Apply practice-configurable buffers for parking, check-in, and building access. Normalize time zones, handle multi-location practices, and recalculate ETAs on schedule changes or as the slot start approaches. Provide a binary gate (send/withhold) plus an arrival confidence score to the messaging pipeline so offers are only sent to patients who can realistically arrive on time. Include resilient fallbacks, rate limiting, caching, and graceful degradation when a data source is unavailable.

Acceptance Criteria
Sub-2-Second Feasibility Response Under Load
Given the ETA engine receives requests containing patient location, appointment start time, and practice location And external travel-time and conditions providers are reachable And a load test of 100 requests per second sustained for 5 minutes with 200 RPS bursts for 30 seconds every 2 minutes When feasibility is computed Then end-to-end response latency is <= 2000 ms at the 95th percentile and <= 3000 ms at the 99th percentile And the non-5xx error rate is <= 0.5% over the test window
Multi-Modal Aggregation with Provider Fallbacks
Given travel modes configured as [drive, transit, walk] and providers P1 (primary) and P2 (secondary) When P1 returns valid data Then the engine aggregates live travel times per mode and applies traffic-incident and weather adjustments to produce per-mode ETA minutes When P1 fails due to timeout (>800 ms), 5xx, or malformed data Then P2 is used automatically without failing the request When all providers fail Then cached results not older than 10 minutes are used; if none, heuristic profiles are used; response includes degradation_reason and confidence_score <= 0.40 And the selected ETA is the minimum across enabled modes And response includes provider_used and mode_selected metadata
Practice-Configurable Buffers Application
Given practice buffers for parking, check-in, and building access are configured per location with defaults of 5, 5, and 3 minutes unless overridden And the appointment slot has a defined start time When feasibility is computed Then total_buffer_minutes = parking + check_in + building_access And on_time = now + travel_time_minutes + total_buffer_minutes <= slot_start_local And the response includes buffer_breakdown and on_time And negative buffer values are rejected and any single buffer is capped at 30 minutes
Time Zone Normalization and Multi-Location Handling
Given a practice with multiple locations in different time zones and a patient in any time zone When computing feasibility Then slot_start is converted to the appointment location’s IANA time zone And DST transitions on boundary dates are handled correctly And if the patient time zone is unknown, infer from geocoded coordinates; otherwise default to appointment location’s time zone And all timestamps in the response are ISO 8601 with explicit offsets
Recalculation Triggers and Freshness SLAs
Given an appointment becomes eligible for offers within 24 hours of start When the appointment time changes, the patient’s last-known location changes by >= 0.5 miles, provider availability changes, relevant incident/weather data updates, or the slot is within 60 minutes of start Then the engine recomputes feasibility within 3 seconds of the trigger And during the final 60 minutes, feasibility is refreshed at least every 5 minutes And duplicate triggers within 60 seconds coalesce into one recomputation And an event is emitted only when decision changes or confidence_score changes by >= 0.05 or crosses the send threshold
Binary Gate and Confidence Score to Messaging Pipeline
Given a configured send_threshold in [0.0,1.0] defaulting to 0.70 at practice or location level When feasibility is computed Then decision = 'send' if on_time = true and confidence_score >= send_threshold; otherwise decision = 'withhold' And a message is published to the messaging pipeline within 200 ms containing {patient_id, appointment_id, decision, confidence_score, mode_selected, eta_minutes, buffer_breakdown, reasons[]} And confidence_score is derived from data freshness, provider reliability, incident severity, and weather impact and rounded to two decimals And outputs are deterministic for identical inputs using an idempotency key
Rate Limiting, Caching, and Graceful Degradation
Given external provider quotas of Q requests per minute When outbound call demand would exceed Q Then the engine rate-limits to <= 95% of Q and serves cached responses not older than 5 minutes where available And identical requests within 60 seconds return from cache with a cache hit rate >= 60% under replay load And when all live data is unavailable, the engine returns decision = 'withhold', sets degradation_reason, sets confidence_score <= 0.30, and maintains latency <= 1500 ms And all degradations are logged with provider identifiers and error codes
Provider & Operatory Availability Sync
"As an office manager, I want ETA Guard to confirm a real, bookable slot exists with the right provider and room so that offers don’t create conflicts or double-bookings."
Description

Continuously sync provider calendars, operatory/chair availability, appointment types, durations, and required buffers from the practice management system to ensure an actually bookable slot exists before sending offers. Enforce provider-specific rules (e.g., procedure constraints, required equipment/room), prevent double-booking via optimistic locking or short-held reservations, and respect blocked times and lunch/meeting schedules. Support multi-provider, multi-location setups and handle daylight saving/time zone edges. Integrate with existing SmileCue scheduling and branching logic without adding manual steps for staff.

Acceptance Criteria
Real-time PMS Sync Ensures Bookable Slots Exist
Given SmileCue is connected to the practice management system (PMS) and the sync service is healthy When ETA Guard is about to send an offer for a candidate time Then the system verifies in PMS that the slot exists with matching provider, operatory, appointment type, duration, and required buffers And the last successful sync for providers, operatories, appointment types, and buffers relevant to the slot is ≤ 60 seconds old And PMS changes propagate to availability calculations within 5 seconds at p95 And if verification fails or sync age exceeds 60 seconds, no offer is sent and a warning is logged with correlation IDs
Provider Rule Enforcement for Procedure and Equipment Constraints (Including Multi‑Provider)
Given a procedure that requires specific provider credentials, equipment, room type, and possibly multiple providers When evaluating candidate slots for an offer Then only slots where all required providers are eligible and simultaneously available are considered And only operatories with the required equipment/room capabilities are considered And slots violating any provider, equipment, or room constraint are excluded, recorded in decision logs, and never offered
Concurrency Control Prevents Double‑Booking During Offer Windows
Given multiple offers or channels may target the same slot concurrently When a slot is selected for inclusion in an offer Then the system acquires an optimistic lock or creates a short‑held reservation for that slot for up to 3 minutes while awaiting patient response And concurrent attempts to reserve the same provider/operatory/time must fail deterministically and select an alternate slot or skip sending And held reservations auto‑release on decline, expiration, or timeout (≤ 3 minutes) And no two accepted offers can result in overlapping bookings for the same provider or operatory
Respect Blocked Times, Meetings, and Buffer Rules in Availability
Given provider blocked times, lunch/meeting schedules, and PMS pre/post buffer rules When computing availability for potential offers Then time ranges marked as blocked or busy are excluded from consideration And pre/post buffers are enforced so the appointment plus buffers do not overlap other bookings And only start times that satisfy duration and buffer requirements are offered
Multi‑Location Time Zone and DST‑Safe Slot Evaluation
Given a practice with locations in different time zones and upcoming DST transitions When generating offer timestamps and validating availability Then all times are computed using the location’s IANA time zone with UTC as the system source of truth And nonexistent times during spring‑forward are not offered And ambiguous times during fall‑back are mapped unambiguously and labeled correctly in notifications And audit logs persist both UTC and location‑local timestamps for each decision
Seamless Integration with SmileCue Branching Without Staff Actions
Given SmileCue’s existing scheduling and branching logic When ETA Guard evaluates whether to send an offer Then availability checks run automatically with no additional clicks or workflows for staff And if no bookable slot exists, the offer branch is skipped and the configured fallback branch is executed And staff calendars reflect a visual indicator only when a hold/reservation exists or a booking is confirmed And pre‑offer availability evaluation completes within 200 ms at p95
External Changes Trigger Offer Revocation and Safe Fallbacks
Given a slot included in an active offer becomes booked or blocked externally in PMS When the sync service receives the change Then outstanding offers for that slot are revoked within 10 seconds And patients attempting to accept after revocation receive a “No longer available” response with next‑best alternatives And any active holds are released immediately to avoid double‑booking
Patient Eligibility & Preferences Rules
"As a dentist, I want offers to consider each patient’s preferences and constraints so that we invite the right patients at the right times."
Description

Evaluate non-travel constraints before offer send, including patient communication preferences (DND hours, channel opt-ins), known availability windows, mobility/assistance needs, distance caps, and historical punctuality/no-show patterns. Respect HIPAA minimum-necessary access while using address-on-file and consented data to avoid intrusive tracking. Exclude ineligible patients (e.g., not due for care type, incompatible insurance for slot) and include rationale codes for audit and staff review. Make rules configurable per practice and appointment type.

Acceptance Criteria
Enforce DND Hours and Channel Opt-Ins
Given a patient with configured DND hours and per-channel opt-in statuses And an offer is eligible by other rules When ETA Guard evaluates eligibility during the patient's DND window Then no outbound message is sent during DND And the offer is deferred to the first minute after DND And only channels with active opt-in are considered for send And if no channels remain after filtering, the patient is excluded with rationale code "NO_CHANNEL_CONSENT" And an audit record is stored with rationale codes ["DND_ACTIVE","CHANNEL_FILTERED"] and the deferred send time
Match Known Availability Windows with Time Zone Accuracy
Given patient availability windows are stored in the patient's local time zone And an appointment slot exists in the practice's time zone When ETA Guard evaluates eligibility Then the slot is eligible only if, after converting to patient time, the slot start falls within a configured availability window (boundaries inclusive) And otherwise the patient is excluded with rationale code "OUTSIDE_AVAIL_WINDOW" And the audit record stores the evaluated time zones and converted times
Exclude Patients Not Due for Care Type or With Incompatible Insurance
Given an appointment slot has a defined care type and accepted insurance list And the patient's record includes recall due status and insurance plan When ETA Guard evaluates eligibility Then exclude the patient if not due for the care type with rationale code "CARE_NOT_DUE" And exclude the patient if the insurance plan is not accepted for the slot with rationale code "INSURANCE_INCOMPATIBLE" And do not send an offer when excluded And store rationale codes on the offer record for audit and staff review
Apply Historical Punctuality/No-Show Risk Thresholds
Given configurable thresholds per practice and appointment type (e.g., exclude if >=2 no-shows in last 6 months for same-day offers) And the patient's punctuality and no-show metrics are available When ETA Guard evaluates eligibility Then include the patient only if metrics do not breach the configured thresholds And otherwise exclude with rationale code "HISTORICAL_RISK" And record the metric snapshot and threshold values used in the audit log
Enforce Distance Caps Using Address-On-File Only
Given a configurable maximum distance per practice and appointment type And the patient's address on file and practice location When ETA Guard evaluates eligibility Then compute distance using address data only without device geolocation And if distance > configured cap, exclude with rationale code "DISTANCE_CAP" And if distance <= cap, pass this rule And no GPS or background location data is requested, stored, or processed
Minimum Necessary PHI Access and Audit Logging
Given ETA Guard needs specific fields to evaluate eligibility [address, communication preferences, consent, availability, insurance plan, appointment history] When eligibility evaluation runs Then only the enumerated fields are read and processed And no other PHI fields are accessed And an audit log entry records timestamp, actor "ETA_GUARD", purpose, rule outcomes, rationale codes, datasets accessed, and rule version And audit entries exclude message content and unnecessary identifiers
Rule Configurability per Practice and Appointment Type with Versioning
Given an admin updates rule settings (thresholds, toggles, distance cap, risk criteria) for a practice and appointment type and saves as version "1.4" When ETA Guard evaluates eligibility for that practice and appointment type Then version "1.4" settings are applied And changes take effect within 5 minutes of save And the audit log records rule_version "1.4" And rolling back to the previous version restores the prior settings and behavior
Confidence Scoring & Lead-Time Guardrails
"As a hygienist, I want configurable confidence thresholds and lead-time rules so that only patients likely to arrive on time receive short-notice openings."
Description

Combine ETA, traffic volatility, weather severity, patient reliability signal, and slot prep requirements to produce a 0–100 arrival confidence score. Gate messaging with configurable thresholds per practice, appointment type, and time-of-day. Enforce minimum lead times (e.g., at least X minutes to arrive and complete check-in) and dynamic safety buffers during adverse conditions. Support A/B testing of thresholds, capture reasons for rejections, and expose configuration via admin settings with change history.

Acceptance Criteria
Compute 0–100 Arrival Confidence Score from Multivariate Inputs
Given a candidate appointment slot and patient When the system retrieves real-time distance/ETA, traffic volatility index, weather severity index, patient reliability score, and slot prep/check-in requirements Then it calculates a numeric confidence score between 0 and 100 And Then the score is deterministic for identical inputs within the same 5-minute window And Then the calculation stores an audit record including input values, weightings, timestamp, and resulting score And Then the score is retrievable via API within ≤300 ms at p95
Gate Messaging by Configurable Thresholds (Practice, Appointment Type, Time-of-Day)
Given configured thresholds at practice default, appointment type, and time-of-day windows When a confidence score is evaluated Then the most specific matching threshold is applied (appointment type > time-of-day > practice default) And Then messaging is allowed only if score >= applied threshold And Then threshold values are integers 0–100 and validated on save And Then each decision logs the applied threshold value and rule source
Enforce Minimum Lead Time and Dynamic Safety Buffers
Given a candidate slot When travel ETA + required check-in minutes + slot prep minutes + safety buffer <= minutes until slot start Then the offer is eligible to send; otherwise it is rejected And Given normal conditions (no adverse flags) When evaluating lead time Then the safety buffer equals the configured base buffer And Given adverse conditions (traffic volatility or weather severity above configured triggers) When evaluating lead time Then the buffer increases per configuration (fixed minutes and/or percentage), and the applied buffer is recorded And Then rejections include reason codes INSUFFICIENT_LEAD_TIME, ADVERSE_CONDITIONS, or BOTH
A/B Test Threshold Variants with Guardrails
Given an active A/B test with two or more threshold variants When eligible evaluations occur Then patients are randomly assigned per configured allocation ratios, stratified by practice and appointment type And Then the assigned variant’s threshold is used for gating and cannot go below the configured global minimum threshold And Then assignments and outcomes (sent, accepted, rejected, no-show) are tagged with a variant ID And Then the test can be started, paused, or stopped in admin, with changes effective within 5 minutes
Capture and Expose Rejection Reasons
Given an evaluation results in rejection When logging the decision Then the system stores primary and secondary reason codes with structured details (required_lead_minutes, available_minutes, score, applied_threshold, buffer_applied, missing_data_flags) And Then rejection reasons are queryable via API and visible in admin analytics with filters by date range, practice, appointment type, and reason code And Then at least 95% of rejection logs are available for analytics within 2 minutes
Admin Configuration with Validation and Change History
Given an authorized admin user When updating thresholds, lead-time rules, adverse condition triggers, or buffers Then inputs are validated for ranges, required fields, and conflicts; invalid saves are rejected with messages And Then successful changes are recorded with timestamp, user ID, previous value, new value, scope (practice/appointment type/time-of-day), and optional change reason And Then admins can view chronological change history and revert to any prior version; reversions are also logged And Then changes propagate to evaluation services within 5 minutes and audits include the configuration version ID
Fail-Safe Behavior and Data Gaps Handling
Given any critical input is unavailable or stale beyond TTL (e.g., traffic API timeout, weather data older than 15 minutes) When evaluating eligibility Then the system applies a conservative fallback: block messaging and log reason MISSING_CRITICAL_DATA unless a configured safe default explicitly allows proceed And Then all external API errors/timeouts are recorded with correlation IDs And Then evaluations are idempotent for the same requestId; duplicates do not produce duplicate messages And Then the decision service responds within ≤500 ms at p95; on timeout, no message is sent and the event is logged
HIPAA Compliance, Consent & Data Minimization
"As a compliance officer, I want consent, encryption, and audit safeguards built-in so that ETA Guard protects patient privacy while enabling accurate offers."
Description

Ensure all ETA Guard processing adheres to HIPAA by limiting PHI use to the minimum necessary, encrypting data at rest and in transit, segregating secrets/API keys, and maintaining BAAs with data vendors. Provide patient-friendly consent flows for optional location-based enhancements (e.g., on-demand ETA link), record consent provenance, and allow revocation. Enforce retention limits and access controls, and store audit artifacts for compliance review without exposing sensitive data in logs or dashboards.

Acceptance Criteria
Minimum Necessary PHI for ETA Guard Processing
Given ETA Guard evaluates feasibility for a patient offer, When data is requested, Then only allowed categories are accessed: pseudonymous patient identifier, appointment time, contact channel, and practice location. Given ETA Guard services receive a payload containing disallowed PHI, When processing begins, Then the request is blocked with a 4xx policy error and an alert is created, And no disallowed PHI is persisted. Given data flow monitoring is enabled, When ETA Guard runs, Then access logs show 0 reads of disallowed PHI fields across all requests in the release window.
Encrypt PHI at Rest and In Transit
Given ETA Guard writes PHI to storage, When data is persisted, Then it is encrypted at rest with AES-256 or stronger and keys managed by a centralized KMS, And backups are encrypted. Given ETA Guard transmits PHI between internal services or to covered vendors, When connections are established, Then TLS 1.2+ with strong ciphers is enforced, And plaintext or downgraded connections are refused. Given a service endpoint is misconfigured without TLS, When a call is attempted, Then the call fails and a security alert is issued within 5 minutes.
Secrets and API Keys Segregation and Rotation
Given ETA Guard requires third-party API credentials, When services retrieve credentials, Then they are fetched from a secrets manager via workload identity, And secrets are not stored in code, images, or plaintext environment variables. Given least-privilege access, When API keys are provisioned, Then scopes restrict usage to required endpoints and tenant, And unsuccessful access attempts trigger alerts. Given rotation policy, When 90 days elapse or compromise is detected, Then keys are rotated and previous keys revoked within 15 minutes without service interruption.
BAAs for External Data Vendors
Given a vendor may receive PHI or patient identifiers from ETA Guard, When vendor integration is configured, Then a signed BAA is recorded and the vendor is marked HIPAA-covered before any traffic is permitted. Given a vendor lacks a BAA, When ETA Guard attempts to call the vendor, Then the request is blocked and returns a configuration error without transmitting any patient data. Given a compliance review, When viewing vendor settings, Then the system displays BAA document link, effective dates, and data flow description within two clicks.
Consent Flow for Location-Based ETA Enhancements
Given a patient is offered an on-demand ETA link, When the feature is first invoked, Then a clear consent screen explains purpose, data types, retention, and rights, And no location data is collected unless the patient explicitly opts in. Given consent is granted, When the event is saved, Then the record stores patient identifier, channel, timestamp, consent text version, and locale. Given consent is absent, When staff or automation attempt to trigger location-based enhancements, Then the action is blocked and a consent-required message is shown.
Consent Provenance Recording and Revocation
Given a patient has previously consented, When they reply STOP via SMS, toggle in portal, or staff records revocation, Then location-based processing stops within 5 minutes and the opt-out propagates to all channels. Given consent is revoked, When future messages are prepared, Then no location requests are sent and templates reflect opt-out status. Given an audit request, When viewing the patient’s consent history, Then the system displays grant, updates, and revocation with actor/method, timestamps, and consent text version.
Retention Limits, Access Controls, and PHI-Safe Audit Artifacts
Given ETA Guard stores feasibility inputs and outputs, When the nightly retention job runs, Then raw location coordinates and third-party payloads older than 7 days are purged while aggregated metrics are retained. Given role-based access control, When a user without PHI permissions views ETA Guard data, Then PHI fields are redacted, And PHI access requires explicit role assignment and MFA. Given operational logs and dashboards, When ETA Guard operates, Then no PHI values are recorded; automated weekly DLP scans report 0 PHI findings; and audit artifacts include only hashed or redacted identifiers.
Staff Console & Explainability
"As a scheduler, I want a clear explanation and the ability to simulate or override when appropriate so that I can manage openings confidently and transparently."
Description

Deliver a console that shows why a patient did or did not receive an offer, including key factors (ETA, traffic, weather, availability, preferences) and the computed confidence score. Provide a privacy-safe explanation, quick simulations (“what if we moved the slot by 15 minutes?”), and a limited, auditable override with mandatory reason codes. Integrate directly with SmileCue’s existing queue and messaging views to minimize context switching.

Acceptance Criteria
Decision Rationale Visibility in Queue View
Given a staff user with role Scheduler or Manager is viewing the Queue view When they open the Offer Decision panel for a patient Then the panel displays the decision state (Sent or Suppressed) and decision timestamp in the practice timezone And the computed confidence score is displayed as a number from 0.0 to 100.0 with one decimal place And the evaluated factors at decision time are listed with values: ETA (minutes), distance (mi/km), traffic level (Low/Medium/High), weather condition (e.g., Clear/Adverse), provider availability window (start–end), patient preference matches (channels/time windows) And each factor shows its data source and last refresh time And the displayed decision id equals the backend decision id for that patient and decision time
Threshold Badging and Reasoning for Confidence Score
Given an offer decision is displayed in the panel When the confidence score is below the practice's configured send threshold Then a "Below threshold" badge shows the threshold value and the score And the panel lists the failing constraints with measured deltas (e.g., ETA exceeds slot start by N minutes) When the confidence score is at or above the threshold Then a "Meets threshold" badge is shown with the threshold value and the score And the panel lists the top contributing factors supporting the send decision
Privacy-Safe Explanation and PHI Redaction
Given the panel renders decision rationale for a specific patient When presenting data to staff Then the panel does not display PHI such as full street address, date of birth, SSN, MRN, insurance ID, or diagnosis codes And patient location is shown at city/neighborhood granularity only (no street number) And API responses, logs, and audit entries for this panel exclude or mask the above PHI fields And audit entries contain only: user id, timestamp, action, before/after decision state, reason code, free-text note, pseudonymous patient id
What-If Simulation: Shift Appointment by ±15 Minutes
Given a staff user opens the What-If Simulation for a patient When they select "Move slot by +15 minutes" or "Move slot by -15 minutes" Then the system recalculates the decision and confidence using the adjusted slot and latest factors within 2.0 seconds at p95 And changes in factor values are displayed with deltas relative to the original decision And the simulation state is clearly labeled and does not persist or send messages And the user must explicitly Apply Changes to create any real scheduling change; otherwise the original state remains unchanged on close
Limited Override with Mandatory Reason and Audit
Given a decision is Suppressed and the current user has the Override permission When the user clicks Override Send Then a modal requires selection of a reason code from a managed list and entry of a free-text note between 10 and 250 characters And the Confirm button remains disabled until both fields are complete And on confirmation, an audit record is created with user id, timestamp, pseudonymous patient id, original decision, override action, reason code, note, and request IP And one message send is triggered without altering the underlying model's stored decision And overrides are rate-limited to 5 per user per day and 20 per practice per day (HTTP 429 returned and UI error shown if exceeded) And users without Override permission see the Override control disabled with a tooltip
Seamless Integration in Queue and Messaging Views
Given a staff user is in the Queue or Messaging view When they click the Explain Decision icon for a patient Then an explainability drawer opens on the right without full-page navigation And the list scroll position and selection are preserved And the drawer loads initial content within 1.5 seconds at p95 on broadband and within 3.0 seconds at p95 on LTE And closing the drawer returns keyboard focus to the previously focused element And deep links of the form /queue/:patientId?panel=eta-guard or /messages/:patientId?panel=eta-guard open the drawer directly
Data Freshness and Staleness Warning
Given factor values are displayed in the panel When viewing their freshness Then last-updated timestamps are shown for each factor relative to decision time And maximum allowed ages are enforced: traffic ≤ 5 minutes, weather ≤ 15 minutes, provider availability ≤ 1 minute, patient preferences ≤ 1 minute, location/ETA ≤ 2 minutes And if any factor exceeds its freshness threshold, a warning badge is shown and the confidence score displays a "Stale inputs" tooltip
Observability, Auditing & SLA Monitoring
"As a product owner, I want robust monitoring and audit trails so that we can maintain reliability, prove compliance, and quickly resolve issues."
Description

Instrument ETA Guard with metrics (latency, decision rates, data-source errors), structured event logs with PII minimization, distributed tracing for external API calls, and health checks. Provide alerting for degraded data sources, falling confirmation rates, or rising rejection errors. Generate daily compliance-ready audit reports of offer decisions and rationale codes. Establish SLOs (e.g., 99.9% decision availability, <2s p95 latency) and track error budgets.

Acceptance Criteria
p95 Latency SLO and Alerting
Given ETA Guard processes production decision requests When measuring decision latency over a rolling 30-day window Then p95 latency is < 2000 ms and p99 < 4000 ms And a dashboard displays p50/p95/p99 updated within 60 seconds And an alert fires within 5 minutes if p95 >= 2000 ms for 10 consecutive minutes And the alert auto-resolves when p95 < 2000 ms for 10 consecutive minutes
Decision Availability SLO and Error Budget Tracking
Given ETA Guard receives production decision requests When measuring decision availability over a rolling 30-day window Then availability is >= 99.9% where a request is counted available if a decision (offer or decline) is returned within 5 seconds with HTTP status in {2xx,4xx} And 5xx and timeouts count as unavailable And an error budget of 0.1% is computed and displayed with 1h, 6h, and 24h burn rates And an alert triggers when >= 2% of monthly error budget is consumed within 1 hour or >= 5% within 6 hours
Structured Event Logs with PII Minimization
Given each ETA Guard decision attempt When emitting structured event logs Then logs conform to schema_version=1 with fields: tenant_id, decision_id, timestamp, outcome, rationale_codes[], data_sources[], latency_ms, correlation_id, error_class And no raw PII (name, phone, email, address, DOB) is present; patient identifier is a non-reversible token And an automated PII scanner runs hourly on a 1% log sample and reports 0 critical findings; deployments fail on any critical finding And logs include severity levels and are queryable within 1 minute of ingestion
Distributed Tracing for External API Calls
Given a decision requires calls to distance, traffic, weather, or scheduling APIs When a decision is executed Then a W3C traceparent correlation_id is generated and propagated to all outbound HTTP calls And spans are recorded for each external call with peer.service, host, status_code, and duration And sampling is 100% for errors and 10% for successes And >= 95% of decision requests have a complete trace with parent/child relationships visible in the tracing UI over a 24h period
Data Source Health Checks and Degradation Alerts
Given external data sources are required by ETA Guard When synthetic health checks run every 60 seconds per source Then 5-minute success rate per source is >= 99% And an alert fires within 3 minutes if a source’s 5-minute success rate < 99% or median latency > 1000 ms And ETA Guard marks the affected source as degraded and switches to fallback logic within 60 seconds, emitting rationale_code="DATASOURCE_DEGRADED" And recovery clears the degraded flag after 10 consecutive successful checks
Outcome Trend Alerts: Confirmation Drop and Rejection Error Spike
Given daily operations with >= 200 offers in the last 24 hours When the 24h offer confirmation rate drops by > 20% relative to the 14-day trailing average (with statistical significance p < 0.05) Then a Warning alert is sent within 10 minutes with links to the outcomes dashboard and top rationale codes And when rejection errors with error_class in {"DATASOURCE_UNAVAILABLE","DECISION_ENGINE_ERROR"} exceed 3 standard deviations above the 14-day baseline in a 1h window Then a Critical alert fires within 5 minutes including sample trace links and affected tenant list
Daily Compliance Audit Report Generation and Delivery
Given a scheduled job at 02:00 UTC daily When generating the audit report per tenant Then an encrypted CSV and JSONL are produced with fields: decision_id, timestamp, tenant_id, patient_token, slot_id, outcome, rationale_codes[], consulted_sources[], source_statuses, latency_ms, alerts_triggered[] And a signed hash manifest is included; row counts match metrics within ±1% And the report is stored in a secure bucket with encryption-at-rest and access restricted to the Compliance role And delivery receipt and checksum are logged; failures trigger an alert within 10 minutes And automated schema validation passes 100% and a random 100-record sample shows 0 PII fields

Waitlist Profiles

Patients self-manage waitlist preferences via a secure link: preferred days/times, providers, locations, language, channels, and deposit willingness. Profiles include pediatric caregiver constraints. Offers match preferences, increasing acceptance and reducing opt-outs.

Requirements

Secure Magic-Link Access
"As a patient, I want a secure link to manage my waitlist preferences so that I can update them quickly without creating an account while keeping my health information private."
Description

Implement HIPAA-compliant, single-use magic links for patients to access and self-manage waitlist profiles without account creation. Links are sent via SMS or email, contain no PHI, expire after configurable windows, and are bound to the patient record and device fingerprint where possible. Support optional OTP step-up for sensitive actions (e.g., enabling deposits), rate limiting, revocation, and re-issuance flows. Ensure end-to-end TLS, HSTS, CSRF protection, and replay attack mitigation. Integrate with SmileCue’s messaging services for delivery status, bounce handling, and fallback to alternate channel when the primary fails.

Acceptance Criteria
Single-Use Magic Link Redemption
Given a patient receives a valid magic link via SMS or email, When they open it within the validity window on the issuing device, Then they are authenticated to their waitlist profile without account creation and the token is invalidated immediately upon success. Given the same magic link is used a second time, When attempting access, Then the system returns 401 (invalid/used link), shows a re-issue CTA, and displays no profile data. Given a magic link tied to Patient A, When it is presented for Patient B or any other patient context, Then access is denied and a security audit event is recorded. Given a successful redemption, When reviewing audit logs, Then an entry exists with patient ID, channel, timestamp, device fingerprint hash (if available), and outcome=success.
Configurable Expiration Enforcement
Given tenant policy sets link expiry to 2 hours (default 24 hours), When a new magic link is generated, Then the server-side token TTL is 2 hours and reflected in metadata. Given a link past its expiry, When the patient clicks it, Then the system returns 401 (expired), offers a re-issue option, and ensures the token cannot be reused. Given clock skew of up to ±5 minutes between client and server, When validating expiry, Then the server applies skew tolerance and makes the final determination. Given a server restart or cache flush, When validating a token, Then expiry is enforced from the durable store and not bypassed.
HIPAA-Safe Link Content and Transport Security Controls
Given a generated magic link, When inspecting the full URL (host, path, query), Then no PHI (name, DOB, phone, email, MRN, appointment details) is present and the token is an opaque random value with ≥128 bits entropy. Given outbound SMS/email content, When rendered, Then the body contains no PHI and uses generic language; the link uses the SmileCue-approved domain. Given web access to the magic-link page, When connecting, Then TLS 1.2+ is enforced, HTTP is redirected to HTTPS (301), and no mixed content is loaded. Given site security headers, When responses are inspected, Then HSTS max-age ≥ 15552000 with includeSubDomains is set, secure/HttpOnly/SameSite attributes are set on cookies, and CSP blocks inline scripts where applicable. Given state-changing requests (e.g., saving profile changes), When submitted, Then CSRF tokens are required and validated; requests lacking valid tokens are rejected with 403.
Device Fingerprint Binding and OTP Step-Up for Sensitive Actions
Given the first successful redemption on a device, When device fingerprinting is available, Then the token is bound to that fingerprint and subsequent redemptions from a different device require OTP verification. Given a device mismatch or fingerprint unavailable, When accessing the link, Then an OTP (6 digits, 5-minute TTL, max 5 attempts) is sent via the original channel with automatic fallback to the alternate channel on failure. Given a patient toggles deposit willingness (sensitive action), When attempting to save, Then OTP step-up is enforced even on the same device unless the tenant explicitly disables step-up for this action. Given OTP validation outcomes, When OTP succeeds, Then the action completes and is audited; when OTP fails or times out, Then the action is not applied and the prior state remains unchanged.
Rate Limiting and Replay Mitigation
Given a patient requests a magic link, When more than 3 requests are made within 15 minutes for the same patient and channel, Then the API returns 429 with a Retry-After header and no additional messages are sent. Given token redemption attempts, When more than 5 invalid token submissions occur from the same IP/device within 10 minutes, Then further attempts are blocked for 30 minutes and logged as throttled. Given a valid token is redeemed, When any subsequent request reuses the same token (replay), Then the server returns 401 and records a replay-detected security event with IP/device details. Given rate limit windows elapse, When the window resets, Then counters automatically clear and normal operation resumes.
Revocation and Re-Issuance Handling
Given an outstanding magic link exists, When an office user revokes it or the patient requests a new link, Then all prior unredeemed tokens for that patient are immediately invalidated and cannot be used. Given a re-issued link, When generated, Then it adheres to current tenant expiry policy, binds on first redemption to the new device, and prior tokens remain blacklisted. Given a revoked/expired link is clicked, When landing on the page, Then the user sees a non-specific expired/revoked message with a re-issue CTA and no profile data exposure. Given audit requirements, When revocation or re-issuance occurs, Then an audit entry records actor (system/patient/staff), timestamp, and reason (revoked/reissued/expired).
Messaging Delivery Status, Bounce Handling, and Channel Fallback
Given SMS is primary and email is fallback, When SMS send returns undelivered/bounced within 60 seconds, Then the system sends the email variant exactly once and correlates both messages to the request. Given a primary channel delivery receipt is received as Delivered, When updating status, Then no fallback is attempted and the message status is marked Delivered in SmileCue. Given both channels fail to deliver within 5 minutes, When evaluating outcome, Then the request is marked Failed, a dashboard alert is created, and no further retries are attempted for that request. Given unsubscribe/STOP and bounce semantics, When a channel is flagged as opted-out or hard-bounced, Then it is suppressed for future sends and the alternate channel is used if available.
Preference Data Model & Validation
"As an office manager, I want structured patient waitlist preferences so that the system can reliably match openings and reduce manual coordination."
Description

Design and implement a normalized data schema for waitlist profiles capturing preferred days (by weekday), time windows, providers, locations, languages, communication channels, deposit willingness (boolean and optional limit/notes), and pediatric caregiver constraints. Include field-level validation (e.g., non-overlapping time windows, valid provider/location IDs, language codes), versioning for auditability, and default values per practice. Support soft-deletes, historical snapshots for rollbacks, and partial updates. Expose typed APIs for create/read/update with optimistic concurrency to prevent overwrites.

Acceptance Criteria
Create Profile with Defaults and Pediatric Constraints
Given a practice with configured defaults for languages, communication channels, deposit policy, and timezone When a client creates a profile via POST /waitlist-profiles with valid preferred_days (by weekday), time_windows, providers, locations, languages, channels, deposit_willingness, optional deposit_limit and deposit_notes, and optional pediatric_caregiver_constraints Then the API returns 201 with a typed payload containing id, version=1, created_at, updated_at, and the full resolved profile And omitted optional fields are populated with the practice defaults and returned in the response And deposit_willingness=true permits an optional deposit_limit (>= 0 and <= practice.max_deposit) and optional deposit_notes (<= 500 chars) And deposit_willingness=false requires deposit_limit=null and deposit_notes=null; any provided values are rejected with 400 and field-level error codes And pediatric_caregiver_constraints, when provided, must include caregiver_availability windows that pass the same weekday/time-window validations; otherwise 400 with structured validation errors
Non-Overlapping Time Windows by Weekday
Given a profile containing multiple time windows per weekday in the practice timezone When validation is executed on create or update Then each window must have start < end and be contained within a single weekday And no two windows within the same weekday overlap; adjacency (e.g., 09:00–10:00 and 10:00–11:00) is allowed And times must conform to HH:mm 24h format; invalid formats or out-of-range values cause 400 with per-item error paths And normalized storage preserves minute precision in the practice timezone
Reference Integrity for Providers, Locations, Languages, and Channels
Given provider_ids, location_ids, languages, and channels are supplied on create or update When the API validates the payload Then every provider_id and location_id must exist, be active, and belong to the same practice as the profile; otherwise 400 with the offending IDs And languages must be valid BCP 47 tags supported by the practice; unknown codes yield 400 with code=invalid_language And channels must be a non-empty subset of {sms, email, voice} and enabled at the practice; disabled or unknown channels yield 400 with code=invalid_channel And duplicate IDs or values in any list are rejected with 400 code=duplicate_value
Versioning, Snapshots, and Rollback
Given a profile is created When the profile is created it is stored as version=1 with an immutable audit snapshot (who, when, changes) And each successful update creates a new immutable snapshot and increments the version by 1 Then GET /waitlist-profiles/{id}?version=n returns the exact historical snapshot for version n And POST /waitlist-profiles/{id}/rollback with toVersion=n creates a new version containing the data from snapshot n (without mutating snapshot n), increments version, and returns the new current profile
Optimistic Concurrency on Update
Given a client reads a profile and receives version=v (and ETag matching v) When the client PATCH/PUTs with If-Match: v (or body.version=v) Then the update succeeds only if the stored version still equals v, returning 200 and version=v+1 And if the stored version != v, the API returns 409 Conflict with the current version and no changes applied
Soft Delete and Restore
Given an existing profile When DELETE /waitlist-profiles/{id} is called Then the profile is soft-deleted (is_deleted=true, deleted_at set), a new version is created, and the endpoint returns 204 And soft-deleted profiles are excluded from matching queries by default and from standard list endpoints unless include_deleted=true is provided And POST /waitlist-profiles/{id}/restore clears is_deleted, creates a new version, and returns 200 with the restored profile
Partial Updates and Field-Level Validation
Given PATCH /waitlist-profiles/{id} with a subset of fields When the request is processed Then only provided top-level fields are updated; omitted fields remain unchanged And array fields provided are replaced atomically (no merge); full validation is applied to updated fields and any dependent cross-field rules And explicit null clears optional fields that allow null; attempting to null required fields yields 400 code=required And unknown or type-mismatched fields yield 400 with field-level error details And the response returns the fully materialized profile with incremented version
Mobile-first Preference Manager
"As a patient on the go, I want an easy mobile interface to update when and how I can come in so that I receive offers I can actually accept."
Description

Deliver a responsive, accessible (WCAG 2.1 AA) web UI for patients to review and edit waitlist preferences on mobile devices. Pre-fill existing preferences, provide guided inputs (chips for days, sliders/time pickers, provider/location selectors), and inline validation/errors. Include multi-language UI matching the patient’s language preference, timezone detection for time windows, progressive save with offline tolerance, and clear confirmations with the ability to revert changes. Integrate with SmileCue theming and brand settings per practice.

Acceptance Criteria
Responsive Mobile UI, WCAG 2.1 AA, and Practice Theming
- Given a mobile device with viewport width between 320px and 414px, When the Preference Manager loads, Then content fits within the viewport without horizontal scrolling and tappable targets are at least 44x44px. - Given the device orientation changes between portrait and landscape, When the UI reflows, Then no content overlaps, truncates critical text, or obscures controls. - Given a user enables a screen reader, When navigating the form, Then all inputs have accessible names, roles, states, described-by relationships for errors, and focus order matches the visual order. - Given a user sets high-contrast mode or prefers-reduced-motion, When the UI renders, Then color contrast meets at least 4.5:1 and non-essential animations are disabled. - Given a practice with configured brand theme (logo, colors, typography), When the page loads with that practice context, Then the theme is applied and minimum contrast requirements remain satisfied.
Prefill Existing Preferences and Editable Fields
- Given a patient with saved waitlist preferences, When opening the link, Then all corresponding fields pre-populate with the latest server values and a loading skeleton is shown until data resolves within 2 seconds. - Given no saved value exists for a field, When the form renders, Then the field displays an explicit neutral state (e.g., "Select..." or "None selected") without defaulting to an option. - Given server values change after link issuance, When the form loads, Then the most recent server values are displayed and a non-blocking notice "Preferences updated" appears within 1 second. - Given the patient edits values, When Save is invoked, Then only changed fields are sent to the API and the server persists them successfully, returning a 200/204 response.
Guided Inputs and Inline Validation for Preferences
- Given day-of-week chips are displayed, When the patient selects days, Then selections toggle on tap and at least one day or "Any day" must be selected before Save is enabled. - Given time window controls (slider or time pickers), When the patient chooses a start and end time, Then the end time cannot precede the start time and times snap to 15-minute increments. - Given provider and location selectors, When the patient searches or scrolls, Then only providers/locations authorized for the practice are listed and multiple selections are supported. - Given channel toggles (SMS, email, voice), When the patient toggles a channel off, Then that channel is excluded from outreach and the setting is persisted. - Given a deposit willingness toggle, When the patient sets willingness, Then the value is saved as a boolean and can be cleared. - Given the patient is flagged as pediatric, When the form loads, Then caregiver constraint fields are visible and required; otherwise they are hidden. - Given a field has invalid input, When focus leaves the field, Then an inline error message appears, is announced via aria-live, and Save is disabled until all errors are resolved.
Multi-language UI Auto-selection and Switching
- Given the patient’s language preference is available (per practice configuration), When the page loads, Then all UI labels, helper text, and validation messages render in that language and the html lang attribute is set accordingly. - Given the patient changes the language from a language switcher, When a new language is selected, Then all strings re-render within 500ms without a full page reload and the choice is saved to the patient profile. - Given translated assets are missing for a string, When the UI renders, Then the default fallback language is used and the string is included in translation logs for remediation.
Timezone Detection and Time Window Conversion
- Given the device provides a timezone, When the page loads, Then the patient’s local timezone is detected and used to display time window selections with an indicator of the practice timezone. - Given the patient selects a time window, When the preferences are saved, Then times are converted and stored in the practice timezone with the correct UTC offset, including during DST transitions. - Given the patient’s local day differs from the practice day due to timezone offset, When times cross midnight, Then the correct day-of-week mapping is applied and reflected in the summary.
Progressive Save with Offline Tolerance
- Given network connectivity is available, When the patient changes a field, Then the change is auto-saved within 1 second and a “Saved” indicator appears. - Given network connectivity is lost mid-session, When the patient continues editing, Then changes are queued locally in secure, session-scoped storage and no PHI is written to persistent storage. - Given connectivity is restored, When queued changes exist, Then they sync automatically in order using ETags/If-Match to prevent overwrite; on conflict, the patient is prompted to resolve with clear options. - Given an auto-save fails, When a retry is attempted, Then the UI retries up to 3 times with exponential backoff and displays a persistent error banner with a manual Retry action.
Confirmation Summary and Revert Changes
- Given the patient saves changes, When the server confirms success, Then a confirmation banner appears with a timestamp and a summary of changed fields. - Given the patient taps “Undo changes,” When invoked within the current session, Then all changes made since the session start are reverted to the prior saved state and persisted. - Given an undo is executed, When the server confirms success, Then the confirmation banner updates to indicate “Reverted” and the UI reflects the previous values. - Given changes are saved, When audit logs are queried, Then an entry exists capturing patient ID, fields changed (names only), channel “Web,” and timestamps.
Pediatric Caregiver Constraints
"As a caregiver of a pediatric patient, I want to specify my availability and contact preferences so that appointment offers respect school and custody constraints."
Description

Extend profiles to support pediatric scenarios: designate caregiver(s), relationship, required presence, preferred contact order, school-hour constraints, and custody schedules (e.g., alternating weeks, specific days). Allow multi-contact notifications with consent tracking and require confirmation from an authorized caregiver when the patient is a minor. Enforce rules in matching (e.g., exclude school hours unless explicitly allowed) and in offer sending (e.g., send to both caregivers when required). Include age-based gating and automated transition when the patient reaches adulthood.

Acceptance Criteria
Capture and Validate Pediatric Caregiver Profile
Given a minor patient profile, when a caregiver is added, then the system must allow 1–4 caregivers with fields: full name, relationship (enum), legal custody (sole|joint|none), required presence (Yes|No), authorized to confirm (Yes|No), preferred contact order (1..n). Given required fields are incomplete or enum values invalid, when saving the profile, then the save is rejected with field-level errors and no partial data is persisted. Given the patient is a minor, when saving the profile, then at least one caregiver must have authorized to confirm = Yes or the save is blocked. Given the profile is saved, when auditing, then an audit log entry must record the actor, timestamp, and before/after diff of caregiver list.
Contact Order and Multi-Channel Notification Rules for Minors
Given a minor patient with multiple caregivers and defined preferred contact order, when a waitlist offer is generated, then notifications are sent in order and via only the channels each caregiver has consented to. Given any caregiver is marked required presence = Yes, when an offer is sent, then that caregiver receives the offer regardless of contact order, provided channel consent exists. Given no caregiver has consent for a proposed channel, when attempting to send via that channel, then the system must skip that channel, try the next consented channel per caregiver, and log the suppression. Given an offer is sent, when reviewing logs, then delivery attempts and outcomes are recorded per caregiver, channel, timestamp, and correlation ID.
Enforce School-Hour Constraints in Matching
Given a minor patient without explicit permission for school hours, when generating candidate appointment slots, then exclude slots that start between 08:00 and 15:00 Monday–Friday in the practice location’s local time. Given the patient has allow school hours = Yes, when generating candidate slots, then include school-hour slots alongside other eligible slots. Given a slot crosses a boundary into school hours, when evaluating eligibility, then the slot is excluded if its start time is within the school-hour window. Given matching is completed, when inspecting the match rationale, then the presence or absence of the school-hours rule is recorded for each included/excluded slot.
Custody Schedule-aware Offer Eligibility
Given a minor patient with custody schedule = alternating weeks (caregiver A on odd ISO weeks, caregiver B on even ISO weeks), when generating offers for a date in week N, then only slots in week N are offered and notifications are targeted to the caregiver assigned for week N (plus any required presence caregivers). Given custody schedule = specific days (e.g., caregiver A: Mon/Tue, caregiver B: Thu/Fri), when generating offers, then only slots on the specified days are eligible and notifications are targeted accordingly. Given no custody schedule is configured, when generating offers, then both caregivers are considered eligible subject to other constraints. Given a custody schedule change is saved, when generating subsequent offers, then the new rules take effect immediately and are reflected in the match rationale.
Authorized Caregiver Confirmation Requirement
Given the patient is a minor, when an offer is accepted, then booking is not finalized until at least one caregiver with authorized to confirm = Yes confirms via a verified channel. Given any caregiver is marked required presence = Yes and does not have authorized to confirm, when an offer is accepted, then booking is not finalized until that caregiver acknowledges required presence AND an authorized caregiver confirms. Given a caregiver without authorization attempts to confirm, when processing the confirmation, then the system records the response but does not finalize the booking and requests confirmation from an authorized caregiver. Given all required confirmations are received within the offer validity window, when finalizing, then the appointment is booked and an audit entry records who confirmed, timestamps, and source channels; otherwise the offer expires without booking.
Age-based Gating and Automatic Adult Transition
Given a patient’s DOB indicates age < 18 on the appointment date, when evaluating constraints, then pediatric rules (caregiver notifications, school hours, custody, confirmation requirements) are enforced. Given the patient turns 18, when the system processes the daily transition job, then pediatric rules are disabled, caregiver confirmation is no longer required, and the patient is set as the primary contact for offers. Given there are pending offers created before the 18th birthday and not yet confirmed, when the patient turns 18, then those offers are updated to require only patient confirmation and caregivers are notified of the change per consent settings. Given the transition occurs, when auditing, then a transition record includes previous guardianship state, new state, affected offers, and notification outcomes.
Preference-driven Offer Matching
"As a scheduler, I want the system to match openings to patient preferences so that offers are relevant and acceptance rates improve."
Description

Create a rules-and-scoring engine that evaluates open appointment inventory against patient waitlist profiles. Hard filters (provider, location, deposit willingness) gate eligibility; soft preferences (days/times, language) contribute to a match score. Support tie-breaking, batching, and throttling to prevent offer spam, with configurable minimum match thresholds per practice. Include explainability (reason codes) for why an offer was or wasn’t sent, and real-time recalculation when preferences or inventory change. Integrate with SmileCue’s branching logic to adapt follow-ups based on responses.

Acceptance Criteria
Hard Filter Eligibility Enforcement
Given a waitlist profile with provider(s), location(s), and deposit_willing=true/false And an open slot with provider, location, and deposit_required=true/false When the engine evaluates the slot for the patient Then the slot is eligible only if provider and location intersect the profile AND (deposit_required=false OR deposit_willing=true) And if any hard filter fails, the slot is excluded and the decision is recorded as not_sent with primary_code=HARD_FILTER_MISMATCH
Soft Preference Scoring and Minimum Threshold
Given Practice A has min_match_threshold=0.70 and preference weights days=0.4, times=0.3, language=0.3 (configurable) And a slot passes hard filters for Patient P When the engine computes the match score (normalized 0..1) Then the score uses the configured weights and preference matches And the offer is eligible only if score >= 0.70 And the computed score and matched_soft_preferences are persisted with the offer decision
Deterministic Tie-Breaking for Candidate Ranking
Given two or more patients are eligible for the same slot with equal match scores (within 0.001) When ranking candidates for the initial offer Then the engine applies tie-breakers in order: earlier waitlist_joined_at, higher patient_priority (if present), earlier preferred_time proximity, stable_random(patient_id, slot_id) And rerunning the evaluation with unchanged inputs within 10 minutes yields the same ranking order
Batching and Throttling Controls
Given a patient has multiple eligible slots within a 1-hour evaluation window When sending offers Then the system consolidates up to 3 top-ranked slots into a single outbound message (configurable) And at most 1 outstanding offer exists per patient at any time And a patient receives no more than 3 offers in any rolling 7-day window (configurable) And practice-level sends do not exceed 100 offers/hour and 20 offers/minute (configurable) And excess offers are queued and retried FIFO at the next allowed window
Explainability with Reason Codes
Given any evaluation outcome (sent or not_sent) When recording the decision Then reason_codes includes primary_code, category, message, and inputs for both sent and not_sent And for sent offers, include match_score and matched_hard_filters And for not_sent, include a blocking primary_code in {HARD_FILTER_MISMATCH, BELOW_THRESHOLD, THROTTLED, RATE_LIMITED, DUPLICATE, INVENTORY_EXPIRED} And the reason_codes are returned via API, shown in the admin UI, and written to the audit log
Real-Time Recalculation on Profile or Inventory Change
Given a patient updates preferences or an appointment slot is created/updated/cancelled When the change event is received by the engine Then impacted matches are recomputed within 5 seconds And any pending offers that now fall below threshold are cancelled (if not accepted) with primary_code=SUPERSEDED And new eligible offers are created subject to batching and throttling rules And rankings remain consistent with tie-breaker rules
Branching Logic Integration on Offer Responses
Given a patient receives an offer generated by the matching engine When the patient Accepts, Declines, or does not respond within the practice-configured SLA Then SmileCue workflows can reference variables {match_score, slot_id, provider_id, location_id, reason_codes} And Accept places a hold on the slot for the configured hold window and suppresses further offers to the patient until resolved And Decline records the reason (if provided) and prevents re-offering the same slot within 14 days (configurable) And No Response triggers one follow-up according to cadence, without violating throttling rules
Channel & Quiet Hours Control
"As a patient, I want control over when and how I’m contacted so that I’m not disturbed at inconvenient times and can opt into my preferred channels."
Description

Respect patient-selected communication channels (SMS, email, voice) and set per-channel opt-in/out, quiet hours, timezone-aware delivery windows, and frequency caps. Implement fallback cascades (e.g., SMS then email) and practice-level defaults. Enforce compliance (TCPA, HIPAA) by honoring consent status and including opt-out mechanisms. Expose configuration in admin and ensure delivery orchestration integrates with matching and offer sends.

Acceptance Criteria
Per-Channel Opt-In/Out Enforcement
Given a patient has SMS: opt-out, Email: opt-in, Voice: opt-out When a waitlist offer is queued Then the system sends via Email only and suppresses SMS and Voice Given consent is missing or revoked for all channels When any offer is generated Then no message is sent, the event is logged with reason "no_consent", and the offer is marked unsendable Given a message is sent via SMS or Voice Then the message contains an opt-out mechanism (e.g., "Reply STOP" for SMS; IVR keypress for Voice) and includes no PHI in clear text; any PHI is accessible only after secure-link authentication Given a patient opts out by replying STOP/UNSUBSCRIBE or using the IVR opt-out When the event is received Then the corresponding channel consent is set to false within 60 seconds and further sends on that channel are blocked Given an API-triggered send When consent has changed within the last minute Then the latest consent state is honored at send time
Quiet Hours & Timezone-Aware Delivery Windows
Given a patient timezone is determined by priority: patient profile > patient phone area-code inference > practice default When scheduling a send Then the schedule uses the resolved timezone (IANA/Olson) for all time calculations Given quiet hours are 21:00–08:00 local and Voice delivery window is 09:00–18:00 local When a send is attempted outside the allowed window Then it is deferred to the next allowed minute within the earliest applicable window Given a DST transition day in the patient’s timezone When scheduling sends Then no duplicate sends occur and no sends are scheduled outside configured local windows due to offset changes Given the patient has no explicit delivery window When scheduling sends Then the practice-level default window is applied Given both patient and practice windows exist and conflict When scheduling sends Then patient windows take precedence, constrained by legal limits (e.g., Voice calls not before 08:00 or after 21:00 local)
Frequency Caps per Channel
Given frequency caps are configured as SMS: 2/day, 5/week; Email: 3/day, 10/week; Voice: 1/day, 3/week (all values configurable) When a send would exceed the applicable cap for that channel and timeframe Then the send is suppressed and an audit entry is recorded with reason "frequency_cap" Given counters reset at local midnight and track a rolling 7-day window When counting prior sends Then the counts include all automated waitlist offers for that channel in the patient’s local timezone Given an authorized admin applies a one-time "bypass caps" override with justification When scheduling the next send Then exactly one additional send is permitted and the override is captured in the audit log with user, timestamp, and justification
Fallback Cascade Logic
Given the cascade order is [SMS, Email, Voice] When the primary channel fails due to opt-out, hard bounce, carrier error, or no response within 15 minutes (configurable) Then the system attempts the next channel in order without violating quiet hours or frequency caps Given any channel records Delivered or the patient responds/acts on the offer When evaluating the cascade Then all remaining attempts are canceled and the cascade stops Given the cascade would exceed 3 total attempts (configurable max) When evaluating further attempts Then no additional attempts are made and the offer is marked "cascade_exhausted" with audit detail
Practice Defaults vs Patient Overrides
Given practice-level defaults for channels, quiet hours, delivery windows, and caps are configured When a patient has no explicit preferences Then practice defaults are applied for that patient Given a patient sets their own channel preferences and quiet hours When scheduling and sending offers Then the patient-specific settings override practice defaults for that patient only Given "Use practice defaults" is toggled on in the patient profile When saving Then any patient-specific overrides are cleared and future sends use the current practice defaults, with an audit record of the change
Admin Configuration & Audit Trail
Given a user with role "Practice Admin" When accessing Communications Settings Then they can configure per-channel opt-in text, quiet hours, delivery windows, frequency caps, and fallback order with server-validated constraints (e.g., start < end, allowed ranges) Given a user without configuration permission When viewing Communications Settings Then configuration fields are read-only or hidden Given any configuration or consent change is saved at practice or patient scope When the save completes Then an immutable audit record is created capturing user, timestamp, scope, before/after values, and reason/source (e.g., "SMS STOP", "Verbal consent 2025-09-23") Given HIPAA minimum necessary rules When rendering message previews in the admin UI Then no PHI is shown in clear text; previews display placeholders and secure-link indicators
Orchestration Integration with Matching and Offer Sends
Given the matching engine selects a patient-slot pairing When the delivery orchestration prepares an offer Then it retrieves patient/practice channel preferences, consent, quiet hours, delivery windows, caps, and cascade order to compute the eligible channels and schedule Given a send is deferred due to quiet hours or frequency caps When persisting the job Then a pending job is stored with wake time at the next allowed minute in the patient’s local timezone Given the offer expires before the next allowed window When evaluating eligibility Then no send is made and the pairing is skipped with reason "expired_window" Given delivery outcome events (delivered, bounced, responded, opted-out) When processing events Then orchestration updates offer state, triggers cascade or stop conditions accordingly, and records outcomes for reporting
Audit Trail & Consent Capture
"As a compliance officer, I want a complete audit trail and consent records for waitlist preferences so that we can demonstrate regulatory compliance and resolve disputes."
Description

Record immutable, timestamped audit events for all profile views and changes, including actor (patient/staff), method (magic link/portal), IP/device metadata, prior and new values, and correlation to message/offer IDs. Capture explicit consents for communications and deposit willingness with language, version, and checkbox attestation. Provide export/search for compliance reviews and surface a readable change history to authorized staff. Define data retention policies aligned with HIPAA and practice requirements.

Acceptance Criteria
Immutable Audit Event Logging for Profile Changes
Given a patient is authenticated via a magic link to edit their Waitlist Profile And existing preference values are on record When the patient submits changes to one or more fields Then the system must write an append-only audit event containing: event_type=profile_update, profile_id, patient_id, actor_type=patient, method=magic_link, timestamp (UTC, ms precision), source_ip, user_agent/device_fingerprint, prior_values, new_values, message_id (if present), offer_id (if present) And the event must include a cryptographic hash and previous_event_hash to enable tamper detection And attempts to modify or delete the event via any API/UI must be denied and logged And if the audit store is unavailable, the event must be queued with an idempotency key and persisted within 5 minutes with at-least-once delivery and no lost fields
Audit Logging for Profile Views by Staff
Given an authorized staff member views a patient's Waitlist Profile in the portal When the profile page is rendered Then an audit event must be recorded with: event_type=profile_view, staff_user_id, actor_type=staff, method=portal, timestamp (UTC, ms), source_ip, user_agent/device_fingerprint, profile_id, patient_id And the event must not include PHI field values or prior/new values And repeated page refreshes by the same user within 60 seconds must be de-duplicated into a single view event
Explicit Consent Capture and Versioning
Given the patient is presented with consent checkboxes for SMS, email, voice, and deposit willingness in their selected language And the consent text is tied to a unique content_version_id When the patient explicitly checks one or more boxes and submits Then a consent record must be created per consent type with: consent_type, status=granted/withdrawn, language_code, content_version_id, timestamp (UTC, ms), actor_type, method, source_ip, user_agent/device_fingerprint, attestation=true And unchecked boxes must not be auto-granted; submission must be blocked if required consents are missing with a clear validation message And existing consent history must be preserved by appending new versioned records rather than overwriting prior records And for pediatric patients, caregiver attestation must capture caregiver_name, relationship, and attest_on_behalf=true
Search and Export for Compliance Reviews
Given an authorized Compliance role user accesses the Audit Search & Export page When the user filters by date_range, patient_id, profile_id, actor_type, staff_user_id, event_type, method, message_id, and offer_id Then matching results must be returned within 3 seconds for up to 10,000 events and be paginated And the user can export the filtered results to CSV and JSON; exported files must be encrypted at rest and provided via a signed download link that expires within 24 hours And each export action must create an audit event capturing filter summary, record count, requester, and timestamp And exported records must include all captured audit fields except secrets/tokens and conform to a published schema
Readable Change History in Staff UI
Given an authorized staff member opens the Change History tab for a patient's Waitlist Profile When the history loads Then the UI must display a chronological list with human-readable diffs per field showing before -> after, actor, method, timestamp, message_id/offer_id (if present), source_ip (masked to /24), and device label And the staff member can filter by field name, event type (view/update/consent), and date range, and expand an entry to view the raw audit payload And access to the Change History tab must be role-restricted and each access must itself be audited as event_type=profile_history_view
Data Retention and Legal Hold Enforcement
Given a practice-level retention policy is configured in years (minimum 6 to meet HIPAA) And a subset of audit and consent records exceed the retention period When the nightly retention job runs Then records older than the policy must be permanently purged from primary storage and scheduled for purge from backups within 30 days And purge operations must create audit events recording date ranges, counts, and the policy applied And any records under active legal hold must be excluded from purge until the hold is released And after purge, search/export must not return purged records and integrity checks on remaining audit chains must pass

Offer Composer

Auto-builds concise, multilingual offers with one-tap confirm, optional secure deposit/form links, and a clear expiration timer. Can include +/- 15-minute alternates where allowed. Personalized, urgency-aware messages convert quickly and write back to the calendar instantly.

Requirements

Multilingual Offer Templates
"As an office manager, I want ready-to-use multilingual offer templates that auto-personalize safely so that I can reach patients in their preferred language without risking compliance or delays."
Description

Provide a library of concise, customizable offer templates in multiple languages (e.g., English, Spanish, French) that auto-select based on patient preference or profile data. Templates support channel-specific constraints (SMS/email/voice), include PHI-safe merge fields (first name, provider, date/time, location) with redaction rules, and embed compliance disclosures. Authors can toggle optional components (deposit prompt, forms link, alternates, expiry text) and preview across devices. The system enforces tone, length, and reading-level guidelines, validates links, and logs versions for auditability. Integrates with SmileCue’s patient profile, consent, and opt-out settings to ensure HIPAA-compliant, culturally appropriate messaging.

Acceptance Criteria
Auto-select Language Based on Patient Profile with Safe Fallbacks
- Given a patient languagePreference is "es" and a Spanish template exists, When an offer is composed, Then the Spanish variant auto-selects and is shown in preview. - Given languagePreference is unset and the practice default is "en", When an offer is composed, Then the English variant auto-selects. - Given languagePreference is "fr-CA" and only a base "fr" variant exists, When an offer is composed, Then the base "fr" variant is selected and the fallback reason is logged with user/patient IDs and timestamp. - Given no matching variant exists for the derived language, When composing, Then the author must choose an available language before Save and the choice is logged. - Given the author manually overrides the auto-selected language, When Save occurs, Then a justification note is required and captured in the audit log. - Then date/time and address formatting in the preview follows the selected locale conventions (e.g., 24h vs 12h, month/day order).
Channel-Specific Constraints and Disclosures Enforcement
- Given channel = SMS, When previewing, Then character and segment counts are displayed and must be <= the configured maximum; if exceeded, Save is blocked with a clear error. - Given channel = Email, When previewing, Then subject length <= configured limit and the required footer disclosure is present before Save is allowed. - Given channel = Voice (TTS), When previewing, Then estimated read duration <= configured max seconds and the oral disclosure is included before Save is allowed. - Given any channel, When composing, Then the channel- and locale-specific compliance disclosure snippet auto-inserts and cannot be removed by the author. - Given SMS/MMS, When composing, Then carrier-required opt-out language (e.g., "Reply STOP to opt out") is included and counted toward length/segments.
PHI-Safe Merge Fields and Redaction Rules
- Given a template editor, When inserting merge fields, Then only approved fields are available: first_name, provider, date_time, location; all others are blocked with an explanatory message. - Given an unapproved merge field is attempted via paste or import, When validating, Then the system rejects Save and highlights the offending field. - Given a permitted merge field has no value for the patient, When previewing, Then the field is replaced with a safe generic phrase (e.g., "your appointment") and Save is allowed without exposing PHI. - Given logging and versioning, When saving or previewing, Then no PHI beyond approved fields is written to logs; masked values are used where applicable. - Given generated links (forms/deposit), When validating, Then URLs are HTTPS, return HTTP 200–399 within 3 seconds, and contain no PHI in path or query; violations block Save with a specific error.
Optional Components Toggle and Device Previews
- Given the author toggles Deposit Prompt = On, When previewing, Then a secure HTTPS deposit link appears for SMS/Email and is omitted for Voice unless configured for IVR; link validation must pass before Save. - Given the author toggles Forms Link = On, When validating, Then the link passes HTTPS and reachability checks; otherwise Save is blocked and the field is highlighted. - Given Alternates = On and practice policy allows alternates and the calendar has availability at ±15 minutes, When previewing, Then up to two alternate times populate; if not available or not allowed, the alternates section is automatically omitted without error. - Given Expiry Text = On with a valid expiry timestamp, When previewing, Then the localized expiry appears (e.g., "Offer expires Tue 3:00 PM"); if the timestamp is in the past, Save is blocked. - Given device previews are requested, When loading, Then SMS shows segment count and truncation warnings, Email shows mobile and desktop layouts, and Voice plays TTS sample; each preview renders within 2 seconds or shows a retry message.
Tone, Length, and Reading-Level Validation
- Given template content per language, When validating, Then the measured reading level is <= the configured threshold for that language; otherwise Save is blocked with guidance. - Given tone analysis, When validating, Then tone meets configured rules (professional, friendly, urgency-aware, non-alarmist); violations block Save with highlighted phrases. - Given total content per channel, When validating, Then length including disclosures and toggled components remains within configured limits; if exceeded, the system suggests reductions and blocks Save until resolved. - Given locale-specific prohibited phrases, When validating, Then none are present; any matches are flagged and must be resolved before Save.
Versioning and Audit Logging for Template Changes
- Given an edit is saved, When saving, Then a new version is created with version ID, UTC timestamp, editor ID, language variant, channel, and a change summary; the diff is stored. - Given version history is requested, When querying, Then the last 100 versions return within 2 seconds and exclude PHI beyond approved fields. - Given a restore is initiated, When confirming, Then the selected version is restored as a new version and the restore source is recorded. - Given an attempted delete, When actioned, Then hard-delete is disallowed; templates may only be archived with status changes logged.
Consent, Opt-Out, and Compliance Gatekeeping
- Given a patient lacks SMS consent, When channel = SMS is selected, Then sending is disabled and a banner explains consent requirements; the first eligible channel is suggested. - Given a patient has opted out of a channel, When composing for that channel, Then the system prevents queueing/sending and logs the attempt with user ID, timestamp, and channel. - Given multiple channels are enabled, When validating before Send, Then per-channel consent, opt-out, and disclosure checks pass; otherwise Send is blocked with a consolidated error list. - Given locale/culture mappings, When selecting a template, Then only culturally appropriate variants are listed by default; overrides require justification and are audited.
One-Tap Confirmation & Decline
"As a patient, I want to confirm or decline an appointment with one tap so that I can quickly respond without logging in or making a call."
Description

Enable patients to confirm or decline an offered appointment with a single tap from SMS or email, without requiring account login. Deep links carry signed, expiring tokens tied to the specific appointment and patient, support ADA/WCAG accessibility, and prevent duplicate submissions. Upon action, the system immediately acknowledges the choice, triggers appropriate follow-ups (e.g., deposit prompt, reschedule link), and updates internal state to prevent further outreach for that slot. Includes IVR fallback for voice messages and graceful degradation when the deep link expires or is forwarded.

Acceptance Criteria
One-Tap Confirm from SMS/Email Deep Link
Given a patient receives an offer via SMS or email containing a signed, expiring deep link tied to a specific appointment and patient And the token is valid, unexpired, and not previously used When the patient taps the link and selects Confirm without logging in Then the confirmation page loads within 2 seconds (p95) and clearly displays appointment details, office name, date/time, timezone, and action buttons in the offer language And the system records the confirmation with an idempotency key and updates the appointment status to Confirmed in the calendar within 3 seconds (p95) And a success acknowledgement is shown to the patient within 1 second and a confirmation SMS/email is sent within 10 seconds And required follow-ups are triggered (e.g., secure deposit link or pre-visit form) and are included on the success screen and via message And all future outreach for the confirmed slot is suppressed and the offer is closed to additional recipients And an audit log entry captures patient identifier, appointment ID, token ID, timestamp, channel, locale, and IP/call metadata
One-Tap Decline with Reschedule Path
Given a patient opens a valid, unexpired deep link for an offered appointment When the patient selects Decline Then the system updates the appointment offer record as Declined-by-Patient and writes back to the scheduling system within 3 seconds (p95) And an acknowledgement is shown within 1 second confirming the decline And the patient is presented with a reschedule path (inline options or a secure scheduling link) matching the offer language And the declined slot is released for re-offer or general availability per practice rules And the outreach sequence for this slot to this patient is halted And an audit event is stored including optional decline reason, if provided
Duplicate Submission and Forwarded Link Handling
Given an offer link is used after a prior Confirm or Decline was already recorded When any user attempts another action via the same link or a forwarded copy Then the system rejects the action as a duplicate without altering the calendar and returns a non-destructive message indicating the offer is no longer actionable And the UI presents safe next steps (e.g., Request a new link, Call office) without exposing PHI beyond what was in the original offer And the response is idempotent with HTTP 409/422 semantics on APIs and a unique idempotency key logged And forwarded links cannot be used to act on behalf of a different patient; the token is bound to the intended patient and appointment and blocks mismatched device/browser attempts And all attempts are captured in audit logs with reason=duplicate_or_forwarded
Expired or Invalid Token Graceful Degradation
Given an offer deep link is opened after token expiration or with an invalid signature When the patient taps the link Then no PHI or appointment details are displayed And the page clearly states the link has expired or is invalid and provides a one-tap option to request a fresh link or a click-to-call office number And the system returns 410 (expired) or 401 (invalid) on APIs without revealing existence of the appointment beyond the original message context And no changes are made to the calendar or outreach state And a new link request, if initiated, is fulfilled within 30 seconds (p95) and logged with reason=expired_reissue
ADA/WCAG Accessible One-Tap Page
Given a patient accesses the confirmation page on mobile or desktop with assistive technologies or keyboard-only navigation When the page loads Then the page meets WCAG 2.1 AA: contrast >= 4.5:1, focus order logical, all actions keyboard operable, visible focus indicators, labels with ARIA for confirm/decline, and tap targets >= 44x44 px And screen readers (NVDA, JAWS, VoiceOver) correctly announce button roles, statuses, and the success/failure messages via aria-live regions And the page respects reduced motion settings and supports zoom to 200% without loss of content or functionality And the page renders in the offer language with lang attributes and RTL support where applicable And accessibility checks pass automated scans (axe/lighthouse) with zero critical issues and manual spot-checks documented
IVR Fallback: Touch-Tone Confirm/Decline
Given a patient receives a voice (IVR) offer or cannot use the deep link When the patient calls the provided number and enters the offer code or follows the press-1-to-confirm, press-2-to-decline prompts Then the system reads back appointment details and supports confirm or decline via DTMF in the selected language And on confirm/decline the calendar is updated within 5 seconds (p95), a spoken acknowledgement is played, and an SMS/email receipt is sent within 10 seconds And the IVR flow enforces rate limiting and replay protection per offer code and blocks duplicate submissions And all interactions are logged with call SID, DTMF choices, timestamps, and outcomes
Calendar Write-Back, Concurrency, and Outreach Suppression
Given multiple recipients or channels may act on the same offered slot When two or more confirmations are attempted within a short window Then only the first valid action succeeds; subsequent attempts receive a clear message that the slot is no longer available and are offered alternates or a reschedule link And the winning action updates the scheduling system within 3 seconds (p95) and emits an event consumed by Offer Composer to cancel pending outreach for that slot across all channels And the system guarantees idempotent write-backs with conflict detection at the appointment ID level and records resolution outcomes in audit logs And metrics for success/latency/error are captured to monitoring with p95/p99 SLIs and alerts on breach
Secure Deposit & Forms Links
"As a patient, I want a secure, quick way to pay a required deposit and complete forms from the offer so that I can finalize my appointment without extra steps or phone calls."
Description

Attach optional, secure links for deposit collection and pre-visit forms within the offer. Links use short-lived, single-use tokens, enforce HTTPS, and isolate PHI in a HIPAA-compliant portal. Payment flows are PCI-DSS compliant and support major cards, Apple Pay, and Google Pay, with automatic receipts and refunds per office policy. Forms pre-fill known data, validate signatures, and sync completed artifacts to the patient record. The composer conditions inclusion of deposit/forms based on appointment type and payer rules, and clearly indicates when they are required before confirmation.

Acceptance Criteria
Single-Use, Short-Lived Secure Links
Given an offer is generated with deposit and/or forms links for a specific patient and appointment When the patient opens a link over HTTPS within the configured token TTL Then the portal loads bound to that patient and appointment and the token state changes to in-use Given a tokenized link When it is opened after successful completion or more than once Then access is denied with a non-PHI message and HTTP 410 and the token is not revalidated Given a tokenized link When the TTL has elapsed Then access is denied with HTTP 410 and the offer indicates the link is expired without revealing PHI Given a tokenized link When the token is tampered with or replayed Then access is denied and an audit event with source IP, user agent, and timestamp is recorded
HTTPS Enforcement and PHI Isolation
Given any deposit or forms link When it is requested over HTTP Then it is redirected to HTTPS and HSTS is enabled for the domain with includeSubDomains Given the PHI portal When resources load Then all requests use TLS 1.2+ with no mixed content and cookies are Secure, HttpOnly, and SameSite=Lax or stricter Given the PHI portal When rendering or navigating Then no PHI appears in URL path or query parameters and responses include Cache-Control: no-store and a restrictive CSP that only allows required first-party and payment-provider domains Given a signed-in portal session When there is 15 minutes of inactivity Then the session auto-expires and requires a new secure link to continue without exposing partial form data
PCI-DSS-Compliant Deposit Collection with Cards and Wallets
Given a deposit is required by office policy When the patient proceeds to payment Then payment is processed in a PCI-DSS compliant flow (SAQ A scope) and SmileCue systems never store raw PAN Given a supported device and region When payment methods are presented Then Visa, Mastercard, American Express, Apple Pay, and Google Pay are offered when available with graceful fallback to card entry Given a successful payment When the transaction is approved Then an itemized receipt including amount, last4, transaction ID, timestamp, and office policy reference is automatically sent to the patient and stored in the patient record Given a refund is initiated by authorized staff per policy When processed Then a partial or full refund is issued through the original payment method, a receipt is sent, and the patient record updates with the refund details
Conditional Inclusion and Gating of Deposit/Forms
Given appointment type and payer rules When composing an offer Then the composer includes deposit and/or forms links only when permitted and displays Required or Optional labels accordingly Given deposit or forms are required before confirmation When the patient attempts to confirm without completing the required items Then confirmation is blocked and the UI clearly indicates the outstanding steps with a single-tap call-to-action Given deposit and forms are optional When the patient confirms Then confirmation succeeds and optional links remain available until offer expiry Given payer type prohibits deposits When composing an offer Then no deposit link is included in the offer
Pre-Visit Forms Pre-Fill, E-Sign, and Sync
Given known patient demographics, insurance, and health history When forms are opened Then fields pre-fill with available data and the patient can edit prior to submission Given required fields and e-signature capture When the patient submits Then client- and server-side validation enforce completeness and the e-signature captures name, signature, timestamp, and consent with IP/device metadata Given successful form submission When processing completes Then a read-only PDF (and structured JSON) artifact is stored in the PHI portal and synced to the patient record with status, version, and timestamp Given the offer language preference When rendering forms Then form labels, prompts, and receipts display in that language
Confirmation and Calendar Writeback
Given an offer with required deposit and/or forms When all required steps are completed and the patient taps Confirm Then the appointment is marked confirmed and written back to the practice calendar within 5 seconds, the slot is locked, and the offer status updates to Completed Given two patients attempt to confirm the same slot concurrently When both submit within a short interval Then only the first successful completion confirms the appointment and the second receives a conflict message with alternate options if available Given transient network issues during confirmation When the confirm action is retried Then the system processes idempotently without duplicate payments, forms, or calendar entries
Expiration Alignment and Audit Logging
Given an offer with tokenized deposit/forms links When the offer expiration timer elapses Then all associated tokens immediately become invalid and display an expired message without revealing PHI Given any access, payment, confirmation, refund, or settings change event When it occurs Then an immutable audit log entry is recorded with timestamp, actor, event type, context (patient and appointment IDs), and outcome and is retrievable by authorized staff Given repeated failed token validations or payment declines When attempts exceed the configured threshold Then the portal rate-limits further attempts and notifies authorized staff of potential abuse
Expiration Timer & Urgency Logic
"As a hygienist, I want offers to expire and escalate automatically so that scarce chair time is filled quickly without manual follow-up."
Description

Display a clear expiration timestamp and optional countdown within messages and the offer page, localized to the patient’s timezone. On expiry, automatically rescind the offer, notify the next eligible patient or revert the slot to general availability, and update messaging accordingly. Urgency-aware logic escalates reminders at configurable intervals, throttles after-hours outreach, and adapts language to indicate diminishing availability. All state transitions are auditable, idempotent, and resilient to clock skew and daylight saving changes.

Acceptance Criteria
Patient-Localized Expiration Timestamp and Countdown
Given an offer with server UTC expiration T and a patient timezone, When the offer is rendered in SMS/email text and on the offer page, Then the expiration timestamp displays in the patient’s local time with timezone abbreviation and the countdown updates at 1 Hz and matches server time within ±1 second. Given the patient device clock is skewed by up to ±5 minutes, When the offer page loads, Then the countdown is derived from server time and remains accurate within ±1 second of the server-defined TTL. Given the patient timezone is unknown, When rendering the expiration timestamp, Then default to the practice timezone and include the timezone abbreviation in the displayed time. Given the countdown reaches zero, When the timer completes, Then the countdown stops at 00:00 and does not display negative values.
Auto-Rescind on Expiry with Slot Reallocation and Messaging Updates
Given an offer with expiration T, When server time reaches T, Then the offer state transitions to Expired within 5 seconds, the confirmation link becomes inactive, and clicking it shows an "Offer expired" page without booking. Given the configuration is set to notify the next eligible patient on expiry, When an offer expires, Then a new offer is sent to the next eligible patient within 30 seconds and the calendar reflects the reallocation attempt. Given the configuration is set to revert the slot to general availability on expiry, When an offer expires, Then the slot is released to general availability within 15 seconds and all pending messages for the expired offer are canceled. Given a late confirmation attempt occurs after expiry, When the patient clicks the confirm link post-expiry, Then no appointment is booked, an expiry notification is sent to the patient, and the event is logged with reason code "expired".
Configurable Urgency Escalation Reminders
Given an offer with expiration T and configured reminder offsets (e.g., 6h, 2h, 30m before T), When each offset threshold is crossed, Then a reminder is sent at that time using the corresponding urgency template and channel settings. Given an offer is confirmed or canceled before T, When future reminders remain scheduled, Then all pending reminders for that offer are canceled within 10 seconds. Given max_reminders is configured, When the number of calculated offsets exceeds max_reminders, Then only the earliest max_reminders reminders are sent and others are not scheduled. Given a reminder send attempt fails transiently, When a retry policy is configured, Then the reminder is retried per policy without sending duplicate content and all attempts are logged.
After-Hours Outreach Throttling by Patient Local Time
Given quiet hours are configured (e.g., 20:00–08:00) in the patient’s timezone, When a reminder’s scheduled time falls within quiet hours, Then SMS and voice messages are deferred to the next permissible window and the deferment is logged; email is sent or deferred according to configuration. Given a reminder would be deferred beyond the offer’s expiration, When the scheduled time is within quiet hours and no permissible window exists before T, Then the reminder is suppressed, not sent, and the suppression reason "after_hours" is logged. Given quiet hours are updated, When future reminders are recalculated, Then the new schedule respects the updated quiet hours without sending any reminder during restricted times.
Diminishing Availability Language Based on Time Remaining
Given language templates are mapped to time-remaining thresholds (e.g., >12h neutral, 2–12h moderate, <2h high urgency), When an offer message is generated at any point before expiration, Then the template selected matches the current time remaining and includes the localized expiration timestamp. Given time remaining crosses a threshold between scheduled reminders, When the next reminder is generated, Then the message uses the higher-urgency template appropriate to the new time band. Given alternates are limited or nearly exhausted, When composing the message, Then the text includes diminishing-availability phrasing (e.g., "last chance") per configuration and does not overstate availability.
Auditable State Transitions with Complete Traceability
Given any offer state change occurs (Created, Offered, ReminderQueued, ReminderSent, Confirmed, Expired, Rescinded, Reallocated, Released), When the transition is processed, Then an immutable audit entry is recorded with UTC timestamp, actor/system, previous_state, new_state, offer_id, slot_id, patient_id, correlation_id, and related message/calendar identifiers. Given an administrator requests the audit trail for a specific offer, When the audit endpoint is queried, Then the system returns an ordered list of all transitions with no gaps and includes reason codes for suppressions and failures. Given a patient interacts with an expired link, When the event is handled, Then the audit log includes the event, HTTP status outcome, and the mapping to the already Expired state without creating a new state transition.
Idempotency and Resilience to Clock Skew and DST
Given duplicate expiry jobs with the same idempotency key are received within a 5-minute window, When they are processed concurrently, Then only one Expired transition is committed and downstream notifications/calendar updates occur at most once. Given a DST change occurs in the patient’s timezone during the offer’s validity window, When timestamps and countdowns are rendered before and after the transition, Then they display correct local civil time with accurate remaining duration and no one-hour drift or duplication. Given server and client clocks differ by up to 10 minutes, When determining send times and enforcing expiration, Then server time is authoritative and sends/expiry do not occur earlier or later than 1 minute relative to server time. Given a confirmation request arrives within 30 seconds after T due to network delay, When the server-stamped confirm event time is evaluated, Then the system accepts only confirmations stamped before T and rejects others with reason "expired", ensuring consistency across retries.
+/- 15-Minute Alternates
"As a patient, I want nearby alternate times presented with the offer so that I can choose a better fit without calling the office."
Description

Offer adjacent time options within ±15 minutes when allowed by provider, resource, and payer rules. Retrieve real-time availability from the connected calendar, respecting buffers, room/chair resources, provider breaks, and travel time. Selecting an alternate holds the slot temporarily, handles race conditions, and confirms or releases it on decision or timeout. The composer adjusts messaging to present alternates succinctly in SMS and more richly in email, with accessibility-compliant selection controls on the offer page.

Acceptance Criteria
Rule-Eligible Alternate Generation
Given a base appointment offer and patient context And provider, resource, and payer configurations allow ±15-minute alternates for the appointment type When the Offer Composer generates alternates Then it proposes up to two adjacent start times within ±15 minutes of the base start time And alternates are rounded to the provider’s scheduling increment and never outside clinic hours And alternates are not generated when any governing rule forbids alternates for the case And the base slot is always included as an option alongside any alternates
Real-Time Availability and Constraint Validation
Given a connected calendar with live availability, buffers, room or chair resources, provider breaks, and travel time When the Offer Composer queries for ±15-minute alternates Then only alternates that satisfy duration plus pre and post buffer requirements are returned And only alternates with all required shared resources available are returned And no alternates overlap provider breaks, blocked time, or travel time And the availability lookup completes within the configured SLA (e.g., ≤ 2 seconds at p95)
Temporary Hold and Concurrency Safety
Given a patient selects an alternate time from the offer page When the selection request is received Then the system creates a hold on that exact slot for the configured TTL (e.g., 5 minutes) And any concurrent attempt to hold or book the same slot receives a clear conflict response without creating a second hold And the hold is visible in audit and expires automatically at TTL, releasing the slot within 5 seconds of expiration And a patient can have only one active hold per appointment at a time
Confirmation, Release, and Calendar Writeback
Given a held alternate slot When the patient confirms the selection Then the appointment is created on the connected calendar and resources within 1 second p95 And all other holds for that appointment are released immediately And a confirmation message is sent and the offer is marked accepted When the patient declines or the hold times out Then no appointment is created and the hold is released within 5 seconds, with the offer state updated accordingly And all actions are recorded with timestamp, actor, and outcome for audit
Channel-Specific Messaging and Localization
Given SMS delivery is used When alternates are included Then the SMS presents at most two alternates with concise time formats and a one-tap deep link to confirm Given Email delivery is used When alternates are included Then the email presents the alternates with richer details including duration, provider, location, and a clear confirm button And all content is localized to the patient’s preferred language with fallback to English And all times display with the patient’s time zone abbreviation and date to avoid ambiguity
Accessible Offer Page Selection Controls
Given the offer page renders alternate options When navigated via keyboard only Then all selection controls are operable with standard keys, have visible focus indicators, and a logical tab order And controls expose accessible names and states via ARIA for screen readers And color contrast for text and controls meets or exceeds WCAG 2.2 AA And error or conflict messages are announced to assistive technologies and visible without hover
Expiration Timer and Timeout Consistency
Given alternates are displayed with an expiration timer When a hold is created Then the on-page countdown matches the server hold TTL to the second and never shows time after expiration And on expiration, the UI disables confirm actions and reflects that the slot is no longer available within 2 seconds And if the hold TTL is extended or released server-side, the timer and UI state update within 2 seconds to stay consistent across devices and channels
Calendar Write-Back & Conflict Resolution
"As an office manager, I want confirmations to write back to the calendar reliably and safely so that scheduling stays accurate without double-booking or manual edits."
Description

Instantly synchronize confirmed, declined, and alternate selections back to the practice management system/EHR calendar with atomic, audited operations. Implement optimistic concurrency (ETags/versions), retries with backoff, and compensating actions to resolve conflicts and prevent double-booking. Support webhooks to notify downstream systems (billing, reminders) and queue updates for offline scenarios. Provide an admin activity log showing who/what changed each appointment and why, with exportable audit trails for compliance.

Acceptance Criteria
Atomic Calendar Write-Back on Offer Responses
Given a patient selects Confirm, Decline, or an Alternate time from an Offer for appointment A When the system performs write-back to the PMS/EHR Then for Confirm, appointment A is created/updated to status=Confirmed with correct start/end time, provider, and location And for Decline, any tentative hold on A is removed and availability is restored And for Alternate, appointment A reflects the selected alternate time and original hold is released And the write-back completes within 2 seconds p95 and 5 seconds p99 And an audit entry is recorded with correlation_id, action, actor, previous_value, new_value, timestamp, and reason And if external calendar write fails, no calendar change occurs and a failure audit entry with error_code is recorded
Optimistic Concurrency, Retries, and Compensating Actions
Given the PMS/EHR exposes a version/ETag for the target appointment/slot When a write-back is attempted with a stale version/ETag and receives 409/412 Then the system retries with exponential backoff (base 200ms, jitter, max 5 attempts or 10s total) And on success the audit includes resolved_by=retry and attempt_count And if retries exhaust, the system performs a compensating action: refreshes latest state, marks the offer response as Conflict, emits Appointment.Conflict webhook, and does not create an overlapping booking And the admin UI displays a conflict banner within 30 seconds of final failure
Double-Booking Prevention and Temporary Holds for Alternates
Given two or more patients attempt to confirm the same slot or a +/-15-minute alternate within a 5-minute window When their responses are processed concurrently Then at most one appointment is confirmed for that slot And all other attempts are rejected within 1 second of conflict detection with no PMS/EHR double-booking And temporary holds placed for alternates expire and auto-release after 5 minutes of inactivity with an audit entry And released holds immediately restore slot availability for subsequent offers
Offline Queueing and Eventual Consistency for Calendar Updates
Given the PMS/EHR API is unreachable (timeouts >3s or HTTP 5xx) during write-back When the outage is detected Then the operation is enqueued to a durable, encrypted queue with an idempotency key and correlation_id And the admin UI marks the appointment as Pending Write-Back within 5 seconds And retries occur with exponential backoff for up to 24 hours And after connectivity restores, queued operations for the same appointment_id are delivered in order and succeed within 10 minutes And messages that still fail after the retry window are moved to a dead-letter queue and an alert is raised
Webhook Notifications to Downstream Systems
Given a calendar write-back succeeds, fails, or conflicts When the event is generated Then a webhook is sent with event_type in {Appointment.Confirmed, Appointment.Declined, Appointment.Updated, Appointment.Conflict} And the payload includes appointment_id, practice_id, correlation_id, version, and occurred_at (UTC) And each webhook is HMAC-SHA256 signed and includes an Idempotency-Key header And deliveries are retried with exponential backoff until a 2xx is received or up to 24 hours And duplicate deliveries with the same idempotency key are accepted by receivers without side effects And event ordering is preserved per appointment_id
Admin Activity Log and Exportable Audit Trail
Given any calendar change attempt (success or failure) When the operation completes Then an immutable activity log entry is written capturing who (user/service), what (action), when (UTC ms), why (reason/source), previous_value, new_value, outcome, error_code (if any), request_id, and correlation_id And PHI fields are masked per policy and access is role-restricted And the log is searchable/filterable by date range, practice, appointment_id, user, and outcome And exports to CSV and JSON for a selected date range up to 100k rows complete within 30 seconds and include a SHA-256 checksum And export downloads are access-logged and recorded in the audit trail
Personalization & A/B Optimization
"As a practice owner, I want offers tailored and tested for my patient base so that confirmation rates increase and no-shows decrease over time."
Description

Personalize offer content (greeting, urgency phrasing, CTA order, channel) based on patient preferences, history, and no-show risk while honoring consent and privacy settings. Provide a built-in A/B testing framework with configurable variants, randomization, holdouts, and statistical reporting on confirmation, deposit, and no-show outcomes. Surface per-cohort insights and recommended defaults to improve conversion over time. All data processing minimizes PHI exposure, uses role-based access controls, and supports opt-out and deliverability health monitoring.

Acceptance Criteria
Greeting, Language, and CTA Personalization Based on Patient Profile
Given a patient profile with preferred name, preferred language, consented channels, and no‑show risk tier When the Offer Composer generates an offer Then the message uses the patient’s preferred name or a configurable fallback if unavailable And the message is rendered in the patient’s preferred language or the practice default if unsupported And urgency phrasing is selected from approved templates matched to the patient’s risk tier And CTA order and primary channel are selected by the personalization model from among only consented channels And no message is sent via any channel without active consent And optional ±15‑minute alternates are included only when enabled by practice settings And the one‑tap confirmation link is tokenized and expires at the offer’s expiration time
A/B Test Setup with Variants, Randomization, and Holdout
Given an experiment with named variants (min 2, max 5), a holdout group (optional), and traffic allocations totaling 100% When the experiment is activated Then patients are randomly assigned to variants according to allocation with ±2% tolerance once each arm has ≥1000 recipients And assignment for a patient persists for 30 days or until experiment end, whichever is sooner And holdout receives the current default template and channel policy And variant assignment respects each patient’s consented channels and quiet hours And experiment configuration and activations are audit‑logged with user, timestamp, and changes
Statistical Reporting on Confirmation, Deposit, and No‑Show Outcomes
Given an active or completed experiment with at least 200 recipients per arm and a 14‑ to 30‑day observation window When a user views the experiment report Then the report shows per‑variant confirmation rate, deposit completion rate, and 7‑day and 30‑day no‑show rates with 95% confidence intervals And pairwise significance is computed via two‑proportion tests with p‑values; results with p<0.05 are highlighted And underpowered results (power <80% given observed effects) are flagged And filters allow slicing by channel, language, risk tier, and new vs returning And recipients who opted out before delivery are excluded from denominators And the report shows data freshness timestamp and can be exported to CSV
Cohort Insights and Recommended Defaults
Given cohorts defined by language, new vs returning, payer type (if available), and no‑show risk tier When a cohort reaches ≥200 recipients per variant in the last 30 days Then the system surfaces the top‑performing variant per cohort with absolute and relative uplift vs cohort baseline and associated p‑value And a recommendation to set a new cohort default is generated only when uplift is significant (p<0.05) and sustained across 2 consecutive weekly windows And applying a recommendation requires explicit user action and is audit‑logged And users can preview projected impact based on last 30 days before applying
PHI Minimization and Secure Processing
Given Offer Composer generation and analytics processing Then only minimum necessary PHI is processed: first name, language, consent flags, channel preference, risk tier, and appointment date/time window And analytics stores hashed patient IDs and event timestamps; message bodies are not stored in analytics And system logs redact PHI placeholders from message content And all links are signed, tokenized, and expire with the offer; tokens cannot be reused after expiration And service accounts use least‑privilege scopes restricted to required datasets; access attempts outside scope are denied and logged And an automated data scan confirms no prohibited fields (full DOB, full address, clinical details) exist in analytics stores
Role‑Based Access Control for Personalization and Analytics
Given roles Admin, Office Manager, Dentist, and Hygienist When accessing personalization settings and A/B reports Then Admin and Office Manager can view cohort and patient‑level drill‑downs with contact details masked by default and unmasking gated by permission And Dentist and Hygienist see only aggregated cohort metrics with no patient identifiers And CSV exports are restricted to Admin and Office Manager And unauthorized access attempts are blocked and recorded in the audit log with user, resource, and reason
Consent, Opt‑Out, and Deliverability Health Enforcement
Given per‑channel consent and opt‑out status with timestamps When sending offers Then messages are sent only on channels with active consent and within configured quiet hours And recognized opt‑out keywords immediately suppress future sends on that channel within 60 seconds And hard bounces, spam complaints, and carrier blocks automatically suppress the affected channel for the patient and reduce the channel’s deliverability score And the system retries once via an alternate consented channel when the primary fails And a deliverability dashboard shows daily send, delivered, bounce, complaint, and block rates by channel with alert thresholds; alerts are generated when thresholds are exceeded And suppressed channels can be reinstated only after explicit opt‑in is received and recorded

Flex Nudge

When no perfect match exists, politely asks adjacent confirmed patients to shift earlier/later within a safe window to free a precise gap. Respects risk scores, consent, and caregiver needs, then reconciles changes automatically—recovering chair time without overbooking.

Requirements

Smart Gap Detection & Opportunity Modeling
"As a scheduling coordinator, I want the system to surface precise gap-creation opportunities by shifting adjacent patients safely so that I can fill openings without manual trial-and-error."
Description

Automatically identifies fillable gaps when no perfect appointment match exists by analyzing the live schedule, provider availability, operatory/equipment constraints, and appointment durations. Computes viable micro-shifts among adjacent confirmed patients within configurable safe windows to produce exact-fit openings. Ranks opportunities by impact and risk using patient no-show probability, consent status, caregiver and transportation notes, and appointment-type restrictions. Generates a non-destructive plan that preserves buffers, lunch/breaks, room turnover, and pre/post-op holds, and never creates overlaps or double-booking. Exposes a preview and API payload containing proposed adjustments, affected patients, and expected recovered chair time for review or automatic execution.

Acceptance Criteria
Detect Fillable Gaps Without Perfect Match
Given a live schedule with provider availability, operatory and equipment constraints, and appointment durations And a target appointment type and duration D for which no perfect slot currently exists When Smart Gap Detection runs for the specified schedule scope Then it returns one or more gap opportunities that can be created via micro-shifts or an empty set with reason "no viable opportunity" And each opportunity includes a proposed opening with start_time, end_time, provider_id, operatory_id, and required_duration == D And all proposed openings occur within clinic hours and provider availability windows
Compute Viable Micro-Shifts Within Safe Windows
Given confirmed adjacent patients around the targeted area on the same provider and operatory And safe windows configured at org/location/provider/patient levels with documented precedence When the engine computes micro-shifts to create an exact-fit opening of duration D Then no patient is moved earlier or later beyond their effective safe window And only adjacent confirmed patients are shifted; non-adjacent patients remain unchanged And the sum of shifts produces an opening whose duration equals D with 0-minute deviation And no patient is moved across breaks, lunch, holds, or outside provider availability And equipment/resource constraints remain satisfied at the new times
Honor Risk, Consent, Caregiver, and Appointment-Type Restrictions
Given patient nudge consent flags, no-show probability scores, caregiver/transportation notes with time bounds, and appointment-type shiftability rules When evaluating candidate micro-shifts Then any patient without nudge consent is excluded from shifting And any patient with no-show probability above the configured threshold is excluded And appointments marked non-shiftable by type or tags are not moved And patients with caregiver/transport constraints are not moved outside their noted windows And each opportunity records the constraints it satisfied; candidates violating any rule are discarded
Preserve Buffers, Turnover, Breaks, and Prevent Overlaps
Given a proposed non-destructive plan of appointment time adjustments When validating schedule integrity Then all pre-op and post-op buffers remain intact per configuration And required room turnover durations between appointments are preserved And lunch, breaks, and pre/post-op holds remain unmodified And no overlaps or double-bookings are introduced across providers, operatories, or equipment And the plan does not alter stored appointment times until explicitly executed
Rank Opportunities by Impact and Risk
Given a set of viable opportunities When computing rankings Then each opportunity receives an impact score combining expected recovered chair time and risk penalties (e.g., patient risk, number and magnitude of shifts) And opportunities are sorted by descending impact score; ties are broken by lower total patient disruption, then earliest start_time And an optional top_k parameter limits the number of returned opportunities without changing scores And each opportunity includes expected_recovered_chair_time_minutes and a risk_grade label
Expose Preview and API Payload of Proposed Adjustments
Given a generated plan of proposed adjustments When presenting the preview UI and responding via API Then the preview lists for each affected appointment: appointment_id, patient_id, before_time, after_time, delta_minutes, provider_id, operatory_id, and constraint_notes And the API returns 200 with JSON containing plan_id, generated_at, schedule_scope, opportunities[], and recovered_chair_time_total_minutes And each opportunity includes proposed_opening {start_time, end_time, provider_id, operatory_id}, affected_patients[], and non_destructive == true And generating or retrieving the preview/API payload applies no changes to the live schedule
Safeguard Data Privacy and Auditability (HIPAA-aligned)
Given that PHI may be included in patient notes and payloads When generating opportunities and payloads Then only minimum necessary PHI fields are included in the API response and preview And all access to the preview and payload is authorized and audited with user_id, timestamp, and action And patient consent state and changes are traceable in the audit trail for each proposed adjustment And no PHI is logged in plaintext in system logs
Eligibility & Constraint Engine
"As an office manager, I want the system to only ask appropriate patients to move so that we respect consent, clinical constraints, and patient circumstances."
Description

Determines which confirmed patients can be nudged based on explicit message and schedule-change consent, configurable maximum shift minutes per provider and appointment type, minimum notice windows, per-patient nudge frequency caps, and exclusion flags (e.g., sedation, pre-medication, lab case dependency, special equipment). Evaluates caregiver availability windows, transportation constraints, ADA/accessibility needs, patient time-of-day preferences, and risk thresholds. Produces deterministic eligibility decisions with reason codes for transparency. Integrates with the consent registry and PMS/EHR to pull appointment metadata and returns a filtered, ranked list of candidates ready for messaging or staff review.

Acceptance Criteria
Consent and Schedule-Change Authorization Applied
Given a confirmed appointment and evaluation time T When the engine evaluates eligibility Then include only patients with active message opt-in and schedule-change consent effective at T (from the consent registry) And if consent is missing, expired, or revoked, mark Not Eligible with reason CONSENT_MISSING, CONSENT_EXPIRED, or CONSENT_REVOKED And record consent source and consent_version_id in the decision payload
Provider and Appointment-Type Shift Limits Enforced
Given configured maximum shift minutes per provider and per appointment type When computing allowable earlier/later shift windows Then allowable_shift_range_minutes must not exceed those maxima in either direction And if the required shift exceeds the max, mark Not Eligible with reason MAX_SHIFT_EXCEEDED And shifts must not cross provider, location, or operatory assignment boundaries; else Not Eligible with reason PROVIDER_OR_ROOM_MISMATCH
Minimum Notice and Nudge Frequency Caps Respected
Given a configured minimum notice window for the appointment type and a per-patient nudge frequency cap (N per rolling period P) When evaluating a patient Then only consider patients where appointment_start - T >= minimum_notice; else Not Eligible with reason MIN_NOTICE_VIOLATION And exclude patients who reached the cap within period P based on nudge history; Not Eligible with reason FREQUENCY_CAP_REACHED And update nudge history only upon message dispatch, not at eligibility computation
Exclusion Flags and Clinical/Operational Dependencies Honored
Given appointment metadata indicates any exclusion flags (sedation, pre-medication, lab case dependency, special equipment, isolation) When evaluating eligibility Then exclude such appointments; Not Eligible with reason EXCLUSION_FLAG_[FLAG_NAME] And for lab case dependency, require lab_ready_at <= proposed shifted start; else Not Eligible with reason LAB_CASE_NOT_READY And for special equipment, require equipment availability in the target slot; else Not Eligible with reason EQUIPMENT_UNAVAILABLE
Caregiver, Transportation, Accessibility, Preferences, and Risk Applied
Given caregiver availability windows, transportation constraints, ADA/accessibility needs, patient time-of-day preferences, and a risk score When proposing shift windows Then all proposed windows must lie within caregiver and transportation availability; else Not Eligible with reason CAREGIVER_UNAVAILABLE or TRANSPORT_WINDOW_VIOLATION And target operatory/location must satisfy recorded accessibility needs; else Not Eligible with reason ACCESSIBILITY_CONSTRAINT And if preference is hard, exclude windows outside preference; if soft, apply a configurable scoring penalty And exclude patients with risk_score >= configured threshold; Not Eligible with reason RISK_THRESHOLD_EXCEEDED
Deterministic Decisions and Reason Codes
Given identical inputs (appointments, consents, configuration) and evaluation time T When the engine is executed repeatedly Then eligibility status, reason codes, scores, and candidate order must be identical across runs And each decision includes a primary decision (Eligible or Not Eligible) and at least one reason code from a controlled vocabulary And each decision includes rule_set_version and evaluated_at timestamps
Integration, Data Validation, and Ranked Output
Given connectivity to PMS/EHR and the consent registry When fetching appointment and patient data Then required fields (patient_id, appointment_id, provider_id, start/end, appointment_type, location/operatory) must be present; else Not Eligible with reason MISSING_METADATA_[FIELD] And transient integration failures result in Not Eligible with reason INTEGRATION_ERROR and a retryable=true flag And each eligible candidate output includes patient_id, appointment_id, provider_id, allowable_shift_range_minutes, candidate_target_windows, score (0-100), rank, and reason_codes And candidates are sorted by score descending with deterministic tiebreaker by appointment_id ascending And proposed windows must not overlap existing bookings or create overbooking based on the current schedule snapshot
Multichannel Polite Nudge Messaging
"As a patient, I want a polite, easy way to say yes or no to moving my appointment so that I can help the clinic without inconvenience or confusion."
Description

Composes and delivers courteous, context-aware requests over SMS, email, and voice with clear response options (accept, decline, suggest alternatives) and secure short links. Tailors templates by shift size/direction, appointment type, and language, with configurable tone and branding. Enforces HIPAA minimum necessary PHI, includes explicit opt-out language, and adheres to TCPA quiet hours and frequency throttles. Supports adaptive follow-ups if no response by SLA, per-channel fallbacks, and rate limiting per practice. Captures delivery, open, and response events to drive branching logic and maintain a complete communication record.

Acceptance Criteria
SMS Nudge with Consent, Opt-Out, and Quiet Hours Enforcement
Given a patient with documented SMS consent and no SMS opt-out on file, when a Flex Nudge is triggered, then the SMS is sent only if current local time is outside configured quiet hours (default 20:00–08:00), otherwise it is queued until quiet hours end. Given a configured per-patient SMS frequency cap of 2 nudges per rolling 24 hours, when attempting to send a new SMS nudge, then the system blocks the send if the cap would be exceeded and records suppression_reason="sms_frequency_cap". Given minimum necessary PHI policy, when composing the SMS, then the body includes practice name, appointment date and time window, and shift request (earlier/later by X minutes) and excludes diagnosis/procedure codes, clinician names, full DOB, and MRN. Given practice-configured tone (friendly/formal) and language preference for the patient, when generating content, then the selected SMS template matches tone and language; if the language template is unavailable, then the content falls back to English and logs fallback_language="en". Given TCPA opt-out requirements, when sending the SMS, then the body includes a clear opt-out instruction (e.g., "Reply STOP to opt out"), and upon receiving STOP/UNSUBSCRIBE, the system sets SMS opt-out within 60 seconds and suppresses future SMS. Given secure link requirements, when including a link, then the URL is HTTPS on an approved short domain, contains no PHI, is single-use, and expires at 48 hours or upon response, whichever comes first. Given supported SMS responses A=Accept, D=Decline, S=Suggest, when the patient replies with A/D/S (case-insensitive) within the link expiration window, then the system parses the intent, sends an SMS confirmation of the received choice, and records a response event with normalized_value in {ACCEPT, DECLINE, SUGGEST} and the original inbound text.
Email Nudge with Branded, Language-Specific Template and Secure Short Link
Given patient's preferred language and practice branding profile, when generating the email, then subject and body use the selected language and configured tone, and the email applies the practice logo and color palette per branding profile. Given appointment type and shift direction/size, when selecting the email template, then the system chooses the variant matching appointment type and direction (earlier/later) and inserts the correct shift delta value (e.g., 30 minutes) in the body. Given minimum necessary PHI policy, when composing the email, then the subject contains no PHI, and the body contains only practice name, appointment date, and time window; any link is a secure short link that carries a token but no PHI in the URL. Given tracking is enabled, when the email is opened or the short link is clicked, then open and click events are captured within 5 seconds of occurrence with fields {channel=email, message_id, event_type, timestamp, template_id}. Given opt-out requirements, when the email is sent, then the footer includes a clear unsubscribe link; when a recipient clicks unsubscribe, then the system marks email opt-out within 1 minute and suppresses future emails for that patient. Given delivery outcomes, when a hard bounce or spam complaint is received, then the system records the event and halts further email attempts for that nudge, triggering fallback per the escalation policy.
Voice Nudge with Clear IVR Response Options and Minimal PHI
Given the patient has voice-call consent and a preferred language, when placing a voice nudge, then TTS or pre-recorded audio plays in the preferred language; if unavailable, it falls back to English and logs fallback_language="en". Given minimal PHI policy, when a live answer occurs, then the script requests simple identity confirmation (e.g., "press 1 if this is [first name initial]"), and only upon confirmation states the appointment date and time window; if voicemail is detected, then no appointment details are spoken, only practice name and a callback/short link. Given keypad options 1=Accept, 2=Decline, 3=Suggest, when the callee presses a key during the prompt, then the system captures the DTMF input, plays back a short confirmation message of the choice, and records a response event with normalized_value in {ACCEPT, DECLINE, SUGGEST}. Given quiet hours and frequency caps, when scheduling call attempts, then calls are not initiated during configured quiet hours and do not exceed 2 voice nudge attempts per rolling 24 hours per patient. Given call outcomes, when a call fails (e.g., carrier error, busy, no answer after N rings), then the attempt is recorded with a failure_code and the next fallback action is evaluated according to the escalation policy.
Adaptive Follow-up and Per-Channel Fallback After SLA No-Response
Given an initial channel attempt with a response SLA of 2 hours, when no response is received within the SLA, then a follow-up is scheduled on the next eligible channel according to the patient's channel preference order. Given a channel failure (e.g., SMS code 30005, email hard bounce, call unreachable), when the failure is detected, then the system immediately triggers fallback to the next eligible channel without waiting for the SLA to elapse. Given a global max of 3 total attempts across channels for a single nudge request, when a response is received on any channel or the max attempts is reached, then all pending follow-ups are canceled and the nudge is marked completed. Given quiet hours and per-patient frequency caps, when scheduling any follow-up, then the send time is deferred to outside quiet hours and the follow-up is suppressed if it would exceed the patient's cap, with suppression_reason recorded. Given compliance logging, when any escalation or suppression occurs, then an audit entry is written capturing prior channel, outcome, next channel, decision reason, and timestamp.
Rate Limiting and Frequency Throttling at Practice and Patient Levels
Given a practice-level send rate limit of 60 messages per minute per channel, when dispatching messages, then the system does not exceed the configured rate and queues overflow in FIFO order with per-channel isolation. Given provider rate-limit responses (HTTP 429 or equivalent), when encountered, then the system applies exponential backoff starting at 60 seconds with jitter, retrying up to 3 times without violating quiet hours. Given a per-patient cap of 2 nudges per rolling 24 hours across all channels, when attempting to enqueue beyond the cap, then the message is suppressed and suppression_reason="patient_frequency_cap" is recorded with the next eligible timestamp. Given clock skew up to ±2 minutes across nodes, when evaluating rolling windows, then the throttling decisions use a centralized monotonic time source to ensure consistent enforcement.
Event Capture for Delivery, Open, Response, and Branching Record
Given any message attempt, when a delivery, open, click, voicemail-detect, or response event occurs, then the system records the event within 5 seconds with fields {patient_id, appointment_id, practice_id, channel, message_id, event_type, timestamp_utc, template_id, campaign_id}. Given a response event (accept/decline/suggest), when recorded, then it is published to the orchestration bus within 1 second for branching logic consumption and is immutably appended to the patient's communication record. Given audit retention requirements, when querying the communication record for an appointment, then all associated events and message bodies (with PHI redacted to minimum necessary) are retrievable for 6 years and protected with tamper-evident hashes. Given a patient opt-out on any channel, when the opt-out is processed, then the system retains prior events for audit, marks the opt-out timestamp and channel in the record, and suppresses future sends across that channel while continuing to respect remaining permitted channels.
Real-time Response Processing & Auto-Reconciliation
"As a scheduler, I want accepted nudges to rebook automatically and safely so that the calendar stays accurate without manual rework."
Description

Processes patient replies in real time, re-validates schedule state to avoid race conditions, and places temporary holds on proposed times. On acceptance, performs atomic rescheduling across the PMS and SmileCue, cascades required shifts for impacted appointments, and updates reminders and notifications for all affected parties. Handles declines, counter-suggestions, expired offers, and conflicts with deterministic rollbacks and staff alerts. Emits events for downstream workflows and maintains idempotency to prevent double moves. Ensures no overbooking, preserves clinic buffers, and logs every change for auditability.

Acceptance Criteria
Real-Time Reply Intake and Temporary Hold Placement
- Given SmileCue receives a patient reply webhook for a nudge, when the payload is validated, then a processing task is enqueued within 100 ms and the reply is processed within 2 seconds p95. - Given a valid acceptance or counter-suggestion references one or more proposed slots, when processing begins, then a temporary hold is placed on each candidate slot within 2 seconds p95 with a configurable TTL default 5 minutes (range 1–15) and the hold prevents any other booking for the same resource(s). - Given an existing hold for the same patient and appointment, when a new hold is requested, then the prior hold is released and replaced (single active hold per patient per appointment). - Given a hold is active, when the offer is accepted, declined, or expires, then the hold is released within 500 ms and the hold state is visible to staff in the schedule UI and API.
Pre-Commit Schedule Re-Validation to Avoid Race Conditions
- Given an acceptance is received, when committing the change, then SmileCue re-fetches and compares PMS and SmileCue schedule versions for all impacted resources and time ranges and validates availability and buffer rules. - Given any version mismatch or conflict (slot no longer available, resource change, policy violation), when detected, then the acceptance is rejected with a clear reason, the hold is released within 500 ms, no changes are persisted, and a staff alert is created. - Given the acceptance window has expired, when a late acceptance arrives, then the system responds "offer expired", releases any holds, and makes no schedule changes.
Atomic Acceptance and Cross-System Rescheduling
- Given all validations pass, when rescheduling the accepting patient, then SmileCue writes the new appointment to the PMS and SmileCue atomically so that either both systems reflect the new time or neither does. - Given any write failure to either system, when it occurs, then all partial writes and dependent reminders/notifications are rolled back within 5 seconds and the original appointment remains intact. - Given a successful commit, when post-commit tasks run, then all reminders and notifications for the moved patient are updated to the new time, any now-invalid reminders are canceled, and the previous time is freed.
Deterministic Cascade Shifts With Buffer Preservation
- Given acceptance requires shifting adjacent confirmed patients, when computing a cascade, then only patients within their consented safe window and meeting risk/caregiver constraints are considered. - Given a cascade plan, when applying it, then clinic-defined buffers (e.g., cleanup, prep) are preserved, provider/resource utilization never exceeds configured capacity, and no overbooking occurs. - Given multiple valid cascade sequences, when selecting a plan, then the chosen sequence is deterministic based on documented priority rules (e.g., earliest feasible, lowest risk score). - Given any step of the cascade fails to apply, when detected, then all prior steps are rolled back within 5 seconds, holds are released, and staff are alerted with the failure context.
Declines, Counter-Suggestions, and Expired Offers Handling
- Given a decline reply, when processed, then the offer is marked declined, the hold is released immediately, the patient’s original appointment is retained, and the next candidate in the outreach policy is engaged if available. - Given a counter-suggestion reply with a specific time, when processed, then the system validates the time against provider availability, buffers, consent, and policy; if valid, a new hold is placed and a confirmation request is sent; if invalid, an explanatory message is sent and the original appointment is unchanged. - Given an offer reaches TTL without acceptance, when it expires, then the offer is marked expired, all holds are released, no schedule changes are made, and a staff notification summarizes the outcome.
Idempotent Operations and Downstream Event Emission
- Given duplicate delivery or retries of the same reply/offer event (same correlation ID), when processed, then no duplicate holds, moves, or communications are created (exactly-once effect). - Given a state-changing outcome (accepted, declined, expired, cascade applied, rollback), when committed, then SmileCue emits a single event per outcome type with a stable event ID, monotonic sequence number per appointment, and sufficient payload for downstream workflows. - Given an event consumer retries or a network partition occurs, when events are re-delivered, then downstream systems can de-duplicate using event ID and sequence number, and system state remains consistent.
Comprehensive Audit Trail and Traceability
- Given any hold, validation, schedule change, cascade, rollback, or communication, when it occurs, then an immutable audit record is appended containing timestamp (UTC), actor (patient/system/staff), correlation ID, prior and new values, resource IDs, rule evaluations, and reason codes. - Given an audit search by appointment ID, patient ID, correlation ID, or date range, when executed, then the complete chain of related records is returned in order within 2 seconds p95. - Given a compliance review, when exporting audit data for a time window, then the export includes all related events and links, is tamper-evident (hash chain or signature), and redacts PHI as configured.
Safety Guardrails & Risk Limits
"As a dentist, I want strict safeguards on when and how patients are moved so that care quality and trust are never compromised."
Description

Applies hard guardrails to protect patient experience and clinical safety: maximum cumulative shift per appointment, minimum notice before start time, per-day and per-patient nudge limits, provider- or appointment-type exclusions, do-not-nudge lists, and flags for anxiety, mobility, or medical risks. Validates caregiver/transport dependencies and ensures no shift violates room/equipment allocations or sterilization turnover. Provides pre-send simulation to detect any constraint violations and auto-aborts with clear error reasons if safety thresholds are exceeded.

Acceptance Criteria
Enforce Maximum Cumulative Shift Per Appointment
Given an appointment with original start time T0 and configured max_cumulative_shift_minutes = L And prior approved shifts totaling S minutes from T0 When Flex Nudge proposes an additional shift of D minutes (absolute value) Then S + |D| must be <= L to proceed And if S + |D| > L, the nudge is not sent, reason code MAX_SHIFT_EXCEEDED is recorded, and the appointment time remains unchanged
Respect Minimum Notice Window Before Start Time
Given configured min_notice_minutes = N in the practice time zone When the time from now to the proposed start time is < N minutes Then the nudge is blocked, no message is sent, and reason MIN_NOTICE_VIOLATION is recorded And when the delta is >= N minutes, the nudge may proceed subject to other guardrails
Apply Per-Patient and Per-Day Nudge Limits
Given configured patient_daily_nudge_limit = D and patient_appointment_nudge_limit = A And the patient has received d nudges today and a nudges for this appointment When a new nudge is attempted Then it proceeds only if d < D and a < A, and the counters are incremented atomically And if d >= D or a >= A, the nudge is not sent and reason NUDGE_LIMIT_REACHED is recorded And daily counters reset at 00:00 in the practice time zone
Honor Consent, Exclusions, and Risk Flags
Given channel-level consent statuses for SMS, email, and voice And provider and appointment-type exclusion lists And a do-not-nudge list And patient risk flags (e.g., anxiety, mobility, medical) with a policy that disallows nudging when present When building the candidate pool and selecting outreach channels Then include only patients with active consent for the channel being used And exclude any appointments/providers on exclusion lists And exclude any patient on the do-not-nudge list And exclude any patient with disqualifying risk flags per policy And record explicit reason codes (e.g., NO_CONSENT_SMS, PROVIDER_EXCLUDED, DO_NOT_NUDGE, RISK_FLAG_BLOCKED) for each exclusion
Validate Caregiver and Transport Dependencies
Given a patient linked to a caregiver/guardian and/or transport constraints with defined availability windows When proposing a new appointment time via Flex Nudge Then the proposed time must fall within caregiver availability and transport windows and must not overlap the caregiver’s other appointments in the practice And if any dependency fails, the nudge is not sent and reason CAREGIVER_OR_TRANSPORT_CONFLICT is recorded
Protect Resource Constraints and Sterilization Turnover
Given required provider, room, and equipment for the appointment type and sterilization_buffer_minutes = B When proposing a shift Then the new time must not double-book the provider, room, or required equipment And must maintain at least B minutes of sterilization turnover before and after relevant procedures per infection control policy And if any conflict is detected, block the nudge and record reason RESOURCE_OR_TURNOVER_CONFLICT And any auto-reconciled schedule resulting from accepted nudges must yield zero overbookings
Pre-Send Simulation and Auto-Abort With Clear Errors
Given pre-send simulation is run for a batch of proposed nudges When validating each candidate nudge against all guardrails Then the system returns pass/fail per nudge with specific reason codes for any failures And any failing nudge is automatically excluded from send And the UI shows a summary count of passes/fails and the reason codes per failure And an audit log entry is written with timestamp, user, and configuration snapshot hash
Staff Oversight, Preview, and Audit
"As an operations lead, I want to review and approve proposed nudges with full context so that I remain in control and compliant."
Description

Offers a dashboard to preview proposed nudges, predicted recovered minutes, and impacted patients with reason codes. Supports one-click approve/deny, manual edits to shift windows, and message preview before send. Provides role-based access, detailed change history, message transcripts, consent proofs, and exportable HIPAA-compliant audit logs. Includes a simulation mode to model outcomes prior to execution and notifications to staff for exceptions requiring manual intervention.

Acceptance Criteria
Dashboard Preview of Proposed Nudges and Predicted Recovery
Given an authorized Office Manager opens the Flex Nudge dashboard for a selected date range, When the page loads, Then it displays a table of proposed nudges with for each: masked patient name (First + Last initial), appointment ID, provider, original time, proposed shift delta (+/- minutes), allowable shift window (start–end), patient risk band, consent status per channel, caregiver note indicator, reason code, and proposal status Pending. Given the dashboard displays proposals, When the header metrics render, Then Predicted Recovered Minutes equals the sum of individual proposal recoveries within ±1 minute and the count of impacted patients matches the number of rows. Given there are up to 200 proposals, When the dashboard loads on a broadband connection, Then first contentful render is ≤3 seconds and full data load completes ≤5 seconds. Given a user expands a proposal row, When details are shown, Then the targeted gap is visualized and the system confirms no current overbooking exists for the target slot.
One-Click Approve/Deny with Auto-Reconciliation
Given a proposal with status Pending is selected, When the user clicks Approve, Then the system moves the appointment within the allowed window, frees the exact target gap, prevents double-booking, updates status to Approved, and enqueues the nudge message; the change history records before/after times, user ID, timestamp, and reason code. Given a proposal with status Pending is selected, When the user clicks Deny, Then no schedule or messaging changes occur, status updates to Denied, a denial reason is required, and an audit entry is recorded. Given an approval attempt encounters a constraint violation (risk, consent, caregiver, or slot race), When the operation fails, Then the system rolls back all changes, marks the item Requires Manual Review, creates an in-app notification, and emails the practice inbox if unacknowledged after 15 minutes. Given multiple proposals are approved sequentially, When reconciliation completes, Then cumulative recovered minutes equal the sum of approved proposals and the schedule contains no overlapping appointments.
Manual Edit of Shift Windows with Safe-Guard Validation
Given a proposal is Pending, When a user edits earliest/latest shift boundaries, Then the UI enforces limits derived from patient consent scope, risk score threshold policy, and caregiver availability; if any rule is violated, Save is disabled and a validation message names the violated rule. Given a valid edit is saved, When the change is committed, Then Predicted Recovered Minutes is recalculated and updates within 1 second and the change history logs the before/after window with user ID and timestamp. Given a user attempts to set a window that would overbook the target slot, When validation runs, Then the system blocks the edit and highlights the conflicting time range.
Message Preview and Consent-Gated Sending
Given an approved proposal has an unsent nudge, When the user opens Message Preview, Then exact SMS/email/voice content is rendered with variables resolved; PHI is masked for users without PHI permission; available channels reflect documented consent and non-consented channels are disabled with a visible reason. Given the user confirms Send Now, When messages are dispatched, Then they are sent only over consented channels, each channel is attempted once, and message transcripts with delivery status (Queued/Sent/Failed) are written to the audit log and linked to the proposal. Given the user cancels from preview, When exiting, Then no messages are sent and only a view access entry is recorded in the audit log.
RBAC for Oversight and Audit Access
Given a user with role Office Manager or Admin is authenticated, When accessing Oversight features, Then they can preview proposals, approve/deny, edit shift windows, run simulations, view message transcripts, and export audit logs. Given a user with role Dentist or Hygienist is authenticated, When accessing Oversight features, Then they can preview proposals, run simulations, and view read-only change history, but cannot approve/deny, edit windows, or export; restricted controls are hidden or disabled. Given an unauthorized or unauthenticated user requests any Oversight or export endpoint, When the request is processed, Then the system returns 403 and logs an access-denied event with user identifier (if present), IP, route, and timestamp.
Audit Log Detail and HIPAA-Compliant Export
Given any schedule change or message event occurs, When viewing the Audit Log, Then each entry includes event type, appointment ID, patient pseudonym, provider, before/after values, actor user ID, UTC timestamp (ISO 8601), reason code, channel, consent proof reference ID, and a link to the message transcript where applicable; entries are immutable and time-ordered. Given an Admin or Office Manager selects a date range up to 90 days, When requesting export, Then a HIPAA-compliant audit file is generated in CSV and JSON within 60 seconds; exports exclude full PHI by default and include PHI only if the user has PHI permission and explicitly selects Include PHI. Given an export is generated, When the download link is issued, Then the file is encrypted at rest until download and the signed URL expires within 15 minutes; an audit entry records who exported, what time, date range, and whether PHI was included.
Simulation Mode No-Impact Outcome Modeling
Given an authorized user selects Simulation mode with a target date range and providers, When Run Simulation is clicked, Then no messages are sent and no schedule changes occur; results include proposal count, expected approvals with model version, predicted recovered minutes, predicted exceptions count, and a list of impacted patients as anonymized IDs. Given the user adjusts parameters such as risk threshold or shift window, When the simulation is rerun, Then results update and are labeled with the parameter set and timestamp, preserving the previous run for comparison within the session. Given a simulation includes up to 500 proposals, When executed, Then results render within 10 seconds with a visible progress indicator.
Performance & Impact Analytics
"As a practice owner, I want clear metrics on how Flex Nudge performs so that I can quantify ROI and fine-tune settings."
Description

Tracks acceptance rate, time-to-fill, recovered chair time, impact on no-show rate, provider utilization, and patient satisfaction signals. Breaks down performance by channel, appointment type, provider, and shift size to inform continuous optimization. Feeds learning signals back into ranking to improve candidate selection and messaging strategies over time. Exposes dashboards and an API for reporting to stakeholders.

Acceptance Criteria
Accurate Metric Computation & Refresh for Flex Nudge Impact
Given a practice with Flex Nudge enabled and a reporting date range and timezone selected When nudges are sent, accepted, gaps are filled, visits occur, cancellations log, and patient feedback is received within the range Then the system calculates and displays: - Acceptance rate = distinct appointments accepted via Flex Nudge ÷ distinct appointments nudged within range, percentage with 1 decimal - Median time-to-fill in minutes from first nudge sent for an appointment to the time its gap is filled - Recovered chair time = sum of filled-gap durations attributable to Flex Nudge shifts (minutes), with per-appointment attribution - No-show impact = difference in no-show rate between Flex Nudge–filled appointments and matched controls (matched on provider, day-of-week, time-of-day ±30m, appointment type, risk bucket, and lead time), with 95% CI - Provider utilization = booked chair-hours ÷ available chair-hours; uplift attributed to Flex Nudge is the portion from Flex Nudge–filled appointments - Patient satisfaction = share of positive signals ([thumbs-up OR rating ≥4/5 OR positive sentiment]) over total feedback items And metrics ingest to dashboard within 5 minutes p95 of event arrival; nightly backfill at 02:00 practice time completes with ≥99.5% record coverage
Segmented Performance by Channel, Appointment Type, Provider, and Shift Size
Given aggregated Flex Nudge metrics exist for a practice When the user applies any combination of filters: channel (SMS, Email, Voice), appointment type, provider, and shift size buckets (±15, ±30, ±45, ≥±60 minutes) Then the dashboard: - Updates charts and tables within 1.5 seconds p95 - Shows zero-value segments explicitly and keeps them selectable - Allows multi-select and displays totals that equal the sum of visible segments (tolerance ≤0.5% due to rounding) - Supports drill-down from any segment to a list of underlying appointment IDs, event timestamps, and patient pseudonyms - Persists filters across navigation and exports
Analytics Dashboard Usability, Consistency, and Export
Given an authenticated AnalyticsViewer for a practice When the user opens the Performance & Impact dashboard Then: - Default date range is last 30 days; selectable up to the last 365 days; all times shown in the practice timezone - KPI values are consistent across widgets (differences only from rounding; absolute delta ≤1 unit) - Number formats: percentages with 1 decimal; times in minutes; hours with 2 decimals - Drill-through from any KPI opens a modal/table with sortable columns and pagination (page size 50) - Export to CSV and JSON is available; exported row count equals the on-screen total; file generation completes within 10 seconds p95 - Initial dashboard load completes in ≤3 seconds p95 on a 10 Mbps connection
Reporting API for Metrics and Breakdowns
Given a client credential with scope analytics:read and practice access When the client calls GET /v1/analytics/flex-nudge/metrics with parameters {practice_id, start, end, group_by?, filters?, cursor?} Then: - Response is 200 JSON matching the published schema with stable field names, units, and ISO-8601 timestamps - Results are deterministic for identical queries; pagination via cursor returns complete coverage with no duplicates or gaps - Supported group_by: channel, appointment_type, provider_id, shift_size_bucket; unsupported values return 400 with error details - Rate limiting enforces ≥1000 requests/min per client with Retry-After on 429; idempotent GETs; gzip compression enabled - Requests without valid OAuth2 token receive 401; insufficient scope or practice access receive 403 - No PHI beyond patient pseudonym and age bucket is returned; all transport uses TLS 1.2+; fields marked pii:false in schema
Learning Signal Pipeline Feeding Ranking and Messaging
Given labeled outcomes for Flex Nudge attempts and associated features are collected When the nightly feature pipeline runs Then: - New features and labels are written to the feature store within 2 hours of day boundary with ≥99% success rate - Weekly retraining triggers when ≥10,000 new labeled events exist; otherwise the prior model remains active - A candidate ranking and message selection model with a new version is deployed only if offline evaluation shows no regression vs baseline on AUC and NDCG@5 - After deployment, ≥95% of scoring responses include model_version and feature_snapshot ids; logs show the active model version timestamp is ≤14 days old - Shadow evaluation demonstrates that at least 20% of candidate lists change order relative to the prior model within 48 hours
Attribution, Consent Compliance, and Data Integrity
Given consent status, risk scores, and caregiver flags are stored for patients When analytics aggregates Flex Nudge outcomes Then: - Events from patients without messaging consent or with excluded risk criteria are excluded from acceptance rate denominators and clearly labeled when excluded - Attribution of recovered chair time and utilization only counts gaps filled by Flex Nudge–induced shifts; manual reschedules are excluded - All event ingestion is idempotent; duplicate events do not change aggregates; late-arriving events re-compute affected aggregates within 10 minutes - Every aggregate point has an audit trail (source event ids, computation version); audits retrievable via GET /v1/analytics/audit with practice scope - Data retention is 24 months for aggregates and 90 days for identifiable event logs; exports and dashboards show a banner when outside retention windows

Fill Analytics

Live metrics for fill rate, time-to-fill, revenue saved, outreach per fill, and fairness distribution by provider/location. Includes what-if simulators for thresholds and waitlist size, plus exports—helping managers prove ROI and fine-tune settings with confidence.

Requirements

Real-time Fill Metrics Dashboard
"As an office manager, I want a live dashboard of fill metrics by provider and location so that I can spot issues in real time and adjust outreach to hit our targets."
Description

Provide live, continuously updating metrics for fill rate, time-to-fill (median, p90), revenue saved, and outreach per fill, with filters for date range, provider, location, appointment type, and channel. Include trend charts, benchmarks/targets, and drill-down to the underlying appointment and outreach events. Data freshness indicator and update latency of ≤60 seconds. Integrates with SmileCue’s scheduling event stream and communication logs; responsive UI accessible on desktop and tablet. Enables managers to monitor performance, prove ROI, and react quickly to gaps.

Acceptance Criteria
Live Data Freshness Indicator and ≤60s Latency
Given the dashboard is open and subscribed to the scheduling event stream and communication logs When a relevant event (vacancy created, outreach sent, appointment filled, appointment canceled) is ingested Then all visible metrics and charts refresh within 60 seconds of the event ingestion time And the freshness indicator displays the last updated timestamp accurate to the second and the status "Live" Given no new data is received or the stream is delayed beyond 60 seconds When the dashboard remains open Then the freshness indicator displays the age of the last update and the status "Stale" Given the network disconnects and later reconnects When connectivity is restored Then the dashboard resumes live updates and the freshness indicator updates accordingly
Metric Definitions and Accuracy Validation
Given a test date range containing 10 vacancy events, 8 of which become filled within the range When metrics are computed Then Fill Rate equals 80% (8 fills / 10 vacancies) Given the 8 fills have time-to-fill durations of [0.5h, 1h, 2h, 3h, 4h, 4h, 10h, 24h] When time-to-fill metrics are computed Then Median time-to-fill equals 3.5 hours And P90 time-to-fill equals 24 hours using the nearest-rank method (ceil(0.9*n)) Given the 8 filled appointments have booked revenue values [$100, $100, $150, $120, $80, $90, $110, $200] When revenue saved is computed Then Revenue Saved equals $950 as the sum of revenue for appointments filled from vacancies in the range Given 40 outreach messages (SMS/email/voice) occurred that directly relate to the 8 fills in the range When outreach per fill is computed Then Outreach per Fill equals 5.0 (40 / 8) and displays to one decimal place Given units and rounding are displayed When metrics render Then percentages show one decimal place, time shows hours and minutes, currency shows the correct locale format
Filter Controls Apply to All Metrics and Charts
Given filters for date range, provider, location, appointment type, and channel are available When the user selects any combination of these filters and applies them Then all KPIs and trend charts recompute using only matching appointments and outreach events Given multiple values are selected per filter (e.g., two providers and three locations) When applied Then the results include the union of selected values within each filter and the intersection across different filters Given filters are cleared When the user selects "Clear all" Then all KPIs and charts return to the unfiltered state for the current workspace Given a filter combination yields no matching data When applied Then KPIs display zero values and trend charts show an empty state with "No data for selected filters"
Trend Charts with Targets and Aggregation Consistency
Given a selectable date range of 30 days When trend charts render Then daily series are shown for Fill Rate, Median Time-to-Fill, P90 Time-to-Fill, Revenue Saved, and Outreach per Fill And each chart overlays its benchmark/target line Given targets are configured (e.g., Fill Rate ≥ 85%, Median TTF ≤ 4h, P90 TTF ≤ 24h, Outreach per Fill ≤ 6) When the current aggregated value is compared to its target Then the UI displays a success state when the metric meets the target and a warning state when it does not Given the daily points shown in the charts When totals/aggregations are computed Then the chart aggregations match the top-line KPIs for the same filters (Fill Rate within 0.1 percentage points; Median within 1 minute; P90 within 1 minute; Revenue within $1; Outreach per Fill within 0.1)
Drill-down to Underlying Appointments and Outreach Events
Given the user clicks a KPI or a point on a trend chart When drill-down opens Then a list of the underlying records for the current filter context is shown with columns sufficient to reconcile the metric (e.g., appointment_id, provider, location, appointment_type, vacancy_created_at, filled_at, time_to_fill, revenue, channel) Given the drill-down list is loaded When counts are compared Then the number of rows equals the metric's numerator for the same context (e.g., fills count) Given a row is selected When the user clicks through Then the appointment detail and associated outreach events open, sourced from scheduling events and communication logs Given the user changes filters while drill-down is open When the context updates Then the drill-down list refreshes to match and maintains sorting and pagination
Stream Integration, Ordering, and Idempotency
Given scheduling and communication events may arrive out of order or be duplicated When events are processed Then the system orders by event_time and deduplicates by event_id to ensure consistent metrics Given a late-arriving fill event pertains to a previously vacant slot in the selected range When it is ingested Then metrics and charts update within 60 seconds and the fill appears in drill-down Given a previously filled appointment is canceled within the selected range When the cancellation event is ingested Then Fill Rate, Revenue Saved, and related charts are decremented accordingly within 60 seconds and the drill-down reflects the change Given an appointment attribute (provider, location, appointment type) changes after initial ingestion When the update event is received Then affected metrics are reclassified under the new attributes on the next refresh and are consistent with current filters
Responsive Desktop and Tablet Layout
Given a desktop viewport (≥1024px width) When the dashboard loads Then KPIs display in a multi-column layout and all charts are fully visible without horizontal scrolling Given a tablet viewport in portrait and landscape (768–1023px width) When the dashboard loads Then KPIs stack appropriately, charts maintain readable axes and labels, and interactive elements have touch targets of at least 44px Given orientation changes on tablet When switching between portrait and landscape Then the layout reflows without content overlap or loss and preserves the current filter state
Time-to-Fill and Cohort Analytics
"As a regional operations lead, I want to analyze time-to-fill by cohort so that I can identify bottlenecks and replicate what works across locations."
Description

Compute and display time from opening creation to confirmation across cohorts (provider, location, appointment type, daypart, lead source, channel). Show distributions, percentiles, and aging buckets with optional outlier handling. Support saved cohort views and comparisons period-over-period. Exclude canceled or re-opened slots per configurable rules. Identifies bottlenecks and best-performing segments to optimize staffing and outreach cadence.

Acceptance Criteria
Compute Time-to-Fill from Opening to Confirmation
Given an opening with created_at T0 and a first valid confirmation event at T1 > T0 When computing time-to-fill Then time-to-fill equals floor((T1 − T0) in minutes) and is non-negative Given multiple confirmation events for the same opening When computing time-to-fill Then use the earliest confirmation after T0 with final status in {confirmed, kept} and not voided by a subsequent reopen Given a reporting date range [Rstart, Rend] When filtering records Then include openings where T0 ∈ [Rstart, Rend], regardless of T1 timing Given an opening without any confirmation When aggregating time-to-fill metrics Then exclude it from time-to-fill aggregates and include it only in aging buckets
Distributions and Percentiles by Cohort
Given a selected date range and cohort filters (provider, location, appointment type, daypart, lead source, channel) When viewing the time-to-fill distribution Then render a histogram with default 15-minute bins spanning min to max observed values and at least 10 bins Given time-to-fill samples in scope When computing percentiles Then display p50, p75, p90, and p95 using the inclusive nearest-rank method, rounded to whole minutes Given daypart is selected as a cohort dimension When assigning records to dayparts Then use the appointment start time in the practice timezone to determine the daypart bucket Given channel is selected as a cohort dimension When assigning records to channels Then use the channel recorded on the confirmation event (e.g., SMS, email, voice, manual)
Aging Buckets for Open and Filled Openings
Given default aging buckets [0–15m, 16–60m, 1–4h, 4–24h, 1–3d, >3d] When computing aging by cohort and date range Then place each opening into exactly one bucket based on elapsed time: T0→T1 if confirmed, else T0→Rend if unconfirmed Given custom bucket boundaries are configured When recalculating metrics Then totals across buckets equal the number of openings in scope and percentages sum to 100% ±0.1% Given the report is run for a past period When computing unconfirmed aging Then use Rend at 23:59:59 practice timezone as the cutoff, not the current clock time
Saved Cohort Views Creation and Management
Given a set of selections (date range, cohort filters, outlier mode/threshold, bucket config, comparison mode) When saving with a unique name of 2–50 characters Then the view is persisted and appears in the Saved Views list for the user Given a saved view exists When applying it Then filters, configurations, and displayed metrics match the saved configuration exactly Given the user has permission to manage saved views When renaming or deleting a view Then the change is persisted; otherwise return a 403 error and make no changes Given a duplicate name within the organization When attempting to save Then validation fails with "Name must be unique"
Period-over-Period Comparison
Given a current date range [Rstart, Rend] When comparison mode "Previous Period" is enabled Then the comparison range is [Rstart − (Rend − Rstart + 1 day), Rstart − 1 day] in the practice timezone Given comparison mode is enabled When displaying time-to-fill metrics Then show for both periods: mean, p50, and p90, plus absolute and percentage deltas where percentage delta = (current − previous) / previous × 100 rounded to 1 decimal place Given the previous period has fewer than 10 samples When computing deltas Then display "insufficient data" and omit delta calculations
Outlier Handling Toggle and Thresholds
Given outlier handling is OFF When computing metrics Then include all time-to-fill samples Given outlier handling is ON with absolute cutoff N minutes When computing metrics Then exclude samples with time-to-fill > N from means, distributions, and percentiles, and display the number and percentage excluded Given outlier handling is ON with percentile cutoff P (e.g., 99) When computing metrics Then exclude the top (100 − P)% of samples by time-to-fill Given outlier settings are changed When the view refreshes Then all affected metrics recompute using the new settings
Canceled and Re-opened Slot Exclusion Rules
Given exclusion rule "exclude canceled before confirmation" is enabled When an opening is canceled before any confirmation event Then exclude it from all time-to-fill metrics and distributions and include it only in aging as unconfirmed until cancel time Given an opening has a confirmed appointment that is later canceled and the slot is re-opened When applying exclusion rules Then treat the re-opened slot as a new opening with a new T0 at reopen time and retain the original confirmed opening’s metrics unless the rule "exclude confirmed-then-canceled" is enabled Given exclusion rules are toggled When recomputing metrics Then the counts, distributions, and percentiles update to reflect the rules in effect and an audit badge displays the number of records excluded
Multi-touch Outreach Attribution
"As a marketing/communications manager, I want to see which messages and channels contribute to each fill so that I can reduce outreach volume while maintaining fill rates."
Description

Attribute filled openings to SMS, email, and voice outreach using configurable multi-touch models (first-touch, last-touch, time-decay) and attribution windows. Calculate “outreach per fill,” channel lift, and script/template performance. Deduplicate contacts, respect opt-outs, and exclude unrelated contacts using appointment and patient linkage. Provide transparent attribution logs for auditability. Surfaces what channels and messages drive fills with the least effort.

Acceptance Criteria
First-Touch Attribution with Configurable Window
Given the attribution model is set to First-Touch and the attribution window is configured to W days And there are one or more outreach events (SMS, email, voice) linked to patient P and appointment A within W days before A is filled When appointment A is filled (confirmed or booked) Then 100% of attribution credit is assigned to the earliest eligible outreach event within the window And all outreach events outside the window or not linked to both patient P and appointment A are excluded from eligibility And an attribution log entry is created for A capturing model, window, selected outreach ID, excluded outreach IDs with exclusion reasons, and timestamps
Last-Touch Attribution with Exclusion of Unrelated Contacts
Given the attribution model is set to Last-Touch and the attribution window is configured to W days And there are multiple outreach events across channels before the fill event And only outreach events linked to both patient P and appointment A are considered eligible When appointment A is filled Then 100% of attribution credit is assigned to the most recent eligible outreach event prior to the fill time within W days And any outreach not linked to both patient P and appointment A, or occurring after the fill time, is excluded And the attribution log records the selected outreach, excluded events, linkage checks performed, and rationale
Time-Decay Multi-Touch Attribution with Half-Life
Given the attribution model is set to Time-Decay with a half-life H hours and attribution window W days And there are k eligible outreach events linked to patient P and appointment A within the window When appointment A is filled Then each eligible outreach i receives fractional credit weight_i = 0.5^(Δt_i/H) normalized so the sum of all weights equals 1.000 (±0.001) And fractional credits are rounded to 4 decimal places and persisted And the attribution log stores model parameters (H, W), per-touch Δt, raw weights, normalized credits, and rounding details
Deduplication and Opt-Out Enforcement
Given outreach events may include duplicates (e.g., retries) and patients may opt out per channel And a deduplication window D minutes is configured When determining eligible outreach events for attribution Then at most one outreach per channel per recipient per template is counted within any D-minute window (earliest retained, later duplicates excluded with reason "Duplicate within D") And any outreach sent after a recorded opt-out timestamp for that channel/recipient is excluded with reason "Opted Out" And exclusions and deduplication decisions are recorded in the attribution log
Outreach per Fill Metric Calculation and Refresh
Given a selected date range and optional filters (provider, location, channel) And attribution credits for fills in range have been computed When calculating Outreach per Fill Then numerator = count of attributed outreach events with non-zero credit for fills in range (after dedup and exclusions) And denominator = count of fills in range And the metric is displayed as a decimal to two places and refreshes within 90 seconds of a new fill being recorded And results respect applied filters and match the sum of underlying attribution logs
Channel Lift Computation with Control Segment
Given a control segment is configured for channel C (e.g., holdout or channel-disabled cohort) for a selected date range And fills and attributed outreach are available for both control and exposed cohorts When computing channel lift for C Then fill_rate_exposed = fills_exposed / opportunities_exposed and fill_rate_control = fills_control / opportunities_control And lift = (fill_rate_exposed - fill_rate_control) / fill_rate_control expressed as a percentage And if either cohort has fewer than N=100 opportunities, display "Insufficient data" instead of a lift value And the calculation inputs (cohort sizes, rates, date range, filters) are shown and exportable
Template/Script Performance Reporting
Given outreach messages include template_id and channel metadata And a date range and filters (provider, location, channel) are selected When viewing template/script performance Then for each template, display: sends, fills attributed (sum of non-zero credits), fill rate per 100 sends, average time-to-fill from send, and outreach per fill And templates with fewer than M=50 sends in range are flagged as "Insufficient data" And metrics reconcile with attribution logs and respect deduplication and opt-out exclusions
Fairness Distribution Reporting
"As a practice owner, I want visibility into how filled slots are distributed across providers so that I can ensure equitable allocation aligned with our targets."
Description

Report the distribution of filled openings across providers and locations normalized by availability and panel size. Display fairness indices, target ranges, and variance flags. Allow configuration of fairness thresholds and target weights for reporting purposes, with alerts when distribution drifts beyond targets. Provide drill-downs to see which appointment types or channels are driving imbalances. Supports compliance and equitable allocation goals without enforcing scheduling rules.

Acceptance Criteria
Compute Fairness Index Normalized by Availability and Panel Size
Given a selected date range and filters (locations, providers) and configured weights weight_availability and weight_panel that sum to 1.0 When the Fairness Distribution report is generated Then for each provider and each location within scope, compute availability_share = available_open_slots_entity / sum_available_open_slots_scope And compute panel_share = active_panel_size_entity / sum_active_panel_size_scope And compute expected_share = normalize(weight_availability * availability_share + weight_panel * panel_share) so expected_shares sum to 1.0 across entities in scope And compute actual_filled_share = fills_entity / sum_fills_scope And compute fairness_index = round(actual_filled_share / expected_share, 2) And display for each entity: fills_entity, actual_filled_share (as %), expected_share (as %), fairness_index And if expected_share = 0 and actual_filled_share = 0, set fairness_index = 1.00; if expected_share = 0 and actual_filled_share > 0, set fairness_index = null and flag as No Baseline
Display Target Ranges and Variance Flags
Given configured target ranges [min_target, max_target] effective for the current scope When the report is viewed Then each entity row displays min_target and max_target alongside fairness_index And sets variance_flag = Within if min_target <= fairness_index <= max_target; Below if fairness_index < min_target; Above if fairness_index > max_target; No Baseline if fairness_index is null And visually highlights Below/Above rows with a red indicator and adds a tooltip explaining deviation And shows report metadata: applied configuration version and last_refreshed timestamp And displays counts as integers and percentages to one decimal place; comparisons use full-precision values (not rounded)
Configure Thresholds and Target Weights
Given a user with Admin or Manager role When they open Fairness Settings and update target ranges and weights, then click Save Then validate that 0.0 <= min_target < max_target, weight_availability >= 0, weight_panel >= 0, and weight_availability + weight_panel = 1.0 And persist settings with organization-level defaults and optional overrides per location; record an audit log (user, timestamp, before/after values) And apply the saved settings immediately to new report generations; existing exported reports remain unchanged And users without Admin or Manager role cannot modify settings and see read-only values
Alert on Drift Beyond Fairness Targets
Given configured target ranges and an alert policy with consecutive_windows = N (default 3), critical_threshold_percent, suppression_window_hours (default 24) When an entity’s fairness_index is outside its target range for N consecutive completed reporting windows Then generate an alert containing entity identifier, current fairness_index, target range, duration of drift, and link to drill-down, and deliver via configured channels (in-app, email) And if deviation exceeds critical_threshold_percent beyond the nearest bound in any single window, send an immediate alert without waiting N windows And deduplicate alerts for the same entity and drift reason within suppression_window_hours And allow recipients to acknowledge and mute per entity without disabling alerting for others; record all alert events in the audit log
Drill-down by Appointment Type and Channel
Given a user viewing the Fairness Distribution report When they click a provider or location row or its Drill Down action Then present a breakdown by appointment_type and outreach_channel showing, per line: fills, actual share (%), expected share (%), variance, and contribution to overall deviation And allow filtering by date range, appointment_type, channel, and toggling between provider/location views; inherit filters from the parent view And sort by variance descending by default and allow re-sorting by any column; show Top 5 by default with an option to View All And allow CSV export of the drill-down with applied filters and include a configuration snapshot in the export metadata
Read-only Reporting and Compliance Safeguards
Given fairness reporting and alerts are enabled When users view reports or modify fairness thresholds/weights Then no scheduling, routing, or booking rules are created, modified, or enforced by these settings; they affect reporting and alerts only And the report surfaces only aggregated, de-identified data (no patient names, phone numbers, emails, or MRNs) and suppresses any cell smaller than k=5 by grouping into Other And access to Fairness Settings is restricted to Admin/Manager roles; all views, changes, and exports are captured in an audit log with user, timestamp, and scope
What-if Simulation Sandbox
"As an operations analyst, I want to model proposed setting changes so that I can predict their impact on fill metrics and choose the optimal configuration."
Description

Simulate the impact of changing thresholds (e.g., outreach cadence, reminder timing, waitlist size) on fill rate, time-to-fill, revenue saved, outreach per fill, and fairness using historical appointment and outreach data. Provide side-by-side scenario comparisons, sensitivity analysis, and confidence ranges. Simulations run asynchronously with queued jobs and are clearly labeled as non-production until applied. Enables data-driven tuning of settings before rollout.

Acceptance Criteria
Async Simulation Queue and Non-Production Labeling
Given I am an authorized manager and submit a simulation with defined parameter changes and a historical date range When I click Run Simulation Then a job is enqueued with a unique job_id and status=Queued And the UI displays "Simulation (Non-Production)" on the job detail and results pages And the job status transitions through {Queued, Running, Succeeded|Failed|Canceled} with timestamps And I can cancel a Running job, which transitions to Canceled within 60 seconds And per-practice concurrent Running simulations are limited to 3; further submissions remain Queued And the job persists progress updates at least every 15 seconds And for a 6-month data range with <=100,000 appointments, 95% of jobs complete within 10 minutes And no external notifications, messages, or schedule changes are triggered by the job
Side-by-Side Scenario Comparison
Given at least one Baseline run and up to three Alternative runs exist for the same practice, cohort, and date range When I open the Compare Scenarios view Then the view shows for each scenario: fill rate, median time-to-fill, revenue saved, outreach per fill, and fairness indices by provider and location And each Alternative displays absolute and % deltas vs Baseline for each metric And if a run’s cohort or date range does not match Baseline, it is flagged Incompatible and cannot be added until re-run with matching scope And I can sort scenarios by any metric and toggle units (hours/days, currency locale) And the comparison supports up to 4 scenarios simultaneously without truncation
Sensitivity Analysis and Confidence Ranges
Given a completed scenario result When I open Sensitivity Then the system reports the top 5 parameters by absolute impact on fill rate using one-at-a-time perturbations around the scenario settings And each reported metric includes a 95% bootstrap confidence interval computed with 1,000 resamples And if the effective sample size < 500 appointments or < 50 fills, the UI shows Low Confidence and widens intervals to 80% CI And sensitivity results include impact bands for time-to-fill, revenue saved, outreach per fill, and fairness indices And all charts and tables display the exact parameter values used for perturbations
Fairness Impact by Provider and Location
Given provider and location tags are present in historical data When a simulation completes Then the results include fairness metrics per provider and per location: Gini coefficient and max share deviation from target And the target share defaults to proportional capacity (historical available slots) and can be overridden per simulation And any provider or location exceeding ±10% deviation from target is highlighted with a warning And the comparison view displays fairness changes vs Baseline for each scenario
Historical Data Isolation and Safety
Given I run a simulation for a specified historical window When the simulation executes Then it only reads from historical appointment and outreach logs within that window And it does not modify production settings, schedules, waitlists, or patient records And it does not send SMS, email, or voice messages And all result pages and exports include a Non-Production watermark And an audit log entry is recorded with actor=simulation, user_id, parameters, date_range, job_id
Export Simulation Results
Given a scenario has completed When I export results as CSV or PDF Then the export includes: inputs (parameters and date range), software version, metric definitions, all scenario metrics, deltas vs Baseline, sensitivity outputs, and confidence intervals And patient identifiers, if present, are pseudonymized (hashed) and PHI is excluded by default to maintain HIPAA compliance And exports are timestamped, include practice and user, and are available for download for 30 days And an audit log entry is recorded for each export
Apply Settings to Production with Guardrails
Given I have Manage Settings permission and a scenario has Succeeded within the last 30 days When I click Apply to Production Then I must review a summary showing predicted impact with 95% CI and fairness warnings, and explicitly confirm And only the scenario’s parameter set (not historical data) is applied to production settings atomically And an audit log records before/after values, job_id, user_id, and timestamp And the system provides an automatic rollback option for 24 hours that restores previous settings with one click And after application, the related simulation remains labeled Non-Production and read-only
Data Export and Scheduled Reports
"As an office manager, I want to export and schedule delivery of our fill analytics so that I can share results and back up ROI claims without manual work."
Description

Offer one-click exports of aggregated and detailed analytics to CSV/XLSX with selectable fields, filters, and aggregation levels. Provide scheduled delivery via email and SFTP, plus an authenticated REST endpoint for programmatic retrieval. Include a data dictionary, versioning of schemas, and audit logs for access and downloads. Support optional de-identification for exports to external stakeholders.

Acceptance Criteria
Manual One-Click Export (Selectable Fields, Filters, Aggregation, CSV/XLSX)
Given a user with export permission selects dataset (Aggregated or Detailed), fields, filters (date range, provider, location), aggregation level, file format (CSV/XLSX), and timezone When the user clicks Export Then the file is generated within 60 seconds for results up to 100,000 rows and 50 columns And the file contains only the selected fields and rows matching the filters And aggregated exports reflect the chosen granularity (day/week/month, provider/location) with totals matching on-screen metrics ±0.1% And column headers match the Data Dictionary display names and include schema_version and generation_timestamp metadata (CSV header row; XLSX metadata sheet) And dates are ISO-8601 with timezone offset; encoding is UTF-8; numeric formats are locale-neutral And if the result exceeds limits, the user is prompted to run as an asynchronous job and receives an email link upon completion
Scheduled Reports via Email and SFTP
Given a user creates a schedule with frequency (daily/weekly/monthly or cron), run time, timezone, recipients, and delivery targets (email, SFTP) plus selected report template When the schedule triggers Then deliveries complete within 10 minutes of the scheduled time And email uses TLS and either password-protected attachments or expiring download links (24-hour expiry) And SFTP uses key-based authentication with host key verification and writes to the configured path And failures trigger alert emails to schedule owners and automatic retries (up to 3 attempts with exponential backoff) And each run records outcome, file checksum (SHA-256), row count, and destinations in the audit log And pausing or deleting a schedule prevents further runs and is reflected in the audit log
Authenticated REST Export Endpoint
Given an API client with valid OAuth2 credentials and export scope requests /exports with dataset, fields, filters, schema_version, and deidentify parameters When the request is within rate limits (≤ 60 requests/min per tenant) Then small results (≤ 50,000 rows) return 200 with a downloadable file and headers Content-Type, Content-Disposition, X-Schema-Version, and ETag And large results return 202 with a job_id and status endpoint; completion provides a time-limited, single-use URL And only tenant-scoped data is returned; cross-tenant access is rejected with 403 And all requests and downloads are recorded in the audit log with client_id, IP, parameters, and outcome And invalid parameters return 400 with a descriptive error and link to the data dictionary
Data Dictionary and Immutable Schema Versioning
Given a user opens the Data Dictionary UI or calls /schemas When a schema version (e.g., v1.2) is selected Then all exportable fields display name, technical name, type, description, example, allowed values, PHI flag, and availability by dataset/aggregation And a changelog highlights additions, deprecations, and breaking changes since the prior version And schema versions are immutable once published; the default version can change without altering existing schedules And exports include schema_version in file metadata; pinned schedules continue to use their pinned version And deprecated fields remain available for at least 12 months with warnings in UI and API responses
Comprehensive Audit Logging for Exports
Given any export action (manual click, scheduled run, or API retrieval) completes or fails When an auditor queries the audit log by date range, actor, export type, or outcome Then entries include timestamp (UTC), actor (user_id or client_id), tenant, action type, parameters (dataset, fields, filters, deidentify, schema_version), destination (download/email/SFTP), file hash, row count, status, error code/message (on failure), and source IP And logs are retained for at least 6 years, are read-only, and tamper-evident And authorized roles can export audit logs to CSV with the same fields And viewing or exporting audit logs is itself logged
Optional De-identification for External Stakeholder Exports
Given a user or API client sets deidentify = true for an export When the export is generated Then direct identifiers (name, phone, email, exact address, DOB, MRN/patient_id) are removed or replaced with consistent per-tenant pseudonyms (e.g., patient_hash via salted hash) And dates are shifted by a consistent per-patient offset within ±14 days while preserving intervals; ages ≥ 89 are bucketed as "89+"; free-text fields are omitted And the Data Dictionary for de-identified mode lists removed/transformed fields and notes HIPAA Safe Harbor alignment And resulting files contain no direct identifiers; spot checks on a test set confirm zero leakage And the audit log records deidentify=true for the export
Role-based Access and HIPAA-safe Aggregation
"As a compliance officer, I want analytics access and exports constrained by role and safe aggregation so that we remain HIPAA-compliant without sacrificing insight."
Description

Enforce role-based access controls for analytics views and exports, restricting PHI to authorized roles and masking identifiers where not required. Apply minimum cell-size thresholds and k-anonymity-style aggregation to prevent re-identification in small cohorts. Encrypt data in transit and at rest, and maintain immutable audit logs for all analytics access and exports. Ensures compliance while preserving actionable insights.

Acceptance Criteria
RBAC Enforcement for Analytics Views
Given a user with a PHI-Restricted role, when they open any Fill Analytics dashboard, then no patient identifiers (name, phone, email, DOB, MRN, appointment ID) are rendered and only aggregated metrics are visible. Given a user with a PHI-Authorized role, when they open the same dashboard, then only the minimum necessary PHI fields configured for that role are visible and all others are masked (e.g., **** or hashed tokens). Given a user lacking the Analytics.View permission, when they attempt to access analytics routes or APIs, then a 403 is returned and no data is leaked in error messages. Given any user, when RBAC rules are changed, then the new permissions take effect on the next request with no stale cached permissions allowing access. Given any RBAC decision, when rendered or denied, then the decision is recorded in the audit log with userId, role, permission, resource, timestamp (UTC), and outcome.
PHI-Safe Exports and Watermarking
Given a PHI-Restricted role, when they request a data export from Fill Analytics, then only de-identified/aggregated columns are included and all patient identifiers are removed or replaced by irreversible salted hashes. Given a PHI-Authorized role, when they request an export, then included PHI columns are limited to those explicitly allowed by policy and marked as Minimum Necessary. Given any export, when the file is generated, then it is watermarked with userId, role, requestId, timestamp (UTC), and filter parameters, and the same metadata is stored in the audit log. Given any export, when the download link is created, then it is a pre-signed URL that expires in ≤ 15 minutes and allows a single successful download. Given an export request that would produce rows violating the minimum cell-size threshold (k), when processed, then the export is blocked with a clear message and zero bytes of data are returned.
Minimum Cell-Size and k-Anonymity Aggregation
Given the system default k = 10 (configurable), when any table, chart, or cross-tab would show a cell count < k, then the cell is suppressed (e.g., shown as "<10") and no drill-down is permitted. Given multiple dimensional filters (e.g., location + provider + time), when results are computed, then all intersections meet k; otherwise those intersections are suppressed. Given sequential queries that differ by filters likely to produce differencing attacks, when executed within a 15-minute window, then cohort locking or result smoothing prevents inference of < k members. Given the What-If simulator, when simulating thresholds or waitlist size, then it uses aggregated or synthetic data only and applies the same k suppression logic. Given suppression occurs, when results are returned, then a suppression indicator and k value are visible to the user and captured in the audit log.
Encryption In Transit and At Rest
Given any analytics API or UI connection, when established, then TLS 1.2+ with strong ciphers is enforced and HTTP->HTTPS is redirected with HSTS enabled. Given analytics data at rest (databases, object storage, backups), when stored, then AES-256 encryption via managed KMS is used and encryption cannot be disabled per-tenant. Given KMS keys, when in use, then access is restricted by least privilege and keys are rotated at least every 90 days. Given any export file, when written to storage, then it is encrypted at rest and any temporary unencrypted files are not created; if created, they are securely deleted immediately. Given a security scan, when performed with SSL Labs or equivalent, then the public analytics endpoints achieve grade A or better.
Immutable Audit Logging for Analytics Access and Exports
Given any analytics view, filter change, drill, or export initiation/completion, when it occurs, then an audit event is appended with userId, role, ip, action, resource, parameters (non-PHI), row counts, timestamp (UTC), and outcome. Given audit storage, when events are written, then they are immutable (append-only WORM) and tamper-evident via hash chaining or equivalent. Given audit retention policy, when enforced, then events are retained for at least 6 years and are queryable within that window. Given an auditor or compliance admin request, when retrieving audit events by userId or date range, then results are returned within 2 minutes for 95th percentile queries. Given a deletion attempt or alteration of past audit events, when attempted by any user or process, then the action fails and an alert is generated.
Scope-Based Access by Location/Provider
Given a user assigned to specific locations/providers by RBAC scope, when they view analytics or request exports, then only data for their assigned scopes are returned and visualized. Given a user attempts to include out-of-scope locations/providers via filters or API params, when the request is processed, then a 403 is returned and the attempt is logged with the rejected scopes. Given a user’s scope changes, when the next analytics request is made, then the new scope is enforced immediately and cached results outside scope are invalidated. Given a super-admin or compliance role, when accessing analytics, then they may view all scopes consistent with policy and all such access is highlighted in the audit log.

SmartCode Routing

Delivers the one-time passcode over the best available, consented channel—SMS, email, or voice—then auto-falls back if undelivered. Multilingual prompts and delivery checks reduce lockouts and support calls, lifting completion rates across all patient cohorts without extra staff effort.

Requirements

Consent-Aware Channel Selection
"As an office manager, I want OTPs routed only through channels patients have consented to so that we remain compliant and avoid patient frustration."
Description

Selects the initial OTP delivery channel (SMS, email, or voice) using per-patient consent, verified contact availability, regulatory constraints, and practice preferences. Pulls consent and language from SmileCue’s patient profile and EHR integrations, honors opt-in/opt-out status in real time, and filters out non-consented channels for both primary send and any fallback attempts. Validates contact health (e.g., hard bounce history, carrier blocks), respects quiet hours and do-not-call rules, and records the rationale for each routing decision for auditing. Ensures compliant, patient-friendly delivery that reduces failures and complaints while fitting seamlessly into existing SmileCue communications infrastructure.

Acceptance Criteria
Initial Channel Selection Honors Consent and Preferences
Given a patient has consented SMS and email and both contacts are verified and healthy, and the practice channel preference order is SMS > email > voice When an OTP delivery is requested outside quiet hours and all regulatory checks pass Then SMS is selected as the initial channel and the decision rationale records consents used, contact health, preference order, regulatory checks, and timestamp Given the top-preference channel is not consented or fails contact health checks When an OTP delivery is requested Then the next highest-preference consented and healthy channel is selected and excluded channels are recorded with reasons
Real-Time Opt-Out Enforcement at Send Time
Given a patient opted out of SMS in SmileCue or the EHR after the OTP flow was initiated but before send When the system evaluates the channel for the initial send Then SMS is excluded from consideration and the next consented channel is selected Given no channels remain consented at evaluation time When an OTP delivery is requested Then the request is rejected with reason code NO_CONSENTED_CHANNEL and no delivery attempts are made and the event is logged for audit
Consent-Filtered Fallback on Non-Delivery
Given the initial OTP attempt is undelivered due to hard bounce, carrier block, invalid number, or call unreachable When a fallback is triggered Then the system selects the next consented and healthy channel and does not retry the failed channel in the same flow Given the fallback channel is also undelivered When the system evaluates remaining options Then additional fallbacks continue only across consented and healthy channels until all are exhausted or delivery succeeds, and each attempt outcome and reason are logged Given no consented and healthy channels remain When fallbacks are exhausted Then the flow ends with terminal status UNDELIVERED and the user-facing API returns machine-readable failure details
Preferred Language Applied to OTP Delivery
Given a patient preferred language is present in SmileCue or EHR When the OTP is delivered via SMS, email, or voice Then the content templates or TTS voice are rendered in the patient preferred language and the language code is recorded in the audit log Given the preferred language is missing When the OTP is delivered Then the practice default language is used and recorded; if neither is available, English is used as a safe default and recorded Given a multilingual practice with per-location defaults When the OTP is requested for a patient without a preference Then the location default is used
Quiet Hours and Do-Not-Call Compliance
Given current time falls within practice quiet hours or the patient has Do Not Call for voice When selecting an initial or fallback channel Then voice is excluded from consideration and the reason is recorded Given current time falls within practice quiet hours for SMS When selecting an initial or fallback channel Then SMS is excluded; if email is consented, email is selected; if no permissible channels remain, the OTP send is deferred to the end of quiet hours and the scheduled send time is recorded Given quiet hours end is reached for a deferred OTP When the deferred send is evaluated Then the channel selection runs again honoring consent, contact health, and regulations before sending
Audit Trail for Routing Decisions
Given any OTP routing decision is made When the attempt is processed Then a tamper-evident audit record is persisted containing request ID, selected channel, evaluated channels with inclusion or exclusion reasons, consent states with sources and timestamps, contact health signals, regulatory and quiet-hours evaluations, language used, timestamps of each attempt, and final outcome Given an authorized admin queries the audit log via API or console When filtering by request ID or patient ID within the retention window Then the audit record is retrievable within 2 seconds and is immutable and write-once
Real-Time Consent and Contact Health Data Freshness
Given SmileCue fetches consent and language from the EHR and internal profile When evaluating channel selection Then the system uses the most recent available consent state; if the EHR is unavailable, it uses cached consent not older than 5 minutes; if the cache is older than 5 minutes or missing, no send is attempted and a RETRIEVE_CONSENT_FAILED error is returned and logged Given contact health shows hard bounce for email within the last 30 days, carrier block for SMS, or invalid/disconnected phone for voice When evaluating channels Then those channels are excluded from initial and fallback attempts and the exclusion reasons cite the specific health signal and timestamp
Multi-Channel OTP Fallback Orchestration
"As a patient, I want my passcode delivered over a working channel with automatic retries so that I can sign in without contacting support."
Description

Delivers a single OTP across the best available, consented channel and automatically falls back if undelivered or unacknowledged within a configurable window. Implements delivery checks per channel (SMS delivery receipts, email bounce/SMTP codes, voice call outcome), capped retry counts, and backoff with jitter to reduce carrier filtering. Maintains idempotency across attempts (one active code per flow), masks destinations in notifications, and synchronizes state so the same code can be received on alternate channels without duplication. Includes timeout/expiry, max attempt limits, and clear error handling, integrated with SmileCue’s messaging gateways and job scheduler.

Acceptance Criteria
Channel Selection Honors Consent and Priority
Given a patient has consented channels with priority [SMS, Email, Voice] and all destinations are valid When an OTP is requested Then the system sends the OTP via the highest-priority consented channel with a healthy gateway And no other channel is attempted initially Given the top-priority channel is unhealthy or destination is invalid When an OTP is requested Then the system selects the next highest-priority consented channel with a healthy gateway Given the patient has no consented channels When an OTP is requested Then the API responds with an error code no_consent And no OTP is generated or sent
Timed Fallback Across Channels on Undelivered or Unacknowledged OTP
Given SMS is the selected channel and fallback window W=60s When the SMS delivery status is failed or remains unknown after W Then the system sends the same OTP via the next consented channel And marks the prior attempt as superseded without generating a new code Given delivery was successful but the user has not verified within W When W elapses Then the system sends the same OTP via the next consented channel Given the user verifies the OTP at any time When verification succeeds Then all scheduled retries are canceled And no further messages or calls are placed
Per-Channel Delivery Validation and State Updates
Given an SMS is sent When a delivery receipt is received as delivered Then the attempt state is set to delivered Given an SMS is sent When a delivery receipt is failed or a network error is returned Then the attempt state is set to undelivered and eligible for fallback Given an Email is sent When SMTP returns 250 and no bounce is received within W=60s Then the attempt state is set to sent (provisional) and not immediately retried Given an Email is sent When a hard bounce (5xx or permanent) is received Then the attempt state is set to undelivered and the system falls back Given a Voice call is placed When the outcome is answered by human and the OTP prompt completes Then the attempt state is set to delivered Given a Voice call is placed When the outcome is busy, no-answer, voicemail, or failed Then the attempt state is set to undelivered and eligible for retry/fallback per policy
Idempotent OTP Across Attempts and Channels
Given an OTP flow is active When a resend or fallback is triggered Then the same OTP value is reused across all channels and attempts And only one active OTP exists for the flow Given concurrent OTP requests for the same flow occur within the TTL When the API is called Then the existing active OTP is returned/reused and no new OTP is created Given the OTP is successfully verified When verification completes Then the OTP is invalidated and all pending/scheduled sends are canceled And subsequent verification attempts with that OTP fail with otp_consumed
Masked Destinations and PII-Safe Observability
Given any event log, audit entry, metric, or webhook related to the OTP flow When destination data is included Then phone numbers are masked to E.164 last 2 digits only (e.g., +1******34) And emails are masked to first/last character of local and domain (e.g., j****@d****.com) Given user-facing notifications or errors When destination details are shown Then only masked values are shown and full PII is never displayed or spoken Given message bodies across SMS, Email, and Voice When content is generated Then no full destination identifiers are included in the content
OTP Expiry and Global Attempt Limits
Given OTP TTL=5 minutes When the OTP is presented after TTL Then verification fails with error otp_expired and no further retries are scheduled Given a maximum of N=3 attempts across all channels per flow When the Nth attempt is completed without successful verification Then the flow is marked terminal with attempt_limit_reached And no additional retries or fallbacks are scheduled Given a flow is terminal due to expiry or attempt limit When any new send request is made for the same flow Then the API responds with flow_closed and requires starting a new OTP flow
Backoff with Jitter and Scheduler Integration
Given capped retries per channel are configured as 2 and initial delay=10s, multiplier=2, jitter=±20%, max_delay=60s When retries are scheduled Then the job scheduler enqueues next attempts at approximately 10s and 20s with randomized jitter And no two attempts occur within less than 8s of each other Given repeated SMS failures with provider error codes indicating carrier filtering When the next retry is evaluated Then the system escalates to the next consented channel early and records reason carrier_filtering Given gateway/service health is degraded at the scheduled time When the job executes Then the attempt is deferred within the same backoff window with jitter or routed to an alternate healthy channel per policy
Adaptive Routing Intelligence
"As a practice owner, I want the system to learn which channel works best for each patient so that more patients complete verification on the first attempt."
Description

Learns the optimal channel and send timing per patient using historical deliverability, engagement signals, and cohort-level performance, while strictly enforcing consent rules. Computes a per-patient/channel score and chooses the highest-scoring eligible option for the first attempt, with guardrails for cost and call frequency. Supports cold-start defaults, continuous feedback from delivery outcomes and completion events, and A/B evaluation to verify uplift. Exposes safe, explainable decisions and allows admins to set bounds (e.g., limit voice usage). Integrates with SmileCue analytics pipeline and feature flags for iterative rollout.

Acceptance Criteria
Score-Based Channel Selection with Consent Enforcement
Given a patient with recorded per-channel consent states and computed per-patient/channel scores And feature flags for Adaptive Routing are enabled for the practice When a one-time passcode (OTP) routing decision is requested Then the system selects the highest-scoring channel that is consented, feature-flag-enabled, and within configured quiet-hours/timezone rules And the decision is persisted with decision_id, model_version, per-channel scores, consent statuses, and timestamp And if no eligible channel exists, the system returns a NoEligibleChannel error and performs no send
Cold-Start Default Routing
Given a new patient with no prior delivery or completion history And a practice-configured default channel order [SMS, Email, Voice] And channel consent states for the patient When an OTP routing decision is requested Then the system uses cold-start logic to choose the first channel in the default order that is consented and feature-flag-enabled And schedules the send within the practice's configured sending window in the patient's local timezone And logs that cold-start logic was applied for traceability
Auto-Fallback with Cost and Call Frequency Guardrails
Given practice guardrails: max_attempts_per_otp=3, max_voice_calls_per_patient_per_day=1, max_cost_per_otp=$0.50 And test channel costs configured (SMS=$0.01, Email=$0.001, Voice=$0.12) When the first attempt results in a definitive failure event (e.g., bounce) or no delivery confirmation within 10 minutes Then the system retries on the next highest-scoring eligible channel within 2 minutes of failure detection or at the 10-minute timeout And total attempts do not exceed max_attempts_per_otp and cumulative estimated cost does not exceed max_cost_per_otp And voice is not attempted if it would exceed max_voice_calls_per_patient_per_day And all attempts, outcomes, timings, costs, and reasons are logged with a shared decision_id
Continuous Feedback Score Update
Given delivery outcome events (delivered, failed) and completion events (OTP verified) are emitted to the analytics pipeline When such an event is ingested for a patient Then the per-patient/channel score is updated and versioned within 15 minutes of event ingestion And the next routing decision for that patient uses the updated score version And replays of the same event_id are ignored to ensure idempotency And all score updates are audit-logged with before/after values and event references
Explainable Decisions and Admin Bounds
Given admin-configured bounds (e.g., limit_voice_usage_per_patient_per_week=1, disallow_sending_outside_hours=20:00–08:00 local) When an OTP routing decision is made Then the API/UI explanation includes: selected channel, top 3 alternatives with scores, excluded channels with reasons (no consent, bound exceeded, cost cap), applied guardrails, model_version, and timestamps And if a higher-scoring channel is excluded by a bound, the explanation cites the specific rule identifier And no PHI beyond patient_id and contact channel identifiers is exposed And updates to bounds take effect on the next decision without service redeploy
A/B Evaluation and Feature-Flagged Rollout
Given a feature flag supports variants: control (static default order) and treatment (adaptive scoring) And a 10% holdout is configured for control When rollout is initiated Then patient allocation is random, stable (sticky) for at least 30 days, and within ±1% of target proportions And emitted metrics include per-variant completion_rate, delivery_success_rate, average_attempts, and average_cost_per_otp And a daily uplift report comparing treatment vs control is generated and stored And a kill switch disables treatment within 5 minutes and routes all decisions through control And analytics events include decision_id, variant, patient_pseudonym, channel, attempt_number, outcome, and per-channel scores
Multilingual OTP Prompts
"As a Spanish-speaking patient, I want to receive OTP instructions in my preferred language so that I can complete verification confidently."
Description

Provides localized OTP templates for SMS and email, and natural-sounding IVR/TTS prompts for voice in supported languages. Automatically selects language based on patient preference with fallback to English, supports right-to-left scripts, and formats digits clearly for voice playback with repeat options. Centralizes translation management, template versioning, and QA checks to ensure consistency across channels. Ensures all content remains PHI-free and aligns with SmileCue’s branding while reducing confusion and support burden for non-English speakers.

Acceptance Criteria
Language Auto-Selection and Fallback
Given a patient profile with preferred_language=Spanish and Spanish is supported When an OTP is requested via any channel Then the prompt is rendered in Spanish for that channel Given a patient profile with preferred_language=Korean and Korean is not supported When an OTP is requested Then the prompt defaults to English and logs a language_fallback event without PHI Given a patient profile with no preferred language When an OTP is requested Then the prompt defaults to English Given SMS is undelivered and routing falls back to voice When the voice call is placed Then the voice prompt uses the same language selected by patient preference
Right-to-Left Script Rendering (SMS/Email)
Given preferred_language=Arabic When an SMS/email OTP is generated Then the email template sets dir=rtl and the SMS includes proper bidi marks so text flows right-to-left Given preferred_language=Arabic When the OTP digits are inserted Then digits are presented left-to-right and unbroken with non-joining spaces preventing digit reordering Given preferred_language=Arabic When rendering in common clients (Gmail Web, Outlook Desktop, iOS Messages, Android Messages) Then no mixed-order artifacts or misplaced punctuation are observed in QA screenshots Given preferred_language=Arabic When the message is generated Then the OTP code never wraps across lines
Voice OTP Playback Clarity and Repeat
Given preferred_language=French When an OTP is delivered by voice Then TTS uses a French neural voice and speaks the code as individual digits with a 300–500 ms pause between digits Given a voice OTP prompt in any supported language When the user presses DTMF "1" Then the full OTP and instructions are repeated up to 3 times Given a voice OTP prompt in any supported language When the user presses DTMF "2" Then the code is replayed slower by increasing the inter-digit pause by at least 200 ms Given no input is detected for 10 seconds When a voice OTP is in progress Then the system repeats the instruction once and ends the call gracefully after the final repeat
Centralized Translation Management & Versioning
Given a Translator role When editing the Spanish SMS template Then saving requires a change note and creates version n+1 with author, timestamp, and diff recorded Given a language version n+1 for SMS, email, and voice When attempting to publish Then publishing is blocked until all channel templates pass automated QA checks and receive at least one QA Approver approval Given a draft translation version When preview is requested Then the system shows channel-specific previews and allows test send/call to seed endpoints before publish Given a published language version history When a rollback is requested Then all channel templates revert to the selected prior version and the full audit trail is retained
PHI-Free Content Enforcement
Given any template content When the PHI linter runs Then usage of disallowed placeholders (e.g., {patient_name}, {dob}, {appointment_time}) or free text matching PHI patterns blocks publish with an explicit error Given any channel template When validating placeholders Then only {brand_name}, {otp_code}, {expiry_minutes}, {support_contact}, and {help_link} are permitted and publish fails if {otp_code} is missing or appears more than once Given outbound previews and logs When retention is reached (24 hours) Then OTP codes are redacted and no patient identifiers are stored
Multichannel Consistency & Quality Checks
Given published French templates When generating SMS, email, and voice prompts Then instruction strings are semantically equivalent per translation key mapping and include the same variables Given an SMS template with accented characters When validating encoding Then GSM-7 is used if possible else UCS-2 is selected automatically and the chosen encoding is recorded without PHI Given an SMS message When length exceeds 160 GSM-7 or 70 UCS-2 characters Then the message is split with UDH and a non-PHI warning is logged Given an email template When running accessibility checks Then color contrast meets WCAG AA and links have meaningful text Given a voice template When running audio QA Then at least two reviewers rate intelligibility at 4/5 or higher
Verification UX: Resend & Channel Switch
"As a patient, I want an easy way to resend or switch delivery method if I didn’t get the code so that I can finish verification quickly."
Description

Offers a streamlined OTP entry experience with countdown, masked destination hints, and accessible controls to resend the code or switch to another consented channel without restarting. Enforces rate limits, lockout thresholds, and code expiry while providing clear, localized feedback messages. Mobile-first UI supports one-tap SMS code autofill where available, copy/paste handling, and deep links from email. Integrates with SmileCue’s authentication flow and session management to minimize drop-off and prevent brute-force attempts.

Acceptance Criteria
Resend OTP with Countdown and Rate Limiting
Given the OTP screen is displayed and a code has been sent When the countdown is running Then the Resend button remains disabled until 30 seconds have elapsed Given 30 seconds have elapsed and no lockout is active When the user taps Resend Then a new OTP is issued, the prior OTP becomes invalid, the countdown resets to 5:00, and a localized success message is shown Given a rolling 10-minute window When the user requests resends Then no more than 3 resend requests are allowed; upon reaching the limit, display a localized rate-limit message and disable Resend until the window resets Given a network failure occurs during resend When the user retries Then an inline error with a retry option is shown and the resend attempt is not counted until the provider acknowledges the request Given assistive technology is in use When Resend becomes enabled Then an aria-live announcement informs screen readers that Resend is available
Switch Channel Without Restart
Given the user has consented to multiple channels When the user selects Switch Channel Then only consented channels (SMS, Email, Voice) are listed with masked hints (phone: show country code and last 2 digits; email: show first letter of local part and domain TLD) Given the user switches from channel A to channel B When the switch is confirmed Then a new OTP is issued over channel B, any active OTP from channel A is invalidated, the UI updates masked hint, and the countdown resets to 5:00 without leaving the screen Given the selected channel reports delivery failure or no status within 10 seconds When SmartCode Routing flags failure/timeout Then an automatic fallback option to the next consented channel is presented with one-tap confirm; no duplicate OTPs are sent concurrently Given the user switches channels twice within a 10-minute session window When attempting a third switch Then a localized rate-limit message is shown and the switch is blocked until the window resets Given Voice is chosen as the channel When the OTP call is placed Then prompts are played in the user’s preferred language and the code is repeated twice
Mobile Autofill and Paste Handling
Given iOS or Android supports OTP auto-fill When an SMS containing the OTP arrives Then the code field is auto-filled using platform APIs without requiring SMS read permission and the Submit action becomes enabled Given the user pastes or types a code When the input contains spaces, hyphens, or non-digits Then the input is normalized to exactly 6 numeric digits [0-9] and extraneous characters are ignored Given fewer than 6 digits are present When the user attempts to submit Then submission is blocked and an inline helper text prompts to complete the code Given clipboard privacy requirements When the user pastes a code Then clipboard contents are not persisted to logs, analytics, or session storage
Email Deep Link Verification
Given the user receives an email with a deep link for OTP verification When the link is opened on a device with the app installed Then the app opens to the verification screen with the code pre-filled or token-bound for immediate verification Given the app is not installed When the link is opened Then the mobile web verification screen opens in the same session context with the code pre-filled or token-bound for verification Given the deep link token is one-time use When the same link is opened again Then a localized message indicates the link is no longer valid and offers a resend option Given the OTP has expired after 5 minutes When the link is opened Then verification is rejected with an expiry message and a one-tap resend option
Localized Feedback and Accessibility Compliance
Given the user’s locale is English, Spanish, French, or Arabic When success, error, countdown, or lockout messages are shown Then all text, time formats, and pluralization are localized and accurate, with RTL layout supported for Arabic Given a screen reader user When interacting with the verification flow Then all controls have accessible names/roles, focus order is logical, dynamic status messages use aria-live, and color contrast meets WCAG AA (≥4.5:1) Given keyboard-only navigation When navigating the UI Then all actions (resend, switch channel, submit) are reachable and operable without a mouse
Lockout and Brute-Force Protection
Given failed code submissions occur When the user enters 5 incorrect OTPs within a 10-minute window Then the verification flow is locked for 15 minutes with a localized lockout message and guidance to contact support Given a lockout is active When the user attempts to resend or switch channels Then those actions are disabled with an explanation and the remaining lockout time is displayed Given security logging requirements When a lockout occurs Then an audit event with timestamp, channel, and session ID is recorded without storing the OTP value
Session Continuity and State Recovery
Given the user refreshes or returns within the same session When the verification screen reloads Then the selected channel, masked hint, remaining countdown, and rate-limit counters are restored without sending a new OTP Given multiple OTP tabs or windows are open When a new OTP is requested Then only the most recent OTP is valid across all tabs, and older attempts are rejected with a message to use the newest code Given a session timeout of 20 minutes of inactivity When the user returns to the verification screen Then the flow prompts re-authentication and does not allow OTP submission with an expired session context
Compliance, Security & Audit Logging
"As a compliance officer, I want OTP routing and delivery to meet HIPAA/TCPA requirements with full audit trails so that we minimize regulatory and security risk."
Description

Implements HIPAA-aligned processing for OTP flows: no PHI in messages, encryption in transit and at rest, secret/key rotation, and short-lived, random codes with attempt throttling. Records immutable audit logs capturing consent state, routing rationale, send/fallback attempts, and outcomes with timestamps and actor/system IDs. Supports TCPA-compliant opt-out handling, quiet hours, and per-jurisdiction rules. Provides breach-resistant storage, least-privilege access, and exportable audit reports to satisfy compliance reviews and BAAs. Integrates with SmileCue’s centralized logging and alerting.

Acceptance Criteria
PHI-Free OTP Messaging Enforcement
Given an outbound OTP notification is generated for SMS, email, or voice When the message content is rendered Then it contains no PHI (e.g., names, dates of service, procedures, balances) and includes only the OTP, a generic label, and support contact And When a template or variable attempts to include PHI Then the system blocks the send, returns a validation error, and writes an audit event with actor/system ID and reason MSG_PHI_BLOCKED And Then automated content scanning shows 0 PHI matches across 10,000 test messages using approved allowlist/regex rules
End-to-End Encryption for OTP and Audit Data
Given any OTP or audit event transits a network boundary When connections are established Then TLS 1.2+ with modern ciphers is enforced and downgrade attempts are rejected and logged And Given OTP codes and audit logs are stored at rest When data is written Then AES-256-GCM (or equivalent) envelope encryption via KMS/HSM (FIPS 140-2/3 validated) is applied and plaintext is not retrievable from storage snapshots And When red-team attempts offline decryption without keys Then decryption fails and access attempts are logged with source, time, and principal
Key and Secret Rotation with Zero Downtime
Given active KMS keys for encrypting OTP secrets and audit logs When scheduled (≤90-day) or manual rotation is triggered Then new encryptions use the new key within 5 minutes and the event is captured in audit logs with key IDs And Then decryptions of previously stored data continue with 0 failures during and after rotation until old keys are formally retired And Then OTP delivery/verification availability remains ≥99.99% during the rotation window with no message loss
OTP Code Security, TTL, and Throttling
Given an OTP is requested When the code is generated Then it is a 6-digit numeric code created by a CSPRNG and not reused within its TTL And Then the code TTL is 5 minutes; after TTL, verification fails with CODE_EXPIRED and is audited And When a user attempts verification Then a maximum of 5 attempts per OTP per user are allowed; on limit breach, a 15-minute lockout is enforced and audited And When OTP sends are requested Then no more than 3 OTP sends per 15 minutes per user per channel are allowed; excess sends are blocked and audited
TCPA Consent, Opt-Out, and Quiet Hours by Jurisdiction
Given channel-specific consent states exist for a patient When delivering an OTP Then only consented channels are used; non-consented channels are skipped with rationale logged And When an inbound STOP/UNSUBSCRIBE (or local equivalent) is received on SMS Then SMS consent is revoked within 30 seconds, a confirmation is sent (where permitted), future SMS are blocked, and the change is audited And Given configured quiet hours by jurisdiction When local patient time is within quiet hours Then SMS/voice OTPs are deferred or routed to a consented email channel; no restricted sends occur; all decisions are logged with jurisdiction rule IDs
Immutable Audit Logging with Routing Rationale and Export
Given SmartCode Routing performs a send and any fallback When the event completes Then an append-only audit record is stored capturing consent snapshot, routing rationale, channel attempts, outcomes, timestamps (RFC3339 with ms), and actor/system IDs And When a modification or deletion of an audit record is attempted Then the system prevents changes (WORM) and records a tamper-attempt audit and alert And When an authorized auditor requests an export for a date range ≤1 year Then a signed CSV or JSON export is produced within 60 minutes, including integrity metadata (hash/signature) and is retrievable via secure channel
Least-Privilege Access and Centralized Alerting Integration
Given defined RBAC roles When accessing OTP secrets or audit logs Then only Security Admin and Compliance Auditor can view/export full audit data; Support Agents see redacted summaries; all accesses require MFA and are logged And Given integration with SmileCue centralized logging and alerting When error rates for OTP sends >1% over 5 minutes, or a user has >10 failed verifications in 10 minutes, or a TCPA violation is attempted, or key rotation fails Then alerts fire within 5 minutes to the on-call channel with incident context and links to relevant audit events And Then service accounts and data stores enforce least privilege (read/write limited to required scopes) with quarterly access reviews producing an exportable attestation report
Routing Analytics & Policy Controls
"As an office manager, I want visibility into OTP performance and the ability to adjust routing rules so that I can improve completion rates without engineering support."
Description

Delivers a dashboard showing verification funnel metrics (send, deliver, first-try completion), channel performance, language distribution, and failure reasons with filters by location, cohort, and timeframe. Provides configurable routing policies: channel order, max attempts, timeouts, quiet hours, languages enabled, and IVR voice options, with change history and safe previews. Enables CSV export and alerts on abnormal failure spikes. Integrates with SmileCue’s admin console and permissions model for role-based access and environment-specific settings.

Acceptance Criteria
Funnel Metrics Dashboard with Filters
Given I am an authorized user in the Admin Console, When I open the Routing Analytics dashboard with default filters (All locations, All cohorts, Last 7 days), Then I see counts for OTP sends, deliveries, and first-try completions computed in the practice default timezone. Given I change filters to Location = Location A, Cohort = New Patients, Timeframe = Last 30 days, When I apply the filters, Then all widgets and charts refresh within 2 seconds and values reflect only the filtered dataset. Given I clear all filters, When I reset to defaults, Then the dashboard reverts to default filters and metrics. Given no data exists for the selected filters, When the dashboard loads, Then an empty state appears with the message No data for selected filters and no errors. Given the first-try completion metric is displayed, When I view its definition, Then it equals unique verifications completed on the first channel attempt divided by total verifications started in the period, shown as a percentage to one decimal place.
Channel and Language Performance Breakdown
Given the Channel Performance panel is visible, When the dashboard loads, Then per-channel metrics display attempts, delivery rate, completion rate, average time to verify, and failure rate for the selected timeframe. Given the Language Distribution panel is visible, When filters are applied, Then counts and completion rates per language reflect the filtered dataset. Given the Failure Reasons tab is selected, When viewing details, Then the top 5 failure reasons per channel are listed with percentages, and selecting a reason filters the other charts accordingly. Given I sort the channel table by completion rate descending, When I click the column header, Then the rows reorder correctly and the sort order is indicated. Given a metric has an info icon, When I hover it, Then a tooltip shows the metric definition and formula.
Routing Policy Configuration and Validation
Given I have Admin role, When I open Routing Policies for Environment = Staging, Then I can configure channel order (SMS, Email, Voice), max attempts (1–5), per-attempt timeouts (15–900 seconds), quiet hours (local time), languages enabled (at least one), and IVR voice options (voice and speed). Given I attempt to save invalid values (e.g., max attempts = 0, timeout < 15 seconds, quiet hours end before start, no languages selected), When I click Save, Then Save is blocked and field-level validation messages are shown. Given quiet hours are set, When I preview next attempt timing for Location A, Then the preview shows the next scheduled attempt time that respects the location time zone and configured quiet hours. Given I save a valid policy, When the save completes, Then a new policy version is created and associated only with the selected environment. Given another admin is editing the same policy, When I attempt to save, Then I receive a conflict notification and must refresh or resolve before saving.
Safe Policy Preview and Change History
Given I select a draft routing policy, When I click Preview, Then a simulation runs against the last 30 days of verification records and returns projected sends, deliveries, and first-try completion deltas without changing live routing. Given preview results are displayed, When I click Download, Then a preview report containing summary metrics and key diffs is downloaded. Given I click Publish, When I confirm and enter a change reason, Then the policy is published and the change history records user, timestamp, environment, previous values, new values, and reason. Given I open the history view, When I select a prior version, Then I can view details and rollback to that version for the same environment after confirming.
CSV Export (Filtered, HIPAA-Safe)
Given I am viewing any analytics panel with filters applied, When I click Export CSV, Then the export respects current filters and includes columns: timeframe, location, cohort, channel, language, sends, deliveries, completions, first-try completions, failure reasons, delivery rate, completion rate, first-try completion rate. Given HIPAA constraints, When the file is generated, Then the export contains no PHI or PII and only aggregated metrics. Given the dataset size is 500k rows or fewer, When I start the export, Then the file is available within 60 seconds; otherwise a background job is queued and a secure download link is emailed to authorized users. Given an export completes, When I view audit logs, Then an entry exists with user, time, filter summary, row count, and file checksum.
Abnormal Failure Spike Alerts
Given alerting is enabled for Environment = Production, When delivery failure rate or completion failure rate exceeds a 3-sigma threshold versus the trailing 14-day baseline within a 30-minute window, Then an alert is generated. Given an alert triggers, When notifications are dispatched, Then recipients configured for email and Slack receive a message with environment, affected locations, channels, top failure reasons, current rate, baseline, detection window start, and a link to the dashboard. Given multiple spikes occur for the same scope within 60 minutes, When additional detections happen, Then alerts are rate-limited to one per scope per hour and subsequent alerts are suppressed with suppression noted in the alert log. Given an alert is acknowledged in the console, When the incident remains active, Then duplicate notifications for that incident are suppressed until the metric returns to normal and the incident auto-resolves.
Role-Based Access and Environment Isolation
Given my role is Viewer, When I access Routing Analytics, Then I can view dashboards and export CSV but cannot modify routing policies or alert configurations. Given my role is Manager, When I access Routing Policies, Then I can create and preview policies and configure alerts but cannot publish to Production. Given my role is Admin, When I manage Routing Policies and Alerts, Then I can create, preview, publish, rollback policies, and manage alert settings across environments. Given the selected environment is Staging, When I view data and policies, Then they are isolated to Staging; changes do not affect Production and environment context is clearly indicated. Given I attempt an action without permission, When the request is sent, Then the system returns a 403 and logs the unauthorized attempt.

Device Bind

Locks each expiring magic link to the requesting device/browser with a short-lived token, blocking forwarded or intercepted links from opening elsewhere. Optional in-office QR handoff preserves convenience while preventing misdelivery, lowering privacy risk without adding patient friction.

Requirements

Device-bound Magic Link Issuance
"As a patient, I want the magic link I request to only open on my device so that my appointment details stay private even if the message is forwarded."
Description

Issue short-lived, single-use magic links that are cryptographically bound to the requesting device/browser using a privacy-preserving device fingerprint and secure cookies. Tokens contain no PHI, are signed server-side, and expire within a configurable window to limit exposure. On request, the system generates an opaque token tied to device attributes (e.g., Web Crypto key material, user agent, and same-site secure cookie) and stores a hashed reference for verification. Links are distributed across SMS, email, and voice-driven URLs via SmileCue’s messaging pipeline, supporting deep links on iOS/Android and standard browsers. Keys are rotated regularly, clock skew is tolerated within safe bounds, and all operations use FIPS-validated crypto libraries to maintain HIPAA safeguards while minimizing patient friction.

Acceptance Criteria
Device-Bound, PHI-Free Token Issuance
Given a patient initiates a magic link request from a device/browser When the server processes the request Then it issues a URL containing only an opaque token with no PHI or patient identifiers And the token is signed server-side and includes a key identifier (kid) for verification And the server stores only a salted, hashed reference to the token; no plaintext token is stored at rest And the token’s time-to-live (TTL) is set to the configured value and embedded in the token claims And an audit event is recorded with timestamp, channel, and device-binding status, excluding PHI
Enforce Device Binding and Single Use
Given Device A requested the magic link and Device B did not When the link is opened on Device A before expiry Then access is granted and the token is marked consumed When the same link is opened again on Device A Then access is denied with HTTP 410 Gone and a "Link already used" message When the link is opened on Device B at any time Then access is denied with HTTP 403 Forbidden and a "Link bound to another device" message And all denials are logged with standardized reason codes, excluding PHI
Expiration With Clock Skew Tolerance
Given the token TTL is configured to 10 minutes and clock skew tolerance to ±2 minutes When the link is opened on the bound device at T=9:59 Then access is granted When the link is opened at T=12:01 Then access is denied with HTTP 401 Unauthorized and a "Link expired" message And the denial includes a one-click flow to request a fresh link And audit logs capture reason "expired" with timestamps, excluding PHI
Secure Cookie and Privacy-Preserving Fingerprint
Given a modern browser that supports SameSite cookies and Web Crypto When issuing a device-bound magic link Then a Secure, HttpOnly, SameSite=Lax (or stricter) cookie scoped to the auth domain is set And the device fingerprint is derived only from an ephemeral Web Crypto public key, user agent, and the cookie identifier, salted and hashed server-side And no hardware identifiers, IP address, phone/email, or PHI are included in the fingerprint And deleting the cookie or key pair invalidates the binding and requires requesting a new link
FIPS-Validated Signing and Key Rotation
Given the cryptographic module is configured in FIPS-validated mode When tokens are issued Then they are signed with a FIPS-approved algorithm using keys stored in KMS/HSM And each token includes a kid; verification selects the correct active or previous key by kid When a key rotation occurs Then new tokens are signed with the new key and unexpired tokens signed by the previous key continue to verify until the previous key’s deactivation time After deactivation, tokens signed by the retired key are rejected with reason "key retired" And audit logs record key ids and rotation events without exposing key material or PHI
Multi-Channel Delivery and Deep Linking
Given the magic link must be delivered via SMS, email, and voice-driven URL When the messaging pipeline dispatches the message Then each channel carries the same opaque URL on the correct domain with no PHI in the path or query And on iOS/Android, opening the URL triggers Universal Links/App Links to open SmileCue if installed; otherwise it opens the system browser to the bound session And on desktop browsers, the URL opens the bound session in the default browser And the URL length is ≤ 2,048 characters and any analytics parameters are non-identifying and identical across channels
Forwarded/Intercepted Link Handling and Optional QR Handoff
Given a magic link is opened from a device that did not initiate the request When verification detects a device-binding mismatch Then access is denied with HTTP 403 Forbidden and a clear message that the link cannot be used on this device And the page offers two actions: "Request new link" (self-service) and "In-office QR handoff" (if feature flag enabled) When QR handoff is used in-office Then a staff-authorized workstation displays a QR code that, when scanned on the patient device, issues a fresh device-bound token without exposing PHI, and the original token remains unusable elsewhere And all events are audited with reason codes, excluding PHI
Token Validation and Replay Protection
"As an office manager, I want forwarded or intercepted links to be rejected and logged so that patient PHI isn’t exposed and we can address misdelivery issues."
Description

Validate incoming link requests by verifying token signature, expiry, device/browser binding, and single-use status. On first successful use, immediately revoke the token to prevent replay. Reject mismatches with clear, localized error states and capture reason codes (expired, device mismatch, replay, tamper). Apply IP- and tenant-scoped rate limits and progressive backoff to deter abuse. Integrate with SmileCue’s appointment confirmation and rescheduling endpoints so that successful validation continues the intended flow without added steps. Provide operational metrics and health checks for latency and failure-rate thresholds, ensuring security without hurting confirmation rates.

Acceptance Criteria
Seamless Pass-Through on First Valid Use
Given a signed, unexpired token bound to the originating device/browser and marked unused When the patient opens the link on the same device/browser within the configured TTL (default 15 minutes, configurable 5–60 minutes) Then the validator forwards the request seamlessly to the intended endpoint (/appointments/{id}/confirm or /reschedule) without additional steps (HTTP 302 to target) And the token is immediately revoked (single-use consumed) before downstream action executes And an audit event is recorded with reason_code=validated and a hashed device_fingerprint And no PHI appears in responses or logs
Expired Token Rejected with Localized Messaging
Given a token older than its configured TTL When a patient attempts to open the link Then the validator returns HTTP 401 Unauthorized with a localized error message (based on Accept-Language -> tenant default -> en-US) And reason_code=expired is returned in the response payload and logged And no downstream confirmation/rescheduling endpoints are invoked And no PHI appears in the response
Device/Browser Mismatch Blocks Access and Logs Reason
Given a token that is signed and within TTL but the device/browser fingerprint does not match the original requesting device beyond tolerance When the link is opened on a different device/browser Then the validator returns HTTP 401 Unauthorized with a localized error message And reason_code=device_mismatch is returned and logged with device/ip metadata (HIPAA-safe) And downstream confirmation/rescheduling endpoints are not called And response headers include Cache-Control: no-store and Pragma: no-cache
Single-Use Revocation Prevents Replay
Given a token that has already been successfully used and revoked When any client attempts to reuse the link Then the validator returns HTTP 401 Unauthorized with a localized error message And reason_code=replay is returned and logged And downstream endpoints are not invoked And the attempt increments a security counter for replay events
Tampered Signature Detection
Given a token whose signature fails verification or whose payload has been altered When the link is opened Then the validator returns HTTP 401 Unauthorized with a localized error message And reason_code=tamper is returned and logged And response headers include Cache-Control: no-store and Pragma: no-cache And no downstream calls are made
IP- and Tenant-Scoped Rate Limiting with Progressive Backoff
Given more than 20 validation attempts from the same IP in 60 seconds or more than 200 attempts for the same tenant in 60 seconds (defaults; both configurable per tenant) When further validation requests arrive within the window Then the validator returns HTTP 429 Too Many Requests with a localized error message and a Retry-After header And applies progressive backoff delays per offending principal (1s, 2s, 4s, up to 30s) until rates normalize And logs reason_code=rate_limit_ip or reason_code=rate_limit_tenant without throttling non-offending principals
Operational Metrics, Health Checks, and Confirmation-Rate Guardrail
Given live traffic over a rolling 24-hour window When exporting and evaluating validator telemetry Then metrics are emitted per tenant: validation_success_rate, reason_code_distribution, p50/p95/p99 latency, 4xx/5xx error rates, replay_attempts, and downstream_call_rate (HIPAA-safe) And the /health/validator endpoint returns status=healthy when p95 latency <= 250 ms and error_rate < 1%; status=degraded when thresholds are exceeded for 5+ consecutive minutes; status=down if signature verification failures > 10% for 5 minutes And an alert triggers if appointment confirmation conversion rate drops by > 5% absolute versus the prior 14-day baseline; a feature flag allows rollback on breach
In-office QR Handoff
"As a receptionist, I want to hand off a patient’s link to our check-in tablet via a quick QR scan so that we can assist them without exposing their information on other devices."
Description

Enable an optional front-desk flow where staff can generate a time-boxed QR code that authorizes a secure handoff of the patient’s link to a clinic-owned device (e.g., kiosk or tablet). The QR encodes a scoped, ephemeral grant tied to the patient and visit; scanning establishes a new device binding without exposing PHI. Handoff is restricted to configured clinic networks/locations and expires within seconds to limit misuse. Provide visual confirmations for staff and patients, fallback to short code entry if the camera is unavailable, and record all events for auditing. This preserves convenience during check-in while maintaining strong delivery controls.

Acceptance Criteria
Front Desk Generates Time-Boxed Handoff QR
Given a staff user is authenticated at a clinic location with handoff permission And a patient and visit are selected in the check-in module When the user selects "Generate Handoff QR" Then the system creates an ephemeral, one-time grant scoped to that patient and visit with a default TTL of 20 seconds (configurable) And renders a QR that encodes only a signed grant identifier and validation metadata, containing no PHI And any previously active handoff grant for that patient/visit is immediately invalidated And the staff UI displays a visible countdown matching the grant TTL
Handoff Restricted to Registered Clinic Devices and Networks
Given the QR is scanned by a registered clinic-owned device And the device is connected to an allowed clinic network (approved SSID/IP) and, if configured, within an allowed location/geofence When the device submits the grant for redemption Then the server verifies device enrollment, network/location policy, and grant signature And if any check fails, returns an "Access restricted" error and does not bind the device And all denied attempts are logged with a reason code
Successful Scan Establishes New Device Binding Without PHI Exposure
Given a valid, unexpired grant and an eligible clinic device on an allowed network/location When the grant is redeemed Then a new device binding is created for the patient/visit and associated with the clinic device fingerprint And the grant is consumed and cannot be reused And no PHI is transmitted within the QR payload or displayed on either screen before binding completion And the resulting session is least-privilege (limited to check-in for that visit) and auto-expires after 10 minutes of inactivity
Expired or Tampered QR Is Rejected
Given the QR is scanned after the grant TTL has elapsed or the payload has been altered When the device submits the grant Then the server rejects the request with "QR expired" or "Invalid grant signature" And the UI prompts staff to regenerate a new QR And no device binding is created or modified And the event is logged with reason code and device/network metadata
Fallback Short Code Entry When Camera Unavailable
Given the clinic device lacks a camera or camera permission is denied When the patient selects "Enter code instead" Then the staff view displays an 8-digit numeric short code corresponding to the active grant with the same TTL as the QR And the clinic device accepts the code and validates it server-side with rate limiting (max 5 attempts per minute per device) And on successful validation, the device is bound as in the QR flow and the grant is consumed And on failure or expiration, an error is shown and a safe regeneration option is provided
Visual Confirmations for Staff and Patient
Given a handoff is in progress When a QR is generated, redeemed, expires, or is denied Then the staff view displays state-specific banners: Ready with countdown, Success, Expired, or Denied with reason And the clinic device displays corresponding messages: Connecting…, Connected to your visit, QR expired, or Access restricted And no PHI is shown in any message until binding is complete
Comprehensive Audit Trail for Handoff Events
Given any handoff-related action occurs When generation, regeneration, scan attempt, redemption success, denial, or expiration happens Then an immutable audit record is stored with timestamp (UTC), staff user ID, patient visit ID, clinic location ID, device identifier hash, network info (SSID/IP), event type, outcome, and reason And sensitive payloads (QR contents, short code) are never stored in plaintext And authorized admins can filter and export audit records by date range, location, patient visit, user, and outcome
Legitimate Device Change Fallback
"As a patient, I want a simple, secure way to continue on a new device so that I’m not blocked from confirming or rescheduling my appointment."
Description

Provide a secure fallback path when a patient intentionally switches devices after requesting a link. Offer configurable options: approve-on-original-device prompt, SMS one-time code to the verified number on file, or minimal-knowledge verification aligned with HIPAA’s minimum necessary standard. Fallback attempts are rate-limited, logged, and time-bound; success establishes a new device binding and invalidates prior tokens. The experience is accessible (WCAG-compliant) and mobile-friendly to avoid support escalations while preserving privacy controls.

Acceptance Criteria
Approve on Original Device to Rebind New Device
- Given a patient requested a device-bound magic link on Device A and opens the same link on Device B within the token lifetime, When Device A is online and the session is active, Then Device A displays an approval prompt within 5 seconds that contains only the request time, general location (city/region), and device/browser type without PHI. - Given the approval prompt is shown on Device A, When the patient taps Approve within 10 minutes, Then Device B is bound to the session, the prior token is invalidated immediately, and Device A shows a success confirmation. - Given the approval prompt is shown on Device A, When the patient taps Deny or 10 minutes elapse, Then Device B is blocked from proceeding and receives a neutral denial message without revealing whether data matched. - Given the approval flow completes (approve or deny), Then an audit log entry is written with timestamp, method=original-device-approve, outcome, hashed device fingerprint, truncated user agent, and salted-hash of IP, with no message content or clinical data. - Given the approval succeeds, Then attempts to use the original link or any prior token on any device fail within 10 seconds globally with a message instructing the patient to request a new link.
SMS One-Time Code Fallback to Verified Number
- Given a verified mobile number exists on file, When the patient selects SMS code on Device B, Then a 6-digit numeric OTP is sent containing only the code and product name (no PHI) and expires in 5 minutes. - Given an OTP was sent, When the patient enters the correct code within 5 minutes, Then Device B is bound to the session, all prior tokens for this link are invalidated, and the flow resumes. - Given an OTP was sent, When 5 incorrect code attempts occur or 5 minutes elapse, Then the attempt is locked out for 15 minutes and logged; the UI shows a generic rate-limit message. - Given SMS delivery issues occur, When the user requests resend, Then resends are limited to 3 per hour with a minimum 30-second interval and each resend rotates the OTP and invalidates the prior code. - Given any OTP issuance or verification event occurs, Then an audit record captures timestamp, method=sms-otp, outcome, last-2 digits masked phone (e.g., xxx-xxx-xx12), and delivery status, without storing the plaintext code (store only a peppered hash).
Minimal-Knowledge Verification (MKV) Aligned with Minimum Necessary
- Given the practice has enabled MKV, When the patient selects MKV on Device B, Then the UI requests only practice-configured low-risk fields (e.g., birth month, ZIP/postal code, and last initial) without displaying stored values. - Given the patient submits MKV answers, When at least 2 of 3 fields match exactly to records, Then Device B is bound to the session and prior tokens are invalidated; otherwise, the attempt fails with a neutral message. - Given MKV failures, When 3 failed attempts occur within 15 minutes, Then MKV is locked out for that patient/link for 30 minutes and a generic help path is presented (no data disclosed). - Given MKV inputs are processed, Then values are compared server-side against normalized, hashed/peppered representations; no raw PHI values are logged or echoed back in the UI. - Given MKV is used, Then an audit log records timestamp, method=mkv, outcome, and which fields were challenged (not the values), per HIPAA minimum necessary.
Rate Limiting, Throttling, and Time-Bound Controls
- Given any fallback method is invoked, Then per-patient and per-link fallback initiations are limited to 5 per 24 hours and 1 per minute, with exponential backoff on repeated failures. - Given verification attempts occur, Then method-specific attempt limits apply: SMS OTP 5 tries per code; MKV 3 tries per 15 minutes; original-device approval 1 active prompt per link at a time. - Given a lockout is triggered, Then the UI displays a neutral message with next-allowed time and offers contact instructions without confirming identity details. - Given rate limits are enforced, Then responses use consistent HTTP status codes (e.g., 429 for rate-limited) and are logged with reason codes without exposing PHI. - Given time-bound links and codes, Then all tokens/prompts expire at or before their configured TTLs (magic link TTL, OTP 5 minutes, approval prompt 10 minutes) and cannot be reused after expiry.
Compliant Audit Logging and Retention for Fallback Events
- Given any fallback initiation, success, or failure occurs, Then an immutable audit entry is written within 2 seconds capturing timestamp, patient identifier (internal ID), method, outcome, truncated user agent, hashed device fingerprint, and salted-hash/truncated IP. - Given OTP or MKV values are processed, Then only hashed/peppered representations and non-sensitive metadata are stored; plaintext secrets and PHI values are never persisted. - Given audit logs are stored, Then they are tamper-evident (append-only with integrity checks), time-synchronized (NTP), and retained for a configurable period (default 6 years) per compliance policy. - Given authorized compliance users search logs, When filtering by patient ID, date range, and method, Then results return in under 5 seconds for 10,000-record ranges and are exportable in a de-identified format. - Given a privacy request is received, Then logs can be produced without revealing OTPs, MKV answers, or clinical content, demonstrating minimum necessary data handling.
Immediate Token Invalidation and New Binding Propagation
- Given any fallback method succeeds, Then all prior tokens and bindings related to the original magic link are invalidated immediately and cannot be used on any device. - Given invalidation occurs, When the old link is opened on any device, Then access is blocked within 10 seconds globally with a neutral message and a prompt to request a new link. - Given a new binding is established on Device B, Then only one active device/session is permitted for that link; parallel sessions on other devices are terminated. - Given network partitions or delays, Then eventual consistency still ensures invalidation within 30 seconds, with retries until confirmation is logged. - Given propagation completes, Then audit logs reflect the new device fingerprint and prior bindings marked as revoked with reason=fallback-rebind.
WCAG-Compliant and Mobile-Friendly Fallback Experience
- Given a patient uses a mobile device at 320px width, Then all fallback screens render responsively with tap targets ≥ 44x44px and primary actions above the fold. - Given assistive technologies are used, Then all interactive elements have accessible names/roles, visible focus, and meet WCAG 2.2 AA color contrast (≥ 4.5:1 for text) and are fully keyboard-navigable. - Given time-limited OTP or approval prompts, Then the remaining time is conveyed non-visually via ARIA live regions and is extendable once by at least 60 seconds without losing state. - Given SMS OTP inputs on iOS/Android, Then OS autofill is enabled via appropriate input attributes and does not expose the code in logs or analytics. - Given localization is enabled, Then fallback screens support at least English and Spanish with plain-language reading level at or below grade 8 and consistent terminology across methods.
Admin Policy Controls and Configuration
"As a practice administrator, I want to configure device-binding policies and fallbacks so that we balance security with patient convenience across our locations."
Description

Provide tenant-level settings to enable Device Bind per channel (SMS, email, voice portal), configure token TTL and single-use enforcement, toggle in-office QR handoff, and choose enforcement levels (strict vs. lenient with fallback). Allow allowlisting of clinic networks/devices, customization of error messaging and help text, and A/B toggles to measure impact on confirmation rate and no-shows. Surface dashboards with adoption, mismatch rates, and fallback success metrics. Integrate with SmileCue’s feature flag system, role-based access controls, and configuration audit trails.

Acceptance Criteria
Channel-Level Device Bind Policy Toggle
Given a tenant admin with the Security Admin role and the Device Bind feature flag enabled When they enable or disable Device Bind independently for SMS, email, and voice portal and click Save Then the configuration persists tenant-wide, returns via GET /admin/device-bind/settings within 1 minute, and applies only to newly generated links (no retroactive impact) And an audit trail entry records actor, timestamp, channel changes (before/after), and reason And unauthorized roles cannot modify settings (receive 403) but can view read-only if permitted
Token TTL and Single-Use Enforcement Configuration
Given an admin sets token TTL per channel between 5 and 120 minutes and toggles single-use enforcement When values are valid and saved Then new magic links for that channel expire after the configured TTL and cannot be reused once successfully redeemed And attempts to save invalid TTLs (out of range, non-integer) or disable single-use while strict enforcement is on are rejected with inline errors And the effective TTL and single-use values are returned by the admin API and logged in the configuration audit trail
In-Office QR Handoff Control and Safeguards
Given the in-office QR handoff is enabled and at least one clinic network/device is allowlisted When a patient scans the QR on an allowlisted network/device within the configured session window Then the session is transferred without device-mismatch blocking and the magic link remains single-use and respects TTL And QR payloads contain no PHI and expire after one successful handoff or on TTL, whichever occurs first And if the QR is scanned off the allowlisted network/device, access is blocked and the customized error/help text is shown
Enforcement Levels with Fallback and Outcomes Logging
Given enforcement is set per channel to Strict or Lenient with fallback When Strict is active and a device mismatch occurs Then access is blocked, the attempt is logged, and no fallback is offered When Lenient is active and a device mismatch occurs Then the user is offered a configurable fallback (e.g., OTP to the original channel or secondary verification) with max attempts and timeout And successful fallback grants access and is recorded as a fallback success; failures are blocked and logged And enforcement decisions are included in analytics events for dashboards
Allowlist of Clinic Networks and Managed Devices
Given an admin manages an allowlist supporting IPv4/IPv6 CIDR ranges and managed device IDs with optional labels and expiry dates When entries are added, edited, or removed with valid formats and within quota limits Then changes take effect within 5 minutes and are captured in the audit trail with before/after values And device-mismatch checks bypass enforcement only when requests originate from a currently allowlisted network/device, with the matching rule ID recorded in logs and analytics And invalid entries (malformed CIDR, duplicate device ID, past expiry) are rejected with actionable errors
Custom Error Messaging and Help Text per Channel
Given an admin customizes error and help text per channel using approved placeholders (e.g., {practice_name}, {support_phone}, {retry_link}) When content passes validation (no PHI placeholders, length limits, sanitized formatting, language selection) Then end users see the customized copy on mismatch or expiry within 5 minutes of publish And a live preview renders example messages before publish and a default fallback is used if custom content is missing And accessibility checks (contrast, focus order, screen reader labels) meet WCAG AA for the presented error views
Dashboards and A/B Experimentation for Device Bind Impact
Given A/B toggles are enabled per channel with randomization at the appointment level and sticky assignment for 30 days When exposure begins Then dashboards report adoption, device mismatch rate, fallback success rate, confirmation rate, and no-show rate with filters for date range, channel, and clinic location And metrics update with data latency ≤ 60 minutes and support CSV export And stopping an experiment prevents new assignments without altering historical cohorts And dashboard and export access follow RBAC; underlying settings and experiment changes are tracked in the audit trail
Audit Logging, Monitoring, and Compliance
"As a compliance officer, I want complete, PHI-safe logs and alerts for device-bound link activity so that we can demonstrate safeguards and investigate incidents when needed."
Description

Capture immutable, access-controlled logs for token issuance, validation outcomes, mismatches, fallbacks, and QR handoffs with timestamps, tenant IDs, reason codes, and minimal contextual metadata—no PHI in payloads. Encrypt logs at rest, enforce retention aligned to HIPAA and organizational policy, and provide export to SIEM. Implement alerts for anomaly patterns (e.g., spikes in device mismatches) and publish operational dashboards for latency, error rates, and replay detections. Document controls and provide evidence packs to support HIPAA audits and BAAs, including key rotation and disaster recovery procedures.

Acceptance Criteria
Token Lifecycle Audit Logging (Device Bind)
- Given a tenant requests a Device Bind magic link token, When the token is issued, Then an audit record with event_type=token_issued, tenant_id, request_id, token_id (non-reversible), device_id_hash, user_agent_hash, ip_prefix (/24 IPv4 or /64 IPv6), timestamp (UTC ISO-8601), and reason_code=issued is appended. - Given a token is presented for validation, When validation succeeds, Then an audit record with event_type=token_validated_success and the above metadata (no PHI) is appended within 1 second of the decision. - Given a token is presented for validation, When validation fails, Then an audit record with event_type=token_validation_failed and failure_reason in {device_mismatch, expired, signature_invalid, replay_detected, not_found} is appended within 1 second. - Given a token is replayed, When replay is detected, Then an audit record event_type=replay_detected links original token_id and attempt_id with a monotonic sequence number and chain_hash.
Device Mismatch and Fallback Logging
- Given a validation attempt from a non-bound device, When Device Bind blocks access, Then event_type=device_mismatch is logged with previous_device_hash, new_device_hash, decision=blocked, reason_code=device_mismatch, mismatch_counter (per token), and timestamp. - Given an approved fallback is initiated, When fallback begins, Then event_type=fallback_initiated with fallback_type in {sms_otp, in_office_qr, staff_override}, actor_role, tenant_id, and request_id is logged. - Given a fallback completes, When outcome is known, Then event_type=fallback_completed with outcome in {success, canceled, timeout, denied}, duration_ms, and correlation to fallback_initiated is logged. - Rule: No fallback-related log entry contains PHI; automated DLP scan returns zero PHI indicators on sample sets and CI checks block deployments if violated.
QR Handoff Logging Without PHI
- Given staff displays an in-office QR code, When the QR is generated, Then event_type=qr_displayed with tenant_id, location_id (if available), token_id, and timestamp is logged with no PHI fields present. - Given the QR is scanned on an in-office device, When the scan is processed, Then event_type=qr_scanned with device_id_hash, token_id, outcome in {bound, rejected, expired}, reason_code, and timestamp is logged. - Given QR handoff binds the session, When binding succeeds, Then event_type=qr_handoff_bound ties new_device_id_hash to token_id and records policy_decision=allowed. - Rule: QR events store minimal contextual metadata only; DLP and schema validation prohibit patient identifiers (name, email, phone, DOB, address, images).
Immutable, Access-Controlled Logs with Retention
- Given the audit log store is configured, When a log record is committed, Then the record is immutable (append-only) with content_hash and chain_hash and a write-once retention lock is applied. - Given any actor attempts to modify or delete a committed record before retention expiry, When the operation is attempted, Then it is denied and an access_denied audit event is written. - Given access to logs is requested, When authorization is evaluated, Then only roles in {SecurityAdmin, ComplianceAuditor} may read; service principals may write but not read; all access attempts are logged. - Given tenant retention policies are configured, When daily retention jobs run, Then records older than the tenant-configured period (default 6 years; min 1 year; max 10 years) are purged within 30 days unless legal_hold=true. - Rule: Metadata is limited to tenant_id, event_type, timestamps, hashed identifiers, reason codes, and operational context; no PHI is stored.
Encryption at Rest and Key Rotation Evidence
- Given audit logs are stored, When encryption status is checked, Then encryption_at_rest=enabled with KMS-managed keys using FIPS-validated algorithms is verifiable via configuration and API. - Given key rotation policy is configured, When rotation occurs (≥ annually or on compromise), Then old keys are retired and new keys activated without data loss; event_type=key_rotation is logged with timestamp and key alias. - Given a compliance evidence request, When an evidence pack is generated, Then it includes current encryption configuration, last rotation date, key identifiers (redacted as required), and pass/fail results of quarterly encryption audits. - Given a disaster recovery drill is executed, When audit log restoration is tested, Then RTO ≤ 4 hours and RPO ≤ 15 minutes are achieved and captured in the evidence pack.
SIEM Export with Delivery Guarantees and Integrity
- Given a tenant SIEM integration is configured, When audit events are generated, Then ≥99% of events are delivered to the SIEM within 5 minutes with at-least-once delivery semantics and a deduplication_id present. - Given network interruptions occur, When connectivity resumes, Then the backlog is replayed and events up to the last 24 hours are delivered with dropped_events_count=0. - Given integrity verification is enabled, When the SIEM ingests logs, Then message signatures or checksums validate against the published public key with verification failure rate <0.1%; failures emit alerts. - Rule: Exported payloads contain no PHI and are scoped to the requesting tenant only; configuration supports HTTPS (mTLS) or Syslog over TLS with TLS 1.2+.
Anomaly Alerts and Operational Dashboards
- Given baseline metrics are computed per tenant, When device_mismatch rate exceeds 3x the 7-day moving average or >50 mismatches within 15 minutes, Then an anomaly alert is sent to the on-call channel within 5 minutes including tenant_id and recent samples. - Given replay_detected events are observed, When counts exceed 10 within 15 minutes per tenant, Then a high-severity alert is fired and escalation policy is applied. - Given the Device Bind monitoring dashboard is loaded, When viewed by authorized users, Then it shows p50/p95/p99 token validation latency, error rates, mismatch counts, replay counts, and QR handoff success rate with tenant and environment filters; data freshness ≤ 1 minute; dashboard availability ≥ 99.9% monthly. - Rule: Alert rules, runbooks, and dashboard links are version-controlled and accessible to Security and Ops.

SecureShare

Enables patients to securely delegate access to a caregiver for a single item via a separate, time-boxed OTP link. Honors guardian permissions, logs the relationship, and auto-expires after use—supporting real-world family workflows without screenshots or HIPAA headaches.

Requirements

Single-Use, Time-Boxed OTP Link Generation
"As an office manager, I want to generate a single-use, time-limited link for a specific document so that a caregiver can securely view it without exposing the rest of the patient’s record."
Description

Generate a cryptographically secure, single-use OTP link that is time-boxed and bound to a specific patient and item. The token includes claims for patient ID, item ID, and purpose, and expires automatically after the first successful access or when the configurable TTL elapses. No PHI is embedded in the URL or outbound notifications. Implement server-side invalidation, replay detection, and rate limits on OTP verification attempts. Store tokens as hashed, short-lived secrets with key rotation support. Expose creation as an internal API for SmileCue messaging flows and staff tools, emitting events for analytics and monitoring. This ensures caregivers can securely access only what’s intended without exposing broader records, aligning with HIPAA minimum-necessary standards.

Acceptance Criteria
Token Claims Integrity and Non-PHI URL/Notifications
Given an internal API request to create a SecureShare OTP with patientId=P, itemId=I, purpose="caregiver_view", and TTL=30 minutes When the API returns the OTP link Then the URL contains only an opaque token (no patient name, item title, DOB, phone, email, diagnosis, or other PHI in path or query) And the server-verifiable claims for the token include patientId=P, itemId=I, purpose="caregiver_view", iat, and exp within the configured TTL And the token can be verified using the current server keyset without network calls to third parties And the outbound notification content (SMS/email/voice) that includes the link contains no PHI or item metadata and passes automated content checks
Single-Use Redemption and TTL Expiration Enforcement
Given TTL is configured to 30 minutes and a token T is created at time T0 When a caregiver redeems T at time T0+10 minutes Then verification succeeds, access to only the specified item is returned with HTTP 200, and T is marked consumed server-side And a subsequent redemption attempt with T returns HTTP 410 with reason "consumed" and no data When a caregiver first attempts redemption at time T0+31 minutes Then verification fails with HTTP 410 with reason "expired" and no data is returned And audit logs contain "otp.redeemed" and "otp.expired" events with timestamps and request metadata (IP, user agent) and no PHI
Scope Enforcement to Minimum Necessary
Given a valid token bound to patientId=P, itemId=I, and purpose="caregiver_view" When the token is presented to any endpoint other than the single-item retrieval for item I Then access is denied with HTTP 403 and reason "scope_mismatch" And no list, search, or adjacent metadata endpoints can be accessed with the token And attempts to use the token for any other patient or item fail with HTTP 403 and are fully audited without leaking data And the successful redemption path returns only the minimum necessary fields for item I
Server-Side Invalidation and Replay Detection
Given a valid token T exists When staff revoke T via the admin tool or internal API Then subsequent verifications of T fail with HTTP 410 and reason "revoked" And an event "otp.revoked" is emitted with tokenId and revoker identity (no PHI) Given T was successfully redeemed once When T is presented again Then verification fails with HTTP 409 and reason "replay_detected" And an audit event "otp.replay_detected" is recorded with timestamp, IP, and user agent, and returns no data
Verification Rate Limiting and Lockout
Given a rate-limit policy of max 5 failed verifications per token per 10 minutes and max 20 failed verifications per IP per hour When the number of failed verifications for a token exceeds 5 within 10 minutes Then subsequent attempts for that token within the window return HTTP 429 "rate_limited" and do not reveal token existence or validity When the number of failed verifications from an IP exceeds 20 within an hour Then subsequent attempts from that IP return HTTP 429 and are logged for security review And counters reset after their windows elapse, and corresponding metrics and alerts are emitted
Hashed Secret Storage and Key Rotation Support
Given a token T is created Then the stored representation is a salted, peppered hash; the raw token value is never stored or logged And application logs redact or hash any token-like values When the signing/verification key rotates from K1 to K2 Then tokens issued under K1 remain verifiable until their exp timestamps, and new tokens are issued under K2 And attempts to verify any token after its exp fail regardless of key state And a "crypto.key_rotated" audit event is recorded without exposing key material
Internal API Creation and Event Emission
Given an authenticated internal client with scope "secure_share:create" calls POST /internal/secure-share/otp with patientId, itemId, purpose, and TTL When the request is valid Then the API responds 201 with { linkUrl, expiresAt, tokenId } and includes no PHI in the response And idempotency is enforced via Idempotency-Key such that a retried request within 5 minutes returns the original result without creating a new token And input validation rejects invalid or out-of-range TTLs with HTTP 400 and missing scope with HTTP 403 And events "otp.created" and "otp.delivery_queued" (if applicable) are emitted with tokenId, patientId, itemId, purpose, expiresAt, clientId, and no PHI And metrics record request counts, latency, error rates, and event emission success
Item-Scoped Access Enforcement
"As a front-desk coordinator, I want the caregiver’s link to be restricted to a single file so that they can’t browse or discover any other patient information."
Description

Enforce strict, item-level scoping so the recipient can only view/download the single shared item with read-only permissions. Validate every request against token claims and policy checks (patient, item, scope, expiry, status). Prevent navigation or enumeration of other resources (no listings, index, or API expansion). Use ephemeral, pre-signed object access conditioned on scope and expiry; disable caching and prevent embedding where possible. Apply optional viewer watermarking and click-through notices to deter onward sharing. Ensure accessibility- and mobile-friendly rendering with PHI minimization. This containment guarantees the share is narrowly limited to the intended artifact and nothing else.

Acceptance Criteria
Token and Policy Validation on Every Request
Given any request to a SecureShare item endpoint with an OTP token When the server processes the request Then it validates token signature, expiration, revocation/status, patient_id, item_id, and scope=read-only for that item And if any check fails Then respond with 401 (invalid/expired) or 403 (unauthorized) and return no item bytes
Single-Item Scope Enforcement and No Enumeration
Given a valid token scoped to item X When the recipient requests any resource other than item X (e.g., lists, search, index, another item ID, or using expand/related parameters) Then the server returns 403/404 and exposes no links or metadata about other resources And direct URL tampering where itemId != X returns 403 And the UI presents no navigation to other items or collections
Ephemeral Pre-Signed Object Access and Single-Use Expiry
Given an unredeemed SecureShare OTP link When the recipient successfully views or downloads the item Then the OTP token is marked used and cannot be redeemed again And subsequent requests with the same token return 410 Gone And any pre-signed object URL issued for the item expires at or before the token expiry and cannot be reused after expiry And requests after token or URL expiry return 401/403 with no content
No Caching and Anti-Embedding Controls
Given the item viewer or download endpoint is requested Then response headers include Cache-Control: no-store, Pragma: no-cache, and an Expires value in the past And X-Frame-Options: DENY or Content-Security-Policy with frame-ancestors 'none' is present to block embedding And Referrer-Policy is no-referrer And X-Content-Type-Options is nosniff And no content is rendered when loaded inside a non-allowed iframe
Read-Only Viewer With Optional Watermark and Click-Through Notice
Given click-through is enabled by practice policy When the recipient opens the link Then a notice is presented and must be accepted before any item bytes are rendered And declining prevents access Given watermarking is enabled When the item is displayed or downloaded (PDF/PNG/JPG) Then a semi-transparent watermark with practice name, recipient label, and timestamp is applied And at no time are edit, re-share, or upload controls available
Accessible, Mobile-Friendly Rendering With PHI Minimization
Given the item viewer loads on devices >=320px width Then the layout is responsive without horizontal scroll, supports keyboard navigation, exposes accessible names/roles, and meets WCAG 2.1 AA color contrast And focus order is logical and visible Given the viewer chrome (outside the item content) Then it shows only minimal patient identifiers (initials) and practice name and excludes DOB, SSN, full address, and insurance IDs And URLs, query parameters, and headers contain no PHI
Guardian Permission Enforcement
Given the patient has guardian/consent restrictions When a SecureShare OTP link is redeemed Then access is granted only if the patient's guardian policy permits caregiver access for the specific item and scope And otherwise the server returns 403 without disclosing the existence of other resources
Relationship Verification & Consent Capture
"As a dentist, I want to verify the caregiver’s relationship and capture consent or guardian status so that any share complies with HIPAA and our practice policies."
Description

Capture and verify the caregiver’s identity and relationship (e.g., legal guardian, spouse, adult child) and honor guardian permissions from the patient record. For minors, require a guardian of record; for adults, capture the patient’s express consent or use an existing authorization on file per practice policy. Collect caregiver contact details, present HIPAA-compliant disclosures, and log an attestation and timestamped e-signature when required. Perform OTP verification to the caregiver’s channel to confirm possession. Persist the relationship and consent artifacts to the patient profile for future reference and auditing, blocking shares when required permissions are missing.

Acceptance Criteria
Adult Patient Consent and Authorization Handling
Given an adult patient record and a SecureShare request for a specific item When an active authorization on file satisfies practice policy for the item category Then the system references the existing authorization ID and proceeds without prompting for new consent And the authorization reference is recorded in the audit log tied to the share Given an adult patient record and a SecureShare request for a specific item When no valid authorization on file exists per practice policy Then the patient is presented HIPAA disclosures and must provide explicit consent via attestation and timestamped e-signature And the captured consent record is stored on the patient profile with scope, item, and policy-defined validity And sharing is blocked until consent is successfully captured
Minor Share Restricted to Guardian of Record
Given a minor patient (under the practice-defined age of consent) and a SecureShare request When selecting a caregiver for the share Then only guardians of record from the patient profile are selectable And non-guardians or unverified relationships cannot be chosen And guardian scope/permissions from the patient record are enforced for the requested item category And if no eligible guardian exists or scope does not cover the item, the share is blocked with a clear reason and an audit event
Caregiver Identity, Relationship, and Contact Capture
Given a caregiver is invited via SecureShare When entering identity and relationship details Then the form requires legal first name, legal last name, relationship selected from a controlled list, and a unique contact channel (mobile or email) And phone numbers validate to E.164 format and emails validate to RFC 5322 format And duplicate caregiver contacts for the same patient are detected and surfaced to prevent accidental duplicates And on submit, a relationship record is created with status "Pending Verification" including createdBy, timestamp, item scope, and policy basis
Caregiver OTP Possession Verification and Link Expiry
Given a caregiver relationship with status "Pending Verification" When the OTP is sent to the caregiver’s declared channel (SMS or email) Then the OTP is randomly generated, single-use, has a minimum length of 6 digits/characters, and expires within the configured TTL And a maximum attempt limit and rate limiting/backoff are enforced per security policy, with temporary lockout after exceeding the limit And on successful OTP entry, the relationship status updates to "Verified", the share link activates, and the OTP is invalidated And the access link auto-expires after first successful access or at the configured TTL (whichever occurs first) And all OTP and access events (success/failure, channel, IP/device fingerprint, timestamp) are recorded in the audit log
HIPAA Disclosures, Attestation, and E‑Signature Capture
Given a patient or authorized guardian is providing consent for a SecureShare When disclosures are presented Then HIPAA-compliant disclosures are shown with version, locale, and policy basis And the user must attest via required checkbox and provide an e‑signature that captures signer name, intent, timestamp, and a hash of the consent text And submission is blocked until all required fields are completed and disclosures are acknowledged And a consent receipt is generated and stored on the patient profile and available via audit export
Persistence and Auditability of Relationship and Consent Artifacts
Given a SecureShare completes or is blocked When persisting artifacts Then the system stores relationship details, caregiver contact, role/relationship type, consent or authorization reference, disclosure version, e‑signature artifacts, OTP verification outcome, item identifier, scope, initiator, recipient channel, and timestamps And records are immutable (append-only), with each update creating a new version and preserving a full audit trail And authorized staff can retrieve these artifacts from the patient profile and via audit export, with access governed by RBAC and fully logged
Permission Enforcement and Share Blocking
Given a SecureShare request is initiated When required permissions are missing, authorization is expired, consent is revoked, or guardian scope does not cover the requested item Then no share link is generated and the user is shown a specific, actionable reason (e.g., "No valid consent on file", "Guardian scope excludes clinical images") And an audit event records the blocking policy rule, user, patient, item, and timestamp And the system allows retry only after the blocking condition is remediated (e.g., new consent captured or scope updated by authorized staff)
Audit Logging & Compliance Trail
"As a compliance officer, I want a complete audit trail of SecureShare activity so that we can demonstrate compliance and investigate any suspected misuse."
Description

Record an immutable, structured audit trail for all SecureShare events, including link creation, delivery, access attempts (success/failure), OTP verifications, expirations, revocations, and content viewed. Log actor identifiers (staff user, patient, caregiver), relationship type, timestamps, channel, IP/device metadata, and policy decisions without storing unnecessary PHI. Provide retention aligned to HIPAA requirements, search and filter in the admin console, and export to CSV/SIEM. Surface alerts for anomalous behavior (excessive failures, repeated access after expiry) and attach audit references back to the patient record for end-to-end traceability.

Acceptance Criteria
Complete SecureShare Event Logging with Minimal PHI
- Given a SecureShare link is created, When creation is requested, Then an audit event event_type=link_created is written with event_id (UUIDv4), correlation_id, timestamp_utc (ms), patient_id, staff_user_id (if applicable), channel, and policy_decision (allow/deny with reason). - Given a link is delivered via SMS/email/voice, When delivery is attempted, Then event_type=link_delivered is recorded with channel, delivery_status (queued/sent/failed), provider_message_id, and error_code when failed. - Given a recipient attempts to access a link, When the request is received, Then event_type=access_attempt is recorded with success (true/false), failure_reason (expired/revoked/otp_required/otp_failed/other), ip_address, user_agent, device_fingerprint (sha256), geo_country, and channel. - Given OTP entry occurs, When OTP is verified, Then event_type=otp_verified is recorded with verification_result (success/failure) and attempt_count. - Given a link expires or is revoked, When the state changes, Then event_type=link_expired or link_revoked is recorded with cause (ttl/revoked_by_staff/user) and previous_state. - Given protected content is displayed, When access is granted, Then event_type=content_viewed is recorded with content_type (e.g., appointment_details/bill/estimate) and redacted=true. - Given any audit event is persisted, When stored, Then it includes actor_type (patient/caregiver/staff/system), actor_ref_id (internal UUID), relationship_type (self/guardian/parent/spouse/other when caregiver), and staff_role when actor_type=staff. - Given any audit event is persisted, When validated against schema, Then no unnecessary PHI is stored (no message_body, clinical_notes, diagnosis codes, or full PII); only minimal identifiers (patient_id, actor_ref_id) are present; writes with disallowed fields are rejected and a compliance_violation event is logged.
Immutable, Append-Only Audit Log with Tamper Evidence
- Given the audit storage API, When attempting to update or delete an existing event, Then the operation is rejected with 403 and no record is modified. - Given audit events are written, When verifying integrity, Then each event includes previous_hash and record_hash forming a hash chain, and chain verification returns valid=true for unaltered ranges. - Given daily close at 00:00 UTC, When the day ends, Then a daily_anchor event is generated with the day's root hash and stored in an immutable (WORM) location. - Given duplicate writes with the same event_id, When retried, Then only one record exists (idempotent write).
Retention and Purge Policy (HIPAA-Aligned)
- Given retention_policy_years is configured to ≥6, When events age beyond the retention period, Then they are purged automatically within 30 days and a purge_summary event is logged. - Given a legal hold is applied to a patient or case, When the purge job runs, Then events under hold are retained until the hold is removed and holds are auditable. - Given a search for events older than retention and not on hold, When executed, Then purged events are not returned in UI or API. - Given a compliance admin views retention settings, When opened, Then the effective retention period and active legal holds are visible with last_purge_timestamp.
Admin Console Search, Filter, and RBAC
- Given a compliance admin is in the Audit Log UI, When filtering by date range, event_type, actor_type, relationship_type, channel, success/failure, patient_id, staff_user_id, ip_address, and policy_decision, Then results accurately reflect filters with pagination and sortable timestamp. - Given a dataset of 100k events, When a filtered search is executed, Then the first page returns within 3 seconds at p95. - Given a user without Compliance/Admin role, When attempting to access the Audit Log UI or API, Then access is denied with 403 and the attempt is itself audited with event_type=access_denied.
Export to CSV and SIEM
- Given filtered audit results, When Export CSV is requested, Then a UTF-8 CSV with a fixed header schema is generated and available within 60 seconds for up to 1,000,000 rows, with chunked pagination for larger datasets. - Given an exported CSV, When validated, Then all timestamps are UTC, values are properly quoted, line endings are LF, and no PHI fields are present. - Given SIEM forwarding is configured, When new events are written, Then events are forwarded in NDJSON batches (max 10 MB or 5,000 events) over TLS 1.2+, signed with HMAC-SHA256, with retries using exponential backoff up to 24 hours and idempotency via event_id. - Given SIEM delivery failures exceed 1 hour, When detected, Then a compliance alert is raised and a siem_delivery_failure event is logged.
Anomaly Detection and Alerting
- Given a single SecureShare link, When ≥5 failed otp_verified or access_attempt events occur within 10 minutes, Then an alert is created within 1 minute, visible in the Admin Console and sent to the configured compliance notification channel. - Given a link is expired or revoked, When ≥3 access_attempt events occur after expiry within 24 hours, Then an alert is created and linked to the offending IPs. - Given ≥10 distinct IP addresses attempt the same link within 30 minutes, When detected, Then an alert with severity=high is generated and rate-limiting is applied to the link. - Given any alert is created, When viewing the alert, Then it contains direct references to the triggering audit events and affected patient/caregiver actor_ref_ids.
Audit References Linked to Patient Record
- Given a patient with SecureShare activity, When viewing the patient record, Then an Audit section displays related audit events with deep links to the Audit Log UI and pre-populated filters. - Given an audit event pertains to a patient, When recorded, Then it includes patient_id and optional visit_id enabling cross-linking without exposing PHI. - Given a user without appropriate role attempts to view audit from the patient record, When access is attempted, Then access is denied with 403 and the attempt is audited. - Given a caregiver is involved, When viewing audit references, Then relationship_type and actor_ref_id are visible without revealing caregiver PII.
SecureShare Policy Controls & Templates
"As a practice admin, I want to configure timeouts, retries, delivery channels, and templates so that SecureShare matches our compliance requirements and brand voice."
Description

Provide practice-level configuration for SecureShare, including default TTL, single-use toggles, maximum OTP attempts, lockout duration, allowed delivery channels (SMS/email), and permitted relationship types. Manage consent requirements by context (minor vs. adult, specific item categories), and configure legal disclaimers and pre-approved content templates with merge fields. Expose role-based access to initiate, revoke, and view shares, and allow admins to override defaults per share when authorized. Centralized policies ensure consistent risk posture, brand alignment, and easier rollout across locations.

Acceptance Criteria
Apply Practice Defaults and Authorized Overrides
Given a practice admin configures defaults for TTL, single-use toggle, max OTP attempts, and lockout duration within allowed ranges (TTL: 5 minutes–14 days; Attempts: 1–10; Lockout: 1–1440 minutes) When any staff member initiates a new SecureShare Then the system auto-applies the current practice defaults to the share And only users with the Policy_Override permission can modify these fields per share prior to send And any per-share override requires an override reason and is recorded in an immutable audit log with actor, timestamp, patient ID, item ID, field changed, and before/after values And users without Policy_Override attempting to change policy fields receive a validation error and the change is not saved
Enforce Allowed Delivery Channels with Fallback
Given the practice has enabled specific delivery channels (SMS, Email) at the practice or location level When a sender attempts to send a SecureShare via a disabled channel Then the send is blocked with an error referencing the channel policy and no message is sent When the preferred channel fails a deliverability check (e.g., invalid number/email) and another allowed channel exists Then the system prompts the sender to switch to an allowed channel and logs the chosen channel in the audit trail And all sends record channel type and policy version used at send time And changes to channel policy do not retroactively affect already-sent links
Validate Relationship Types and Guardian Permissions
Given the practice has configured a whitelist of permitted relationship types (e.g., Parent/Guardian, Spouse/Partner, Adult Child, Caregiver, Power of Attorney) When a sender selects a relationship not on the permitted list Then the selection is blocked with a policy error and cannot proceed When the patient is a minor Then only guardian-permitted relationship types may be selected and an associated guardian record must exist on file; otherwise sending is blocked When the item category requires Power of Attorney for adult patients per policy Then the system verifies a valid POA document on file before allowing send And the selected relationship type (and guardian linkage for minors) is recorded in the audit log
Enforce Contextual Consent by Age and Category
Given consent rules are configured by patient context (minor/adult) and item category (e.g., appointment reminder, treatment plan, billing) When initiating a SecureShare that matches a rule requiring consent Then the system requires selection of a consent template and capture of consent (eSignature or documented verbal consent) before send And the consent record stores timestamp, actor, patient ID, template ID and version, and share ID, and is immutable in the audit log When a valid consent exists within the configured lookback window Then the system allows send without re-capturing consent and references the prior consent in the audit When consent is missing or expired for a required context Then the send is blocked with a specific policy message
Validate Disclaimers and Templates with Merge Fields
Given admins manage legal disclaimers and message templates with an approved merge-field whitelist (e.g., patient_first_name, practice_name, share_expiry, item_type) When a sender composes a SecureShare using a template Then all merge fields must resolve successfully; unresolved or unapproved placeholders block send with a detailed error listing offending fields And required disclaimers are appended to the outbound message and shown in the sender preview And the final rendered content preview and template version/hash are stored in the audit log And templates containing unapproved PHI placeholders are rejected at save time by admins and at send time by users
Role-Based Initiate/Revoke/View Permissions
Given roles map to permissions: Initiate_Share, Revoke_Share, View_Share, Policy_Override When a user without the required permission attempts an action (initiate, revoke, view audit) Then the action is denied, no data is exposed, and the attempt is written to the security log with actor, timestamp, and action When a user with Revoke_Share revokes an active link Then the link is immediately invalidated, future access attempts fail, and the revoke event (actor, reason, timestamp) is captured in the audit When a user with View_Share views share details Then only share metadata and audit entries are visible; original item content is not displayed And permission changes propagate within 5 minutes and are versioned in the audit
OTP Attempts, Lockout, TTL, and Single-Use Enforcement
Given max OTP attempts and lockout duration are configured per practice or overridden by an authorized admin per share When the recipient exceeds the configured max OTP attempts Then the link is locked for the configured duration and subsequent attempts return a lockout message without exposing PHI When the share TTL expires or a single-use link has been successfully redeemed once Then subsequent access attempts are denied with an expiry/used message and an audit entry is created And OTP codes expire after their configured lifetime (default 10 minutes) and cannot be reused or extended by the recipient And successful redemption logs timestamp, recipient IP, and device fingerprint where permitted by policy, aligning with HIPAA access logging
Adaptive Delivery & Messaging Flow Integration
"As a hygienist, I want to send a SecureShare link through the patient’s preferred flow and have automatic fallbacks so that caregivers reliably receive access without extra follow-up."
Description

Integrate SecureShare into SmileCue’s adaptive messaging engine to collect caregiver details, verify channels, and deliver OTP links via SMS or email based on patient input and delivery health. Support failover (e.g., switch to email if SMS bounces), scheduled reminders before expiry, and one-tap reissue flows if a link expires or is consumed. Ensure separation of channels so the caregiver receives a distinct link from the patient’s notifications. Provide staff-side shortcuts in the inbox/scheduler to initiate SecureShare within existing workflows, reducing manual effort while improving reliability of caregiver access.

Acceptance Criteria
Collect & Verify Caregiver Contact with Guardian Permission Check
Given a patient or staff initiates SecureShare for a single item When the system prompts for caregiver details Then the system requires caregiver full name, relationship to patient, and at least one contact channel (mobile number or email) And when a channel is provided, the system sends a 6-digit verification code to that channel and requires entry within 10 minutes And verification is limited to 5 failed attempts before locking that channel for 15 minutes And if guardian permissions exist on the patient record, the system enforces them by limiting shareable items and requiring guardian-consent flags before link issuance Then an audit record is created capturing timestamp, initiator (patient or staff), relationship, verified channel(s), and consent indicators
Adaptive Delivery with SMS-to-Email (and Email-to-SMS) Failover
Given caregiver contact has been verified for SMS and/or email And delivery health events are monitored in real time When initial delivery is attempted via the patient’s indicated preference Then if SMS returns hard bounce or carrier-undeliverable within 60 seconds, the system sends the OTP link to the verified email within the next 60 seconds And if email hard-bounces within 5 minutes, the system sends the OTP link by SMS if verified And the final successful delivery channel is recorded and visible in logs; no copies of the link are sent to the patient And if neither channel is deliverable, the system notifies patient/staff to collect an alternate channel and pauses delivery attempts
Single-Use, Time-Boxed OTP Link
Given an OTP link is generated for a specific caregiver and item Then the link contains a unique single-use token with at least 128 bits of entropy and is bound to that caregiver and item And the default expiry is 48 hours, configurable between 1 and 72 hours at the practice level And upon first successful access, the token is consumed and immediately invalidated And any subsequent access attempts return an expired/consumed message and offer a reissue option to patient/staff only And all access attempts (success, expired, consumed) are timestamped and stored in the audit log
Scheduled Reminders Before OTP Expiry
Given an active OTP link has not yet been accessed When time remaining reaches 12 hours before expiry Then send a reminder to the last known deliverable caregiver channel; if undeliverable, attempt the alternate verified channel When time remaining reaches 1 hour before expiry Then send a final reminder (maximum two reminders per link) And no reminders are sent after the link is accessed or revoked And all reminders are deduplicated within a 10-minute window and logged with delivery outcomes
One-Tap Reissue for Expired or Consumed Links
Given an OTP link is expired or has been consumed once When the patient taps "Reissue" in their SmileCue thread or staff selects "Reissue SecureShare" in inbox/scheduler Then the prior token is revoked, a new token is generated, and delivery occurs via the healthiest verified channel within 10 seconds And the reissue action completes in no more than 2 taps/clicks from the entry point And no more than 3 reissues are permitted per 24 hours per item/caregiver; exceeding the limit shows an error and suggests alternate contact collection And the audit log links the new token to the original request and records the initiator
Channel Separation and Privacy Guardrails
Given SecureShare is initiated Then the caregiver receives the OTP link only on their verified channel(s), and the patient never receives the link URL or token And patient-facing updates show status only (requested, sent, delivered, accessed, expired) without the link And cross-channel testing confirms zero occurrences where patient messages, notifications, or exports include the caregiver link or token And distinct routing identifiers and templates are used for patient vs. caregiver communications to prevent leakage
Staff-Side Shortcuts in Inbox and Scheduler
Given a staff user is viewing a patient message thread in Inbox or an appointment in Scheduler When the user selects the "SecureShare" shortcut Then the system pre-populates patient and item context and opens the composer in-place without page navigation And the user can request caregiver info or issue a link (if a verified caregiver exists) in ≤3 clicks And the action is permission-gated to authorized roles and writes an audit entry with user ID, timestamp, and item reference And shortcut usage and success/failure metrics are captured for reliability reporting

Adaptive Auth

Tunes verification to risk: recognized devices get streamlined codes; unusual signals (new device, location shift, multiple failures) trigger step-up options like voice callback or secondary checks. Patients breeze through when safe, while high-risk cases get extra protection—balancing security with speed.

Requirements

Real-time Risk Scoring Engine
"As a patient, I want SmileCue to recognize when my login looks normal so that I can confirm my appointment quickly without extra steps."
Description

Implements a low-latency risk assessment service that evaluates each verification attempt using device fingerprint signals, IP reputation, geo-velocity, time-of-day, prior confirmation history, and recent failure patterns. Produces a normalized score and tier (e.g., low/medium/high) within 150 ms to drive Adaptive Auth decisions without delaying patient flows. Integrates with SmileCue’s reminder and scheduling workflows by gating sensitive actions (confirm, reschedule, portal access) behind risk-appropriate verification. Supports privacy-by-design: stores only pseudonymous identifiers, minimizes PHI in logs, and honors retention policies to remain HIPAA compliant. Provides extensible adapters for new signals and safe defaults when signals are missing. Includes circuit breakers and graceful degradation so verification remains available during partial outages.

Acceptance Criteria
P95 Latency Under Load
Given the risk-scoring API receives >=200 requests/second with realistic upstream signal latencies When measuring end-to-end time from request receipt to response sent over a 15-minute window Then the 95th percentile latency is <=150 ms And the 99th percentile latency is <=250 ms And the 5xx error rate is <0.1%
Deterministic Normalized Score and Tier Mapping
Given a fixed set of input signals and a configured policy (Low: score < 40; Medium: 40–69; High: >= 70) with normalization range 0–100 When the same request payload is scored 1000 times across two independent instances Then the normalized score variance is <= ±0.5 points And boundary values map correctly (39 => Low, 40 => Medium, 69 => Medium, 70 => High) And the response includes fields: score (0–100), tier (low|medium|high), reasons[] (non-empty)
Safe Defaults for Missing Signals
Given one or more signals are unavailable or exceed their timeout (e.g., IP reputation, device fingerprint, geo) When a verification attempt is scored Then the engine completes within SLA using neutral defaults for each missing signal And if both device fingerprint and IP reputation are missing, the returned tier is at least Medium And the response reasons[] include which signals were defaulted And no 5xx errors are emitted due to missing signals
Gating Sensitive Actions by Risk Tier
Given a patient attempts to Confirm, Reschedule, or Access Portal and a risk tier is returned When the tier is Low Then the action is allowed with streamlined verification (single-channel code) before commit When the tier is Medium Then a step-up verification via an alternate channel is required before commit When the tier is High Then a step-up via voice callback or equivalent secondary check is required before commit And in all cases the action is not committed until verification succeeds And audit logs record action, risk tier, verification method (pseudonymous), and outcome without PHI
Privacy-by-Design: Pseudonymous IDs, Minimal Logs, Retention
Given a risk event is processed When data is persisted or logged Then only pseudonymous identifiers (e.g., patient_pid, device_pid), timestamps, and signal metrics are stored And no direct identifiers (name, phone, email, appointment details) appear in storage or logs And tokens/codes are redacted in all logs And records older than the configured retention TTL (default 30 days) are automatically deleted daily And access to risk data is role-restricted and audited
Circuit Breakers and Graceful Degradation During Partial Outages
Given a dependent signal provider exceeds configured failure/timeout thresholds within 1 minute When the circuit breaker opens Then the engine bypasses the dependency, applies neutral defaults or cached values, and responds within SLA And an operational alert is emitted with dependency name and breaker status And when health checks pass for the configured consecutive interval, the breaker closes and normal scoring resumes without redeploy
Extensible Signal Adapter Interface and Safe Rollout
Given a new signal adapter implementing the defined interface is deployed behind a feature flag When the flag is enabled for 10% of traffic Then the adapter’s weighted contribution is included in scoring without restarting the core service And disabling the flag removes its contribution immediately And if the adapter raises errors, it is isolated and defaulted without impacting SLA or overall error rates
Trusted Device Recognition & Management
"As a returning patient, I want my usual phone to be recognized so that I can verify with fewer steps and get on with my day."
Description

Establishes secure device recognition to streamline repeat verifications on known hardware while enabling revocation when risk changes. Binds a trusted device using cryptographically strong identifiers (rotating device token + signed server nonce) and stores a pseudonymous handle, never raw device data, to maintain HIPAA compliance. Trust duration, renewal, and inactivity timeout are configurable per practice (e.g., 90 days) via admin policy. Detects material changes (browser reset, OS upgrade, SIM swap indicators) and gracefully downgrades trust to require step-up. Provides patient-initiated and admin-initiated device revocation, with audit trails and alerts on mass revocations. Seamlessly plugs into existing SMS/email reminder links and the patient web flow to auto-apply streamlined challenges for recognized devices.

Acceptance Criteria
Bind Trusted Device with Rotating Token
Given an untrusted device completes strong verification and the user consents to "Trust this device" When the server creates a device binding Then the binding includes a signed server nonce and a rotating device token And the client stores the token in secure, http-only storage (or platform-secure storage on mobile) And the server persists only a pseudonymous device handle plus trust metadata (created_at, trust_expires_at, last_seen_at, policy_id) And no raw device identifiers (e.g., IMEI, MAC, phone number, IP, GPS) are persisted And replay of the same nonce for binding is rejected with HTTP 409 and no handle is created And the response returns trust_expires_at computed from the active practice policy
Streamlined Verification on Recognized Device via Reminder Link
Given a device with a valid trusted handle and unexpired trust follows an SMS or email reminder link When the patient session is established Then the patient is auto-recognized without additional code entry or step-up challenge And the target appointment page loads with authenticated context And server processing time to render the confirmation screen is ≤2 seconds at P95 And an audit entry "trusted_device_streamlined_auth" is recorded with the pseudonymous handle and policy_id
Trust Expiration and Inactivity Timeout Enforcement
Given the practice policy sets trust_duration=90 days and inactivity_timeout=30 days When last_seen_at exceeds 30 days without activity Then the device trust state transitions to "suspended" and step-up verification is required on next access And upon successful step-up, trust is renewed and last_seen_at is updated When current time exceeds trust_expires_at (90 days) Then the trusted handle is invalid and rebinding is required after strong verification And changes to policy values take effect for new sessions within 5 minutes of update
Risk Signal Detection Triggers Step-Up
Given a device previously recognized as trusted When risk signals are detected such as device fingerprint mismatch, geolocation shift >200 km within 24 hours, or ≥3 failed OTP attempts in 10 minutes Then the device trust is downgraded to "suspended" and step-up options (SMS OTP, voice callback, secondary checks) are presented And streamlined challenges are not offered in this session And on successful step-up, trust is reactivated and risk_reason is recorded in audit And on failed step-up, access is denied and lockout rules are enforced per policy
Material Change Downgrades Trust
Given a device with active trust When browser storage is reset, or the OS major version changes, or a SIM swap indicator is received from the carrier Then the device is treated as untrusted without revealing device details And the user is prompted to complete step-up with a neutral, non-PHI message explaining re-verification And no PHI or raw device identifiers are displayed or logged beyond the pseudonymous handle And an audit entry "trusted_device_material_change" is recorded with timestamp and policy_id
Patient-Initiated Device Revocation
Given a patient is authenticated and navigates to Security > Trusted Devices When the patient selects a device and confirms revocation Then the server deletes the trusted device handle and invalidates any associated sessions on that device within 5 minutes And subsequent access from that device requires full verification and rebinding And an audit entry is recorded with actor=patient, action=device_revoke, pseudonymous handle, timestamp And a confirmation notification is sent to the patient's preferred channel
Admin-Initiated Mass Revocation with Alerting
Given an admin with Org Security permission selects a cohort (patient, location, or all) and initiates revocation affecting ≥10 devices When the action is confirmed Then all selected trusted handles are invalidated within 5 minutes and cannot be used for streamlined auth And per-handle and summary audit entries are created (counts by patient and total) And an alert is sent to configured security contacts within 1 minute including counts, initiator, and scope And rate limiting prevents more than 3 mass revocation actions per admin per hour
Adaptive Challenge Orchestrator
"As an office manager, I want verification to adapt to risk in real time so that low-risk patients move fast while high-risk cases get extra protection."
Description

Delivers a policy-driven engine that maps risk tiers and context (device trust, channel health, geo, practice rules) to the next best verification step in real time. Supports step-up options including SMS OTP, email magic link, voice callback with DTMF confirmation, and secondary checks (e.g., birthdate confirmation) while enforcing HIPAA minimum-necessary data exposure. Enables per-practice policy templates with guardrails, A/B tests for friction tuning, and automated fallbacks when a channel fails or deliverability is degraded. Operates as an idempotent, stateful workflow with resumability to handle user drops and retries across channels. Integrates with SmileCue’s scheduling API so downstream actions (confirm/reschedule/cancel) are unlocked only after successful completion of the orchestrated flow. Provides observability hooks and feature flags for safe rollout.

Acceptance Criteria
Real-Time Risk-Tier Mapping Selects Next Best Step
Given an auth request with context (device_trust_score, device_id, geo_ip, channel_health, practice_rules) and correlation_id X When the orchestrator evaluates the request Then it assigns a risk_tier (Low|Medium|High) deterministically for correlation_id X and returns the next best step per active policy within 200 ms P95 and 500 ms P99. And the returned step type is one of [sms_otp, email_magic_link, voice_callback_dtmf, secondary_check_birthdate] and includes TTL, max_attempts, and localized copy keys. And the decision log includes trace_id, policy_version, risk_signals_used, and excludes PHI and full identifiers.
Step-Up Challenge Triggered by Anomalous Signals (Voice Callback with DTMF)
Given any of: unrecognized device, geo_distance_change >= 500 km in last 24h, or >= 3 consecutive failed OTP attempts in 15 min When the user initiates verification Then the orchestrator selects voice_callback_dtmf as the step-up method and initiates the call within 5 seconds P95. And the TTS message masks identifiers (phone last4 only) and requests a 6-digit DTMF code matching the issued token. Then successful entry within 3 attempts completes verification; after 5 total failed attempts the session is locked for 10 minutes and emits audit event AUTH_LOCKOUT. And all events contain no PHI; store only hashed patient_id and last4 phone.
Automated Channel Fallback on Delivery Degradation
Given sms_otp is selected as the primary step When delivery callback reports undeliverable, carrier_block, or no user interaction within 90 seconds Then the orchestrator marks SMS as degraded for this session and switches to email_magic_link within 2 seconds of the signal if a verified email exists. When email is unavailable or fails within 120 seconds Then the orchestrator prompts secondary_check_birthdate in-channel. Then at most one active challenge is valid at any time; previously issued tokens are invalidated; all fallbacks are idempotent for correlation_id X. And metrics record fallback_reason and step latencies; P95 time from failure signal to next-step dispatch <= 2 seconds.
HIPAA Minimum-Necessary Data Enforcement Across Flows and Logs
Rule: Outbound content must not include diagnosis, treatment details, or full PHI; only practice name, appointment date/time window, and masked contact identifiers (email masked, phone last4) are allowed. Rule: Logs and decision events must exclude full DOB; store DOB hash comparison result only (true/false) and token metadata; no raw OTP values. Test: Automated static scans and integration tests across 1,000 sampled events show 0 PHI violations; redaction middleware is required in all egress paths. Test: Any attempt to include disallowed fields is blocked with error code E_MIN_NECESSARY and is captured in audit with severity WARN.
Stateful, Idempotent Resumability Across Drops and Retries
Given a user abandons after receiving a step When they return via any channel within the session TTL (24 hours) Then the orchestrator restores the last incomplete step with the same correlation_id and tokens (or reissues equivalent) within 150 ms P95. When duplicate start requests are received with the same correlation_id Then the orchestrator returns the same current step (HTTP 200, code IDP_RESUME) without creating duplicates. Then once a step completes, state transitions are atomic and immutable; race conditions with concurrent attempts resolve via optimistic locking and produce at-most-once completion.
Per-Practice Policy Templates with Guardrails and A/B Friction Tuning
Given a practice admin applies a policy template When values are saved Then guardrails enforce: otp_length >= 6, max_attempts <= 5, fallback_enabled = true for High risk, and voice_callback required for High risk geoshift. Given an experiment is defined with variants A and B and split 50/50 When rollout begins Then assignment is deterministic by patient_hash and respects exposure cap of 5,000 sessions/variant with auto-stop when P95 time_to_verify exceeds 120 seconds by >20% vs control. Then metrics captured per variant: completion_rate, median_time_to_verify, step_up_rate, fallback_rate; downloadable within 1 hour lag; changes are gated by feature flag FF_ADAPTIVE_AUTH_AB.
Scheduling API Gatekeeping on Verification Completion
Given a patient attempts to confirm, reschedule, or cancel via SmileCue APIs When their orchestrated verification flow is incomplete Then the API responds 403 AUTH_REQUIRED with link to resume verification; no scheduling mutation occurs. When the verification flow completes successfully Then the API allows the action within 1 second P95, associates the action with the verification session_id, and emits AUDIT_SCHEDULING_UNLOCK. Negative test: Attempts to bypass verification (missing/invalid session_id) are rejected with 403 and logged; rate-limited at 10/minute/IP.
Multi-Channel OTP Delivery & Lifecycle Controls
"As a patient, I want to receive my verification code through my preferred channel so that I can complete authentication even if one channel is unavailable."
Description

Implements reliable, compliant OTP delivery over SMS and email with strict lifecycle management to prevent abuse. Enforces single-use codes, short TTLs (e.g., 5 minutes), resend limits, per-identity and per-device rate limits, and lockouts after repeated failures. Provides channel redundancy and auto-fallback (e.g., switch from SMS to email on carrier failure) while preserving the verification session state. Uses HIPAA-safe templates that avoid PHI, supports practice branding (sender ID, email domain), and adheres to CTIA/TCPA guidelines with opt-out handling. Monitors deliverability and latencies with provider health checks and adaptive routing. Exposes server-side and client-side SDKs to integrate OTP requests seamlessly into SmileCue’s reminder links and patient portal.

Acceptance Criteria
Single-Use OTP Enforcement
- Given an OTP is generated for a verification session, When the OTP is successfully verified once, Then any subsequent attempt to reuse the same OTP (via any channel) is rejected with error code OTP_REUSED and HTTP 400, and an audit event is recorded. - Given multiple OTPs have been generated for the same session, When a newer OTP is issued, Then all prior OTPs for that session are immediately invalidated and cannot be verified. - Given an invalidated OTP, When a verify request is made with that code, Then the attempt counts toward failure counters and returns OTP_INVALIDATED without issuing a new code.
OTP TTL & Resend Behavior
- Given an OTP is issued, When 5 minutes elapse from server-side issuance time, Then the OTP expires and any verify attempt returns OTP_EXPIRED (HTTP 400) with no more than 15s clock drift tolerance. - Given a resend is requested, When the prior OTP is still active, Then a new OTP is generated, the prior OTP is invalidated, and the response includes the new TTL and a resendAfter timestamp. - Given session resend limits, When more than 3 resends are requested within 15 minutes for the same identity-session, Then the request is rejected with RESEND_LIMIT (HTTP 429) and includes retryAfter in seconds. - Given rapid repeat requests, When a resend is requested within 30 seconds of the last send, Then the request is rejected with RESEND_TOO_SOON and includes nextEligibleAt.
Abuse Prevention: Per-Identity/Device Rate Limits and Lockouts
- Given a patient identity within a practice, When more than 5 OTP send requests occur within a rolling 15-minute window, Then subsequent send requests are rejected with RATE_LIMIT_IDENTITY (HTTP 429) until the window resets. - Given a device fingerprint, When more than 3 OTP send requests occur within a rolling 15-minute window, Then subsequent send requests are rejected with RATE_LIMIT_DEVICE (HTTP 429). - Given a destination (phone/email), When more than 10 OTP sends occur within a rolling 24-hour window, Then further sends are blocked with RATE_LIMIT_DESTINATION (HTTP 429) for the remainder of the 24-hour period. - Given verification attempts, When 5 incorrect code submissions occur within 15 minutes for the same identity-session, Then verification is locked for 15 minutes and responses return LOCKED_OUT; the next allowed action prompts step-up (e.g., voice callback). - Given a lockout is active, Then additional verify attempts do not increment failure counters and an audit log entry is created including identity, device, IP, and lockout expiry.
Channel Redundancy: Auto-Fallback with Session Preservation
- Given an OTP send via SMS, When the provider returns an explicit failure or no delivery receipt within 30 seconds, Then the system automatically sends the same OTP via email within 10 seconds without requiring user restart. - Given auto-fallback triggers, Then the sessionId remains unchanged, the OTP code remains the same, and the verify endpoint accepts the code regardless of original channel. - Given multi-channel delivery, Then the user receives at most one message per channel per issuance; duplicates are prevented and each send is logged with channel, provider, timestamps, and fallback reason. - Given both channels fail, Then the flow offers a step-up option (e.g., voice callback) and marks the session status as PENDING_DELIVERY with a retry option.
Compliance & Branding: HIPAA-safe Templates and CTIA/TCPA Opt-Out
- Given OTP communications, Then SMS and email templates contain no PHI (no patient name, appointment details, diagnosis, or identifiers) and include only practice display name, purpose, OTP code, expiry, and support/opt-out text. - Given SMS channel, Then outbound texts include STOP/HELP language, honor STOP/UNSTOP within 1 minute, and suppress future sends to opted-out numbers across transactional flows until consent is re-established. - Given email channel, Then messages are sent from a practice-branded domain with valid SPF/DKIM/DMARC alignment; headers and footers reflect configured practice branding (name, logo) without PHI content. - Given consent requirements, Then TCPA/CTIA consent records (phone, source, timestamp, method) are stored and retrievable for audit; attempts to send without consent are blocked with CONSENT_REQUIRED.
Deliverability Monitoring: Provider Health Checks and Adaptive Routing
- Given ongoing sends, When a provider’s 5-minute failure rate exceeds 2% or p95 delivery latency exceeds 8 seconds, Then routing shifts new traffic to the next-best provider within 60 seconds. - Given provider recovery, When metrics remain below thresholds for 15 consecutive minutes, Then traffic is gradually rebalanced to the primary (no more than 20% increase per minute) to avoid flapping. - Given health checks, Then the system records send success, delivery receipts, error codes, and latency per provider and region every 30 seconds and exposes these metrics to the ops dashboard and logs. - Given a routing decision, Then the selected provider and decision rationale are attached to each send event for traceability.
SDK Integration in Reminder Links and Patient Portal
- Given the server SDK, Then otp.createSession(identity, channels[]) returns sessionId, TTL (seconds), resendAfter, masked destinations, and channel order; otp.send and otp.verify endpoints are available with typed error codes (EXPIRED, REUSED, LOCKED_OUT, RATE_LIMIT, OPTED_OUT). - Given the client SDK is initialized in a reminder link, When a user opens the link, Then the SDK resumes or creates a session, requests an OTP on consent, and preserves session across refresh and channel fallback without losing attempt counts. - Given code entry, When verify(sessionId, code) is called with a valid code, Then VERIFIED is returned with server processing time under 300 ms p95; invalid codes return explicit errors without revealing which channel failed. - Given SDK telemetry, Then success/failure events include channel, provider, latency, and error code, and are accessible for analytics within 5 minutes of occurrence.
Voice Callback Step-Up Verification
"As a patient on a poor data connection, I want a verification call option so that I can still authenticate securely and confirm my appointment."
Description

Adds an automated voice callback option for high-risk or failed OTP scenarios, enabling patients to verify via TTS instructions and DTMF input without exposing PHI. Supports branded caller ID where available, localized prompts, retry/backoff policies, and quiet-hour windows configurable per practice. Validates call answer events, handles voicemail detection, and ensures the verification result is posted back to the orchestrator in real time. Encrypts call metadata at rest, redacts sensitive fields in logs, and records audit events for HIPAA compliance. Integrates with existing SmileCue scheduling flows to unblock confirmations when SMS/email are unreliable or the user lacks data coverage. Provides operational dashboards for call success rates and reason codes (no answer, voicemail, DTMF mismatch).

Acceptance Criteria
Trigger Voice Callback on High-Risk or Failed OTP
- Given an authentication or appointment confirmation is flagged high-risk OR the user has 2 consecutive OTP failures, When step-up is required, Then initiate an automated voice callback to the patient’s primary phone on file. - Given SMS/email delivery is unreliable or data coverage is absent, When the orchestrator requests step-up, Then voice callback is selected as the channel. - Given a callback is initiated, When it is queued, Then the orchestrator receives a callback_started event with a correlation ID and practice ID.
Localized TTS Prompts and DTMF Verification Success
- Given the patient’s preferred locale is available, When the call connects, Then TTS prompts play in that locale (at minimum en-US and es-US) without speaking any PHI. - Given branded caller ID is provisioned and carrier supports it, When the call is placed, Then the recipient sees the practice brand; otherwise present the standard caller ID without error. - Given a verification code is required, When the patient enters the correct DTMF within 3 attempts and 30 seconds per attempt, Then the verification status becomes Verified and an answered event is recorded. - Given DTMF input includes non-digits or partial digits, When entered, Then the input is rejected and the prompt repeats without echoing digits. - Given the maximum attempts are exceeded without a correct code, When the call ends, Then the verification status becomes Failed with reason DTMF_mismatch.
Voicemail Detection and PHI-Safe Handling
- Given the call is answered by a machine, When a voicemail beep or machine greeting is detected OR no DTMF is received within 10 seconds of the prompt, Then classify the attempt as voicemail and do not leave any message containing PHI or codes. - Given voicemail is detected, When the call ends, Then record reason code voicemail and schedule a retry per policy. - Given the system encounters an interactive voicemail requesting keypad input, When prompts are detected, Then SmileCue does not transmit any DTMF and ends the call gracefully.
Retry and Backoff Policy Enforcement
- Given the default retry policy is 3 attempts with 1m, 5m, and 15m backoff unless overridden per practice, When a call fails due to no_answer, busy, or voicemail, Then the next attempt is scheduled per policy and canceled on success or window expiry. - Given a practice updates its retry/backoff configuration, When future attempts are scheduled, Then the new configuration is applied without affecting already-dispatched calls. - Given the attempt limit is reached or the verification window expires, When no successful verification occurred, Then post a final Failed result with reason max_attempts or expired and stop further callbacks.
Quiet Hours Compliance per Practice
- Given a quiet-hour window is configured in the practice’s local timezone, When any callback would occur within that window, Then the system defers the call to the earliest allowed time. - Given a retry is due during quiet hours, When the window begins, Then the attempt is rescheduled to the next allowed slot while preserving the backoff sequence. - Given quiet hours are disabled for a practice, When callbacks are scheduled, Then no quiet-hour deferral is applied.
Real-Time Result Posting to Orchestrator, Security, and Auditing
- Given a verification outcome occurs (Verified, Failed, Canceled), When the call ends or success is detected, Then the orchestrator receives the final result within 5 seconds including correlation ID, pseudonymous patient ID, reason code, and attempt count. - Given call metadata is persisted, When data is stored at rest, Then it is encrypted using platform-managed AES-256 (or equivalent) and access is restricted to authorized services. - Given application logs are emitted, When sensitive fields (phone numbers, DTMF digits, correlation tokens) are logged, Then values are redacted or tokenized. - Given security-relevant actions occur, When recorded, Then immutable audit events are written with timestamp, actor/service ID, action, outcome, and request ID.
Operational Dashboard Metrics and Reason Codes
- Given callbacks are executed, When metrics are aggregated, Then the dashboard displays per-practice and global success rate, answer rate, average time-to-verify, and counts by reason code (no_answer, voicemail, busy, DTMF_mismatch, max_attempts, expired). - Given a filter (date range, practice, campaign/flow) is applied, When the dashboard renders, Then metrics and tables update within 5 seconds to reflect the filter. - Given a call attempt completes, When telemetry is ingested, Then the dashboard reflects the event within 5 minutes. - Given a user drills into a specific call, When details are shown, Then they include timestamp, attempt number, reason code, and duration with no PHI or DTMF digits displayed.
Admin Policy Controls & Risk Analytics
"As an office manager, I want to adjust authentication policies and monitor results so that I can balance security with patient experience and reduce no-shows."
Description

Delivers an admin console for practice owners/managers to tune Adaptive Auth policies and review outcomes without engineering support. Allows configuration of risk thresholds, trusted device durations, allowed channels, resend limits, quiet hours, and secondary checks, all with sensible defaults and guardrails. Provides real-time and historical analytics: verification success rates, median time-to-confirm, step-up rate by risk tier, channel deliverability, and no-show impact correlation. Includes exportable, PHI-minimized audit logs and role-based access controls to satisfy HIPAA and internal compliance reviews. Integrates with SmileCue’s existing admin portal and permissions model for a consistent experience. Supports versioned policy changes with staged rollout and automatic rollback on regressions.

Acceptance Criteria
Policy Threshold Configuration with Guardrails
Given an admin with Policy Manager permission, when they open Adaptive Auth > Risk Settings, then default Low/Medium/High thresholds are pre-populated (Low ≤30, Medium 31–70, High ≥71) and are editable within 0–100. Given overlapping or invalid threshold ranges, when the admin attempts to save, then the UI blocks save with inline error messaging and no changes persist. Given valid thresholds, when the admin saves, then the policy version increments by 1, a timestamped entry records admin ID, diff, and reason (required field ≥10 chars), and changes propagate to enforcement within 60 seconds. Given a read-only user, when viewing Risk Settings, then controls are disabled and the Save action is unavailable.
Channels, Resend Limits, and Quiet Hours Enforcement
Given an admin with Policy Manager permission, when configuring allowed channels, then they can enable/disable SMS, Email, and Voice individually; defaults are SMS and Email enabled, and disabled channels are not used at runtime. Given resend limit N (1–3 per 24h per patient) and cooldown C (5–60 minutes) configured, when a patient requests additional codes beyond N within 24 hours, then the system denies the send, returns a user-friendly message, and records the event in the audit log. Given quiet hours defined (e.g., 20:00–08:00 in the practice timezone), when a message is scheduled within quiet hours, then it is deferred to the next permitted window, and the updated scheduled time is visible in the outbound queue view. Given conflicting settings (e.g., all channels disabled), when the admin attempts to save, then the UI blocks the save with a clear error requiring at least one channel enabled.
Device Trust & Step-Up Configuration
Given trusted device duration D (1–90 days, default 30) configured, when a patient verifies from a recognized device within D, then streamlined verification (single-step code) is used. Given a new device, location anomaly, or ≥3 failures within 10 minutes, when verification is attempted, then the configured step-up options (voice callback and/or secondary check) are enforced. Given a step-up option is disabled in policy, when its trigger condition occurs, then that option is not presented and an enabled alternative is used; if none are enabled, the system falls back to standard multi-factor and logs a policy misconfiguration warning. Given device recognition is toggled off, when saving the change, then a confirmation modal warns about increased friction and requires explicit confirmation before persisting.
Risk Analytics: Real-time & Historical Metrics
Given Analytics > Adaptive Auth is opened, when a date range is selected, then the dashboard displays: verification success rate, median time-to-confirm, step-up rate by risk tier, channel deliverability, and no-show impact correlation for the selection. Given real-time view is selected, when traffic exists, then metrics refresh at most every 60 seconds and reflect the last 15 minutes. Given historical view is selected for up to 90 days, when applied, then metrics render within 5 seconds for ≤100k events and can be exported as CSV with aggregated, non-PHI data. Given two date ranges are selected for comparison, when applied, then percentage deltas are shown per metric and the comparison state is reflected in the export.
PHI-Minimized Audit Log Export
Given a user with Compliance Auditor or higher role, when exporting audit logs for a date range, then the export contains event type, timestamp (UTC), actor role, practice ID, policy version, change diff, enforcement outcome summary, and pseudonymized patient/device IDs, and excludes names, phone numbers, emails, birth dates, and free-text PHI. Given an export is requested, when generation completes, then the file is available in CSV and JSON formats with a SHA-256 checksum and auto-expires after 24 hours. Given a policy change is saved, when logged, then the entry includes before/after values, admin ID, reason, and originating IP, is append-only, and is retrievable via the audit UI and export.
RBAC & Admin Portal Integration
Given existing SmileCue roles and permissions, when accessing Adaptive Auth settings, then only Owners/Managers with Policy Manager permission can edit, Auditors can view and export logs, and Staff have no access; unauthorized requests return 403 and are audited. Given portal navigation, when users access Adaptive Auth, then the section appears under Security and inherits the existing admin portal theming and layout components for a consistent experience. Given API calls to Adaptive Auth endpoints without required scopes, when attempted, then the system denies the call with 403 and no state changes occur.
Versioned Policy Changes with Staged Rollout and Auto-Rollback
Given a new policy version V is created, when staged, then it can be rolled out to 5%, 25%, 50%, and 100% of verifications with a scheduled start time and the selected cohorts are visibly indicated. Given a rollout is in progress, when verification success rate drops by >5% absolute versus the previous 7-day baseline or median time-to-confirm increases by >30% for 15 consecutive minutes with ≥200 attempts, then an automatic rollback to the prior version occurs and admins are notified via portal banner and email. Given a manual rollback is initiated, when confirmed, then traffic reverts within 60 seconds and the analytics timeline is annotated with the rollback event. Given a rollout completes to 100% without breach, when finalized, then version V becomes default and the previous version is archived for 180 days with full audit history.

Flex Expiry

Sets smart expiration windows by content sensitivity (e.g., X-rays vs. instructions), shows a clear countdown, and allows self-serve resend/refresh with cooldowns. Staff can grant one-click extensions from the appointment view, preventing timeouts that derail completion and drive inbound calls.

Requirements

Policy-based Expiry by Content Sensitivity
"As an office manager, I want expiration windows to adjust by content sensitivity so that sensitive documents expire quickly while instructions remain accessible long enough to ensure completion."
Description

Introduce a configurable expiry policy engine that sets default time-to-live (TTL) values per content category (e.g., X-rays, treatment plans, pre-/post-op instructions, payment links, intake forms) with template-level and message-instance overrides. Policies apply across SMS, email, and voice workflows, embedding expiry metadata into generated tokens/links. The system resolves the applicable TTL at send time, stores per-artifact expiry timestamps, and enforces soft/hard expiration behavior (e.g., grace period after first access) aligned with HIPAA constraints. Integration points include message templating, adaptive branching (trigger recovery flows on expiry), and appointment records. Timezone-aware calculation ensures countdowns and absolute “expires at” times are accurate to the patient’s locale. Expected outcomes are fewer timeouts, improved completion rates, and tighter control of PHI exposure windows.

Acceptance Criteria
TTL Resolution and Override Precedence at Send Time
Given a content category default TTL of 24h, a template-level TTL override of 12h, and a message-instance TTL override of 6h When the message is queued for send Then the effective TTL is 6h And expires_at equals send_time + 6h (to the second) And effective_ttl_seconds and expires_at are persisted on the artifact record And subsequent changes to category/template policies do not change the stored expires_at for that artifact Given a content category default TTL of 24h and a template-level TTL override of 12h, with no message-instance override When the message is queued for send Then the effective TTL is 12h And expires_at equals send_time + 12h Given a content category default TTL of 24h and no overrides When the message is queued for send Then the effective TTL is 24h And expires_at equals send_time + 24h
Expiry Metadata Embedded in Tokens/Links Across Channels
Given a generated patient-facing SMS and email link When inspecting the URL Then it contains an opaque token with no PHI or TTL values in clear text And the token resolves server-side to an artifact that includes expires_at and policy_version And the server enforces expiry on every access attempt Given a voice workflow that uses a spoken/DTMF code to retrieve content When the code is entered Then the lookup enforces the same expires_at as the underlying artifact And the IVR informs the patient that the item has expired if expires_at is in the past Given a request using a tampered or forged token/code When the endpoint is called Then access is denied (HTTP 401/403) And the attempt is audit-logged with reason "invalid_token" without exposing PHI
Per-Artifact Expiry Timestamps Stored and Queryable from Appointment
Given an artifact is created at send time When the record is persisted Then fields expires_at (UTC), effective_ttl_seconds, first_access_at (nullable), hard_expires_at (if different), and policy_version are stored And these fields are retrievable via internal API and visible on the related appointment record And the UI countdown uses expires_at and the patient timezone to compute remaining time to the second Given the artifact is canceled or superseded before expiry When the appointment record is queried Then the prior artifact is marked inactive and excluded from countdowns, but its expiry fields remain in audit history
Soft/Hard Expiration with Grace Period After First Access
Given hard_ttl = 24h and grace_period = 2h for the category And send_time = T0 And hard_expires_at = T0 + 24h When the patient first accesses at T1 = T0 + 10h Then soft_window_expires_at = min(hard_expires_at, T1 + 2h) = T0 + 12h And access between T1 and T0 + 12h is allowed And access after T0 + 12h is denied with an "expired" response Given the first access occurs after hard_expires_at When the link is opened at T1 = T0 + 26h Then access is denied immediately (no grace applies) Given multiple accesses within the soft window When the link is opened again Then the grace window does not extend beyond the initial soft_window_expires_at And all accesses are audit-logged with allow/deny outcome
HIPAA-Constrained Exposure Windows and Safe Expiry Handling
Given a category policy with min_ttl = 1h and max_ttl = 30d When a template or message-instance sets TTL outside these bounds Then the request is rejected with a validation error and logged with reason "ttl_out_of_bounds" Given a patient opens an expired link When the endpoint responds Then the status is 410 Gone (or channel-appropriate equivalent) And the content contains no PHI And the message copy uses generic wording (no procedure names or identifiers) Given expiry occurs When audit logs are queried Then an event is present with artifact_id, category, expires_at, channel, and outcome = "expired" And no PHI fields are stored in logs beyond identifiers required for traceability
Adaptive Branching Triggers on Expiry with Recovery Flows
Given an artifact reaches expires_at When the expiry is processed Then an event artifact.expired is emitted once (idempotent) within 60 seconds And the event payload includes artifact_id, appointment_id, patient_id, category, channel, and reason = "expired" Given a workflow with an on_expiry branch configured When artifact.expired is received Then the on_expiry branch executes And if the artifact is already completed (status = completed), the branch does not run And execution is recorded with correlation to the source artifact Given multiple channels for the same artifact When expiry occurs Then only one artifact.expired event is emitted for that artifact
Timezone-Aware Countdown and Expires-At Accuracy
Given a patient with timezone America/Denver and practice timezone America/New_York When a message is sent at 2025-03-08 22:00 America/New_York with TTL = 24h Then expires_at (UTC) equals send_time_utc + 24h And the patient-facing UI shows "Expires Mar 09, 2025 20:00" in America/Denver local time, accounting for DST changes And the countdown matches the difference between now() in America/Denver and expires_at Given the patient timezone is unknown When the message is sent Then the system falls back to the practice timezone for display And the chosen timezone source is recorded on the artifact as tz_source = "practice_fallback"
Patient-facing Countdown and Expiry Page
"As a patient, I want to see a clear countdown until my link expires so that I can complete tasks in time and understand what happens if I don't."
Description

Provide a responsive, accessible landing experience that displays a real-time countdown to expiry and an absolute expiry timestamp localized to the patient’s timezone. When content is expired, present a dedicated page that explains the status, removes access to sensitive content, and offers a clear path to request a refreshed link if enabled by policy. Emails render a static expiry timestamp; SMS directs to a landing page with countdown; voice reminders state the expiry window in natural language. Handle clock skew and offline scenarios gracefully by prioritizing server-side expiry checks and fallbacks. This enhances patient clarity, reduces confusion-driven calls, and increases on-time completions.

Acceptance Criteria
Server-validated real-time countdown on landing page
Given a patient opens a valid content link, When the landing page loads, Then it fetches the server expiry timestamp and starts a visible countdown that updates at least once per second and reaches zero exactly at the server-provided expiry time. Given a discrepancy between client-local time and server expiry, When the server response arrives, Then the countdown snaps to match the server value within 500 ms and server time takes precedence for access decisions. Given the countdown reaches zero, When the page time hits or passes the server expiry, Then access to sensitive content is blocked immediately and the UI transitions to the expired state within 1 second. Given the user is offline on initial load, When the page cannot reach the server, Then show a read-only connecting state with an estimated countdown (if prior server value is cached) and do not display or unlock sensitive content until a successful server validation occurs.
Timezone-localized absolute expiry timestamp
Given a patient landing page with a known patient timezone, When content is still valid, Then display an absolute expiry timestamp localized to that timezone in a clear human-readable format that includes date, time, and timezone/offset. Given the patient timezone is unavailable, When rendering the expiry timestamp, Then default to the device timezone and label the timezone/offset explicitly. Given the expiry crosses a daylight saving change, When displaying the absolute timestamp, Then the time shown reflects the correct local clock time for the patient’s timezone.
Expired page with access removal and guidance
Given content is expired per server validation, When a patient visits or refreshes the link, Then show a dedicated expired page that omits and does not request any sensitive payloads, and return HTTP 403 for any asset/API calls tied to the expired content. Given the expired page is shown, When policy allows self-serve refresh, Then display a prominent Request new link call-to-action; When policy disallows it, Then hide the CTA and show contact guidance. Given the patient navigates back from the expired page, When using browser back or history, Then previously viewed sensitive content remains inaccessible (cleared from client cache) and revalidation with the server is required before any content is shown.
Self-serve refresh request with cooldown and policy gating
Given policy enables self-serve refresh and the patient is within the defined cooldown window, When the patient taps Request new link, Then the request is rejected with an inline message showing the remaining cooldown time and the CTA remains disabled until the cooldown expires. Given policy enables self-serve refresh and the cooldown has elapsed, When the patient taps Request new link, Then a new secure link is issued, prior tokens are invalidated immediately, a success confirmation is shown, and an audit event is recorded with patient identifier, channel, timestamp, and outcome. Given policy disables self-serve refresh, When the patient attempts to request a new link, Then no link is issued and a policy message is displayed without revealing sensitive details.
Staff extension reflected on patient page
Given office staff grant a one-click extension for the patient’s link, When the patient is viewing the landing page, Then the countdown and absolute expiry update to the new server expiry within 5 seconds without requiring a page reload. Given an extension exists, When the patient opens the link after the original expiry but before the new expiry, Then the page loads in a valid state and shows the extended expiry countdown. Given an extension is applied, When the original expiry time passes, Then the page does not enter expired state as long as the new server expiry is in the future.
Channel-specific expiry messaging
Given an email reminder is sent, When the patient reads the email, Then it displays a static absolute expiry timestamp localized to the patient’s timezone and contains no live countdown scripts. Given an SMS reminder is sent, When the patient taps the SMS link, Then it opens the landing page that shows a real-time countdown and the absolute expiry timestamp. Given a voice reminder is delivered, When the message plays, Then it states the expiry window in natural language including the duration until expiry and the local date/time of expiry (e.g., “This link expires in 24 hours, on Tuesday at 3:00 p.m. your time.”).
Accessibility and responsive design for countdown and expiry
Given the landing or expired page is displayed, When tested against WCAG 2.2 AA, Then all interactive elements meet contrast requirements, have visible focus indicators, and non-text content has accessible names. Given assistive technology users, When the countdown updates, Then the countdown region uses aria-live="polite" to announce changes without overwhelming screen readers, and the expiry transition is announced once when it occurs. Given keyboard-only navigation, When tabbing through the page, Then all controls (including Request new link) are reachable in logical order and operable without a pointer. Given common device sizes from 320x568 to 1920x1080, When viewing the page, Then layout remains readable without horizontal scrolling, and the countdown plus primary CTA remain visible without additional scrolling on small mobile devices.
Self-serve Resend/Refresh with Cooldowns
"As a patient, I want to request a refreshed link myself with safeguards so that I can continue without calling the office."
Description

Enable patients to request a refreshed access link from the expiry page or authenticated deep link, with configurable cooldowns (e.g., one refresh per 5 minutes and daily caps) and channel-specific rate limiting. For PHI-bearing content, require lightweight verification (e.g., DOB check or one-time code) before issuing a new signed URL. New links are appended to the existing conversation thread without altering appointment state, and failed/abusive attempts trigger progressive delays and optional staff notifications. All actions are logged for compliance. This lowers inbound call volume while preserving security and system stability.

Acceptance Criteria
Refresh expired non-PHI link from expiry page with cooldown enforced
Given a patient opens an expired link for non-PHI content and the practice cooldown is set to 5 minutes with a daily cap of 3 per channel When the patient requests a refreshed link from the expiry page or authenticated deep link Then the system issues a new signed URL via the original channel and records the event And subsequent requests within 5 minutes are blocked with a clear message indicating remaining wait time And requests that exceed 3 in the same day for that channel are blocked with a “daily limit reached” message and display alternative contact options And no patient verification is required for non-PHI content
Refresh PHI-bearing link requires lightweight verification
Given the content is flagged as PHI-bearing and the practice requires verification (DOB or one-time code) When the patient requests a refreshed link from the expiry page or authenticated deep link Then the patient must complete verification by either entering matching DOB (MM/DD/YYYY) or a valid 6-digit OTP delivered to an on-file channel And OTPs expire in 5 minutes with a maximum of 5 attempts per OTP And if verification succeeds, the system issues a new signed URL and records method and outcome And if verification fails 5 times in a 15-minute window, no link is issued and the patient is informed to try later or contact the office
Channel-specific rate limiting and daily caps
Given the practice has configured per-channel limits (e.g., SMS: 3/day, Email: 2/day) and a 5-minute per-request cooldown When a patient requests SMS refreshes up to the configured daily cap for a single appointment Then all requests at or below the cap are fulfilled if outside the cooldown window And the 1st request within the cooldown window is blocked with remaining time shown And a 4th SMS request that day is blocked while Email requests remain eligible until the Email cap is reached And counters reset at local practice midnight and are tracked per patient per appointment per channel
Append refreshed links to existing conversation without changing appointment state
Given a patient’s refresh request is approved When the system sends the refreshed link via SMS or Email Then the message is appended to the existing conversation thread (same sender/subject/thread identifiers) rather than creating a new thread And the appointment state (e.g., Confirmed/Unconfirmed/Completed) remains unchanged And no automated workflows tied to appointment state are triggered by the refresh event And the refresh event is visible in the conversation and appointment activity history
Progressive delays and optional staff notifications on abusive or failed attempts
Given progressive delay rules are enabled and staff notifications are set to Optional When a patient accumulates 3 failed verifications or blocked requests within 15 minutes Then the next eligible request is delayed by 5 minutes with the delay reason shown to the patient And upon 5 failed/blocked events within 30 minutes, the delay increases to 30 minutes And upon 7 failed/blocked events in 24 hours, requests are locked for 24 hours and, if notifications are enabled, a staff alert is sent with minimal necessary details (patient, appointment, channel, counts, reason, timestamps) And no PHI payload is included in notifications
Compliance audit logging for all refresh-related actions
Given auditing is required for HIPAA compliance When any refresh-related action occurs (request, verification attempt, issuance, block, delay, notification) Then an immutable audit record is written with timestamp (UTC), patient and appointment identifiers, channel, content sensitivity, actor type (patient/system/staff), request origin (IP and user agent), verification method and outcome, link/message identifiers, quota and cooldown decisions, and result And audit records are available to authorized staff in the appointment audit view within 2 seconds and exportable via report/API And audit records follow the organization’s retention policy (minimum 6 years) and are protected from tampering
Staff One-click Extension in Appointment View
"As a hygienist, I want to extend a patient's link expiry from the appointment view with one click so that I can prevent timeouts from derailing check-in or forms completion."
Description

Add an “Extend link expiry” control in the SmileCue appointment view that lets authorized staff extend expiry for selected artifacts (or all related items) by preset increments (e.g., +1h, +24h) or a custom duration within policy-defined ceilings. The action should require minimal clicks, show current and new expiry times, and optionally notify the patient with an updated message. Where supported, the extension updates the token validity without regenerating links; otherwise, a new link is created and inserted into the existing thread. Role-based permissions and comprehensive audit entries are mandatory. This prevents timeouts from disrupting check-in and form completion.

Acceptance Criteria
Extend Single Artifact Within Policy Ceiling
Given an appointment contains a patient-facing artifact with an expiring link and the staff user has the "Extend expiry" permission When the staff user selects the artifact, clicks "Extend link expiry", chooses a preset increment (e.g., +1h), and confirms Then the system updates the artifact's expiry by the selected increment without exceeding the policy-defined ceiling And if the requested increment would exceed the ceiling, the confirm action is blocked and an inline error explains the maximum allowed And if the artifact is already expired, the new expiry is set to now + selected increment (within ceiling) And the action requires no more than 3 clicks from opening the control to confirmation And a success message displays the new absolute expiry with timezone and relative countdown And the update completes within 3 seconds at the 95th percentile
Extend All Related Items in One Action
Given an appointment has multiple eligible artifacts (e.g., forms, X-rays, instructions) with expiring links When the staff user selects "All related items", chooses "+24h", and confirms Then each eligible artifact is extended by +24h unless doing so would breach policy ceilings And ineligible items are skipped and listed with a specific reason (e.g., reached max extensions, hard-expired beyond policy) And a results summary shows count extended, count skipped, and links to details And the operation is non-transactional; one item’s failure does not prevent others And all item updates complete within 5 seconds at the 95th percentile for up to 20 artifacts
Optional Patient Notification With Updated Message
Given the staff user enables the "Notify patient" toggle before confirming the extension When the extension is applied Then the patient is notified via the most recent successful channel for that artifact (SMS/email/voice), respecting opt-outs and HIPAA templates And the notification includes the updated expiry timestamp and the valid link (refreshed if regenerated) And the notification is queued within 5 seconds and delivered within 60 seconds at the 95th percentile for SMS/email (voice within 2 minutes) And the appointment timeline records the notification with channel, timestamp, and delivery status
Role-Based Permissions and Audit Trail
Given a user without the "Extend expiry" permission views an appointment Then the "Extend link expiry" control is hidden or disabled, and any API attempt returns 403 and is audited Given a user with the permission views an appointment with eligible artifacts Then the control is visible and enabled for those artifacts And every extension action creates an immutable audit record capturing user ID, timestamp, artifact ID(s), previous expiry, new expiry, policy checks, channels notified (Y/N), source (UI/API), IP, and correlation ID And audit entries are visible in the appointment timeline and exportable via the audit API
Token Validity Update vs Link Regeneration
Given the artifact type supports token validity updates without URL change When the expiry is extended Then the artifact's URL remains unchanged and the underlying token validity reflects the new expiry And patients using previously received links can access until the new expiry Given the artifact type does not support token validity updates When the expiry is extended Then a new unique link is generated and inserted into the existing patient conversation thread And the prior link is invalidated immediately and redirects to a friendly page instructing the patient to use the latest message And the appointment timeline references the new message with timestamp and channel, preserving the original thread
Expiry Countdown and UI Feedback
Given the staff user initiates an extension When the confirmation panel opens Then it shows current expiry, proposed new expiry, and the delta (e.g., +24h) in the practice’s timezone with a UTC tooltip When the user confirms Then countdown badges in the appointment view update within 2 seconds and reflect the new expiry And if the backend update fails, the UI restores prior countdown and shows an actionable error with retry capability And time values are consistently formatted (locale-aware) across modal, timeline, and badges
Policy Ceilings and Frequency Controls
Given organization policies define a maximum absolute expiry window (e.g., 7 days from first send) and a maximum number of staff extensions per artifact (e.g., 3) When a user selects a preset or enters a custom duration exceeding allowed limits Then the system blocks confirmation, shows the specific limit, and suggests the nearest allowable duration And the custom duration input validates on blur and submit, allowing only hours/minutes within range And server-side enforcement returns 422 with machine-readable error codes; the attempt is audited And the UI displays the remaining extension count for the artifact
Secure Expiring Links and Audit Trail
"As a compliance officer, I want all expiry, access, and extension events audited so that we maintain HIPAA compliance and can investigate issues."
Description

Issue per-patient, per-artifact signed tokens/URLs with absolute and optional sliding expirations, single-use toggles, and immediate revocation on appointment cancellation or policy change. Enforce HTTPS, HSTS, and anti-enumeration protections; avoid embedding PHI in message bodies; and encrypt identifiers at rest and in transit. Maintain a tamper-evident audit trail for token creation, access, expiry, refresh requests, resend events, extensions, actor identity, timestamps, and source channel/IP/device, with export and retention controls to satisfy HIPAA. Provide admin views and APIs to search and report on these events for investigations and compliance audits.

Acceptance Criteria
Signed URL Issuance with Absolute and Sliding Expiration
Given a patient and artifact, when a link is generated with an absolute expiry of 24 hours, then the URL becomes unusable exactly 24 hours after issuance and returns a generic expired response with no PHI. Given a sliding window of 15 minutes with an absolute cap of 24 hours, when the link is accessed at time T and again before current expiry, then the expiry extends to T+15 minutes each time while never exceeding the 24-hour cap. Given single-use is enabled, when the link is successfully accessed once, then subsequent requests are rejected with the same generic response and are logged as post-use access attempts. Given single-use is disabled, when the link is accessed multiple times before expiry, then all requests succeed and are audited. Given the token signature is altered, when validation occurs, then verification fails and the attempt is logged with source IP/device. Given key rotation occurs, when validating a token issued before rotation, then it validates against an active or trusted prior key within the configured grace window; after the window it fails and is logged.
Immediate Token Revocation on Appointment or Policy Change
Given an active token, when the appointment is cancelled, then the token is revoked within 30 seconds and any subsequent access yields a generic revoked/expired response with no PHI. Given an active token, when a policy change increases content sensitivity or disallows sharing, then all related tokens are revoked within 30 seconds. Given a revoked token, when staff resend a link, then a new token is issued and the old token remains invalid. Given a revocation event, then the audit trail records token_id, actor (system/staff), trigger (appointment_cancelled/policy_change), and timestamp (UTC).
Transport Security, HSTS, No-PHI Messaging, and Anti-Enumeration
Given any generated link, when a patient follows it over HTTP, then the request is redirected to HTTPS and HSTS (max-age >= 31536000; includeSubDomains) is present on the response. Given TLS negotiation, then only TLS 1.2+ ciphers are accepted and weaker protocols are rejected. Given outbound SMS/email/voice content, then the message body and URL path/query contain no PHI or patient identifiers; the only patient-specific data in transit is the opaque token. Given an invalid, expired, or revoked token, when requested, then the API returns the same status code and message body for all three cases and response time jitter prevents enumeration. Given repeated invalid token requests from the same IP/device, when the rate exceeds 10 per minute, then requests are throttled with 429 and an audit event is recorded. Given identifiers stored for link routing, then they are encrypted at rest and in transit; unauthorized read attempts are denied and logged.
Tamper-Evident Audit Trail Completeness and Integrity
Given any token lifecycle event (create, access, refresh, resend, extend, expire, revoke), then an immutable audit record is written with token_id, patient_id, artifact_id, event_type, actor_id/type, timestamp (UTC ISO 8601), channel (SMS/Email/Voice/Web), IP, and device/user agent. Given audit records, when attempting to modify or delete an existing record, then the system prevents the change and surfaces a tamper detection alert via hash-chain verification. Given a daily integrity job, when it recomputes the audit hash chain, then it completes with zero discrepancies; any discrepancy triggers a P1 alert and is logged. Given retention settings, when a tenant sets retention to N years (>=6), then records older than N years are purged with a tombstone audit entry; legal hold overrides purging. Given an export request, when filtering by date range, patient, artifact, or event type, then the system produces CSV and JSON exports within 2 minutes for up to 1,000,000 records and includes a checksum and signer identity.
Admin Search, Reporting, and Export APIs with RBAC
Given a Compliance Admin, when accessing the Audit view, then they can search and filter by patient, artifact type, event type, actor, date range, IP/device; results paginate (50/100/500 per page) with p95 query latency <= 2 seconds for up to 100,000 records. Given a Staff user without admin rights, when accessing the Audit view, then access is limited to their practice/location and export actions are disabled. Given the Reporting API, when calling GET /audit with cursor pagination and filters, then it returns signed JSON with next_cursor until exhaustion and enforces rate limits. Given an export initiated from the UI, then an asynchronous job generates the file, stores it securely, and sends a notification with a short-lived download token; the download is audited.
Self-Serve Refresh/Resend and Staff One-Click Extension with Cooldowns
Given a patient-facing link page, when loaded, then it displays a countdown to expiry with accuracy within ±1 second and updates on sliding-window extension. Given a patient clicks Refresh/Resend, when the cooldown (5 minutes per channel) has not elapsed, then the action is blocked with a friendly message; when elapsed, a new token is issued, the old token is revoked, and both are audited. Given a staff user clicks Extend in the appointment view, when within policy limits, then the token expiry is extended by the selected duration and reflected immediately on the patient page; when the extension would exceed the absolute policy max, the action is rejected with a clear reason. Given any refresh/resend/extend event, then the audit trail records actor, channel, reason, timestamps, and new vs. old expiry times.
Expiry Analytics and Proactive Alerts
"As an office manager, I want analytics and alerts on expiring items so that I can proactively reduce no-shows and improve confirmation rates."
Description

Deliver dashboards and exports that track expiry-related funnel metrics (views before expiry, refresh rates, extensions, completion after refresh, time-to-confirm) segmented by content type, channel, provider, and practice. Provide real-time alerts for at-risk items (e.g., pre-op instructions expiring within two hours and not viewed) via email/Slack, and optional automation to auto-extend within policy ceilings. Support A/B testing of TTL policies to optimize confirmation rates and reduce no-shows, with outcomes feeding back into policy recommendations. This equips practices to proactively intervene and continuously improve performance.

Acceptance Criteria
Segmented Expiry Funnel Dashboard Accuracy
Given a selected date range and filters for content type, channel, provider, and practice When the expiry analytics dashboard is loaded Then it displays for each segment the metrics: views_before_expiry, refresh_rate, extension_rate, completion_after_refresh_rate, median_time_to_confirm, and p90_time_to_confirm And totals and segment breakdowns match a SQL source-of-truth exactly on counts and within 0.01 on rates And calculations respect each practice’s configured time zone for bucketing And with up to 1,000,000 reminders in range the dashboard renders within 3 seconds
Filtered CSV Export of Expiry Metrics
Given any active dashboard filter set and date range When the user triggers Export Then a CSV is produced within 60 seconds containing columns: date, practice_id, provider_id, content_type, channel, reminders_sent, views_before_expiry, refreshes, extensions, completions_after_refresh, median_time_to_confirm_seconds, p90_time_to_confirm_seconds And aggregating CSV rows reproduces dashboard totals and rates within 0.5% rounding tolerance And files over 50 MB are streamed to object storage and returned via a signed URL expiring in 24 hours And the export contains no PHI (e.g., patient name, phone, email) and only uses pseudonymous IDs
Real-Time Alerts for At-Risk Imminent Expiry
Given an alert rule: pre-op instructions expiring within 2 hours and not viewed When a reminder first meets the condition Then an alert is delivered to configured Slack and or email within 60 seconds containing practice identifier, provider initials, appointment time, content_type, channel, and a secure console link with no PHI And duplicate alerts for the same reminder are suppressed for 30 minutes and can be snoozed for 2 hours And alerts honor practice quiet hours by queuing until the next window unless marked critical And delivery failures are retried up to 3 times with exponential backoff and recorded in audit logs
Policy-Constrained Auto-Extension Automation
Given auto-extend is enabled with a max of 2 extensions and a ceiling of 24 hours past original TTL When an item becomes at-risk per rule and is eligible by content type Then its TTL is extended by the configured increment without exceeding the ceiling and the action is audit-logged as system with timestamp and reason And no additional auto-extend occurs within a 30 minute cooldown unless a staff member manually extends And manual extensions adjust remaining auto-extension budget and are respected by automation And items marked do_not_auto_extend are never auto-extended and trigger an alert instead
TTL Policy A/B Testing Framework
Given a practice starts an experiment with two TTL variants A and B When new reminders are created during the enrollment window Then each reminder is randomly assigned 50 or 50 to A or B stratified by content_type and channel and assignment persists for that reminder And daily reports show per-variant confirmation_rate, no_show_rate, expiry_rate, and mean_time_to_confirm with 95% confidence intervals using appropriate statistical tests for proportions And the system enforces minimum sample size of 500 per arm and power 0.8 at alpha 0.05 before recommending a winner or early stop And ending the experiment allows one click promotion of the winning policy and writes an immutable audit entry of the change
Data-Driven TTL Policy Recommendations
Given at least 90 days of historical data or completed experiments for a segment When the user opens the policy recommendations view Then the system presents up to three TTL policy recommendations per content_type and channel with predicted uplift in confirmation rate and reduction in no shows including 95% confidence intervals and the data window used And segments with fewer than 200 reminders are labeled inconclusive and have no recommendation And applying a recommendation updates the active policy immediately, logs who what and when, and enables one click rollback for 7 days

Safe Preview

Displays a minimal, non-PHI teaser—practice name, provider, and appointment date—plus trusted branding before OTP entry. Builds confidence, reduces phishing anxiety, and nudges completion without exposing sensitive details, improving patient trust and conversion.

Requirements

Pre-OTP Minimal Teaser Display
"As a patient, I want to see a safe, minimal preview of who is contacting me and when my appointment is so that I feel confident it’s legitimate before I enter a verification code."
Description

Implement a pre-authentication teaser view that renders only practice name, provider name, and appointment date/time in the patient’s local timezone, along with SmileCue and practice branding and a primary call-to-action to “Verify with OTP.” The teaser must load in under 1 second on 3G-equivalent networks, work responsively across mobile/desktop, and never reveal PHI beyond the approved whitelist. It integrates with existing message links (SMS/email) and routes to the OTP gate, logs impressions and click-throughs, and supports skeleton loaders and offline-safe messaging to reassure users while preventing sensitive data exposure.

Acceptance Criteria
Whitelist-Only Teaser Content
- Given a user opens a valid pre-auth link, When the teaser renders, Then only practice name, provider name, and appointment date/time are displayed, and SmileCue/practice branding is shown. - Given the teaser is rendered, When inspecting DOM, network requests, URLs, page title, meta tags, analytics payloads, and logs, Then no PHI or non-whitelisted data is present. - Given images and assets load, When alt text or filenames are examined, Then they do not contain PHI or non-whitelisted data.
Patient Local Timezone Rendering
- Given an appointment stored server-side, When the teaser loads on a device with timezone offset different from the practice, Then the appointment date/time is shown in the device’s local timezone with correct DST handling. - Given multiple known timezone test cases (e.g., PST→EST, EST→CET, DST boundary), When rendering, Then displayed times match expected conversions to within 1 minute. - Given the device timezone cannot be determined, When rendering, Then the appointment date/time is displayed using the practice timezone with an explicit "Practice time" label (no claim of local time).
Sub-1s Load on 3G
- Given network throttled to Fast 3G (≈1.6 Mbps down/750 Kbps up/150 ms RTT), When loading the teaser page cold, Then Largest Contentful Paint occurs in ≤ 1.0 s. - Given the same conditions, When measuring, Then total transferred bytes for initial HTML/CSS/JS/fonts ≤ 150 KB compressed. - Given first render, When loading, Then the skeleton appears within 200 ms and the primary CTA is interactable within 1.0 s.
Responsive Layout Across Devices
- Given viewports 320–1440 px wide, When rendering, Then there is no horizontal scrolling and content is not clipped or overlapping. - Given common device sizes (e.g., 320x568, 375x667, 414x896, 768x1024, 1366x768), When rendering, Then branding, teaser text, and the primary CTA are readable and properly scaled. - Given touch interaction on mobile, When tapping the primary CTA, Then the hit target is ≥44x44 px and activates reliably without zooming.
Link Integration and OTP Routing
- Given a user opens the teaser via SMS or email link, When the page loads, Then the teaser view is shown without requiring prior authentication. - Given the primary CTA labeled "Verify with OTP", When tapped/clicked, Then the user is routed to the OTP gate with required token/state preserved and no PHI added to the URL. - Given an expired or tampered link, When opened, Then a generic, non-PHI error state is shown with a safe retry/contact option, and the OTP gate is not initiated.
Skeleton Loader and Offline Messaging
- Given poor connectivity or cold load, When the teaser is requested, Then a neutral skeleton UI displays within 200 ms without revealing PHI. - Given the device is offline, When opening the link, Then an offline-safe message and retry control are shown; no PHI is displayed or cached. - Given connectivity is restored, When retrying, Then the teaser renders automatically without requiring a page reload and without exposing PHI during transitions.
Impression and Click-Through Logging
- Given the teaser renders successfully, When first paint occurs, Then a single impression event is logged with anonymized link/session ID, timestamp, and client hints but no PHI. - Given the user activates the primary CTA, When navigation to OTP gate is initiated, Then a single click-through event is logged, deduplicated within the session. - Given analytics endpoints are unavailable, When events are sent, Then the UI is not blocked; events are retried with backoff up to a capped limit without including PHI.
PHI Guardrails & Redaction Rules
"As a compliance officer, I want enforceable guardrails that prevent PHI from appearing in the preview so that we remain HIPAA-compliant while improving patient trust."
Description

Create a centralized policy layer that strictly whitelists allowed teaser fields (practice name, provider name, appointment date/time) and automatically redacts or blocks all other PHI or free-text content. Policies must be enforced at render-time and API boundaries, include unit and integration validation, and emit audit logs for compliance. Add automated scans and contract tests to prevent template drift or accidental additions of disallowed fields. Include security review, threat modeling, and documented SOPs for updates to the whitelist with versioned change control.

Acceptance Criteria
Render-Time Whitelist Enforcement for Safe Preview
Given a Safe Preview render is initiated prior to OTP entry When the template contains both whitelisted and non-whitelisted fields Then only practice name, provider name, and appointment date/time are rendered in the preview And all non-whitelisted fields are omitted or replaced with the token "[REDACTED]" And no PHI or free-text values appear in the rendered output, DOM, alt text, metadata, or client-side logs And the response includes the policyVersionId used for enforcement
API Boundary Validation and Blocking
Given an API request to generate or send a Safe Preview When the payload contains any field not on the whitelist Then the API responds with HTTP 400 and error code "POLICY_VIOLATION" And the response must not echo or log offending values And an audit event is recorded with decision=deny and policyVersionId Given an API request contains only whitelisted fields When processed Then the API responds with HTTP 202 (accepted) and no non-whitelisted fields are persisted or relayed
Automated Redaction of Free-Text Inputs
Given an appointment or patient record includes free-text notes or custom fields When generating the Safe Preview Then all free-text content is excluded from the preview and backend payloads used to render it And internal logs record a redaction event count but never the original text And a metric "safePreview.redactions" increments with the number of redacted fields per render
Audit Logging for Policy Decisions
Given any render-time or API-time decision by the PHI policy layer When the decision is executed Then an immutable audit log entry is written containing timestamp, actor/service, requestId, decision (allow/deny), affected field keys, and policyVersionId And the audit record stores no PHI values or free-text content And the audit record is retrievable via the compliance export with filters by date range and decision within 5 seconds of the event
Template Drift Prevention via CI Scans and Contract Tests
Given the message/template repository When CI runs the template-scan job Then the build fails if any non-whitelisted placeholder is detected, listing file path and placeholder key in the job summary Given a change to template placeholders or API schema is proposed When contract tests execute in CI Then tests fail until the whitelist policy is updated, versioned, and referenced by the change, after which tests pass
Unit and Integration Validation Coverage Gates
Given the PHI policy engine and Safe Preview rendering services When unit tests and integration tests run in CI Then line and branch coverage for the policy engine enforcement paths are >= 90% And integration tests prove enforcement at both render-time and API boundaries for allow and deny paths And the release pipeline blocks deployment if any relevant tests fail or coverage drops below threshold
Security Review, Threat Modeling, and SOP-Controlled Whitelist Updates
Given a request to add or modify a field on the whitelist When the change is proposed Then a security review and threat model are completed and approved by Security and Product owners And the whitelist policy is versioned with a changelog, rollback plan, and two-person approval with a signed change record And the change is deployed behind a feature flag and is not active until the flag is enabled in production And the SOP for whitelist updates is updated and linked in the change record before activation
Trusted Branding & Verification Indicators
"As a skeptical patient, I want visible verification and recognizable branding so that I can quickly determine the message is legitimate and safe to proceed."
Description

Display clear trust signals within the teaser: practice logo and colors, SmileCue “Verified Sender” badge, branded short-link domain, and links that align with DMARC/SPF/DKIM-authenticated sending domains. For SMS, ensure 10DLC brand registration alignment where applicable; for email, show a recognizable from-name and security-aligned domain; for web, enforce HTTPS/TLS with HSTS and certificate pinning where supported. Provide a short, patient-friendly privacy statement and a link to SmileCue’s privacy policy to reduce phishing anxiety.

Acceptance Criteria
Email/Web Trusted Branding Render
Given a practice has a logo (PNG or SVG) and brand colors configured in SmileCue When the Safe Preview teaser is rendered in email and on the web landing page prior to OTP entry Then the practice logo is displayed at a minimum of 96x96px (retina-ready where supported) with correct aspect ratio And the primary brand color is applied to header and CTA elements And all text/background combinations meet WCAG AA contrast (>= 4.5:1) And if no logo exists, a fallback initials avatar using brand color is shown And only practice name, provider name, and appointment date are displayed (no PHI beyond these fields)
Verified Sender Badge Behavior
Given a Safe Preview teaser is displayed (email or web) When the teaser renders Then a "Verified Sender — SmileCue" badge with a lock/shield icon is visible above the CTA And the badge links to an explainer modal with a brief verification summary And the badge cannot be overridden or hidden by tenant theming And the badge text and icon pass accessibility (ARIA label present; contrast >= 4.5:1)
Email Authentication Alignment (DMARC/SPF/DKIM)
Given an outbound Safe Preview email is queued When pre-send checks run Then the From: display name is the practice name (optionally "via SmileCue") And the From domain is an authenticated, security-aligned domain controlled by SmileCue or the practice And DKIM=pass with aligned d= matching the From domain (relaxed or strict alignment per DMARC policy) And SPF=pass for the envelope-from domain aligned to From And DMARC=pass with policy at least p=quarantine on the organizational domain And if DMARC alignment fails, the send is blocked and an error is logged with remediation guidance
SMS 10DLC Brand & Campaign Alignment
Given a Safe Preview SMS is to be sent to a US number When pre-send compliance validation runs Then the message is sent only via an approved 10DLC brand and campaign registered for the practice use case And the sender (long code/toll-free) matches the approved campaign settings And if brand or campaign status is not Approved or is mismatched, the SMS is not sent and a compliance error is logged And delivery receipts and carrier feedback are stored for audit
Branded Short-Link Domain Alignment and Consistency
Given a Safe Preview includes any links (SMS or email) When links are generated Then all visible links use an approved branded short domain (e.g., scq.app or practice-branded subdomain) owned by SmileCue or the practice And the effective final landing domain is the same domain or a subdomain aligned with the authenticated sending domain And no third-party tracking domains are exposed in visible links And links resolve with HTTP 200 in < 2 seconds and do not redirect more than 2 hops
Secure Web Transport (HTTPS/TLS, HSTS, Certificate Pinning)
Given a patient opens the Safe Preview landing page When the page is requested Then the connection enforces HTTPS with TLS v1.2+ and strong ciphers And HTTP is redirected (301) to HTTPS And an HSTS header is present with max-age >= 15552000 (180 days) and includeSubDomains And certificate chain is valid and not expired And, where the client supports it (e.g., mobile app/webview), SPKI certificate pinning is enabled; connections with unpinned certs fail closed
Privacy Statement and Policy Link Clarity
Given a Safe Preview teaser is displayed (SMS-linked web or email) When the content renders Then a plain-language privacy statement (<= 160 characters, reading grade ≤ 8) is displayed near the CTA And a visible link labeled "Privacy Policy" points to SmileCue’s current privacy policy URL and opens in a secure tab And the statement and link are keyboard-focusable and screen-reader accessible (ARIA role/labels present)
Channel-Specific Safe Preview Delivery
"As a patient, I want a consistent, trustworthy preview experience whether I receive a text, email, or call so that I always know who is contacting me and why."
Description

Tailor the safe preview experience for each channel while maintaining the same whitelist content. For SMS, the landing page opens via a branded short link with meta tags for rich previews where supported. For email, align subject and preheader with teaser content without exposing PHI, and ensure consistent rendering across major clients. For voice, provide a brief IVR preview script that states the practice, provider, and appointment date/time before requesting OTP or confirmation input. Validate behavior across iOS/Android, major browsers, and common email clients.

Acceptance Criteria
SMS Safe Preview via Branded Short Link
- Given a patient with a valid mobile number and an upcoming appointment, When an SMS safe preview is sent, Then the SMS body contains a branded short link on a practice-configured domain and no PHI beyond practice name, provider name, and appointment date/time. - Given a device that supports link previews, When the message is received, Then the rich preview shows only the practice name, provider name, and appointment date/time and no other details. - Given a device that does not support rich previews, When the message is received, Then the SMS body includes a plain-text teaser with the same whitelist content within the first 140 characters. - Given the recipient taps the link on iOS 15+ or Android 11+, When the landing page loads over 4G, Then it renders the safe preview above the fold within 2 seconds and before OTP entry.
Email Subject and Preheader Teaser Alignment
- Given a patient with a valid email address and an upcoming appointment, When an email safe preview is sent, Then the Subject contains the practice name, provider last name, and appointment date/time (patient’s timezone), ≤70 characters, with no other PHI. - Given the same email, When viewed in clients (Gmail web/mobile, Outlook 365/2019 Win/Mac, Apple Mail iOS/macOS, Yahoo), Then the preheader echoes the teaser (≤100 characters) and renders consistently with teaser visible with images off. - Given images are blocked, When the email is opened, Then logo alt text is present, teaser remains visible, and no hidden text or headers include PHI. - Given sender branding is configured, When the email is delivered, Then the From name matches the practice display name and the sender domain aligns with approved sending domains.
Voice IVR Safe Preview Prior to OTP
- Given a patient eligible for voice notifications, When the IVR call connects, Then the system speaks only practice name, provider name, and appointment date and time in the patient’s timezone using a natural language format. - Given language preference is set on the patient profile, When the IVR plays the preview, Then it uses the preferred language (English/Spanish), else defaults to English. - Given the preview is finished, When input is requested, Then the IVR prompts for OTP or confirmation per workflow, captures DTMF reliably with up to 3 retries and 10-second timeouts, and completes the flow without exposing additional PHI. - Then the total preview portion duration is ≤20 seconds.
Whitelist Content Consistency Across Channels
- Given the same appointment instance, When safe previews are delivered by SMS, email, and voice, Then the practice name, provider name, and appointment date/time values are identical across channels. - Then no other PHI (e.g., patient name, reason for visit, insurance, address beyond practice name) appears in message bodies, headers, URLs, meta tags, audio, or page source. - Given timezone differences, When formatting the appointment date/time, Then the patient’s timezone is used; if unknown, the practice default timezone is used.
Landing Page Rendering, Performance, and Accessibility
- Given the safe preview landing page is opened from SMS or email, When loaded on iOS Safari 16+, iOS Chrome 116+, Android Chrome 116+, Samsung Internet 21+, and desktop Chrome/Edge/Firefox/Safari (latest two versions), Then the safe preview appears above the fold with no layout shift >0.1 and LCP ≤2.5s on simulated 4G. - Then all content is served over HTTPS (TLS 1.2+), HSTS is enabled, and there is no mixed content. - Then the safe preview section meets WCAG 2.1 AA for color contrast, focus order, and screen reader labels for practice, provider, and appointment date/time. - Then the page includes noindex,nofollow and Open Graph/Twitter meta tags limited to whitelist fields.
Fallbacks, Expired Links, and Error States
- Given a client blocks link preview fetching, When the SMS or email is received, Then the human-readable teaser (practice, provider, appointment date/time) is present in the message body without requiring a rich preview. - Given the landing page cannot retrieve appointment data, When the page loads, Then it shows a branded generic message with no PHI and offers to request a new OTP to proceed. - Given a short link is expired or already used, When it is opened, Then a non-PHI “Link expired” page is shown with a single action to request a new code; no appointment details are revealed.
Cross-Channel Device and Client Validation Matrix
- Given the supported device and client matrix (iOS 15–17, Android 11–14; Gmail web/iOS/Android; Outlook 365/2019 Win/Mac; Apple Mail iOS/macOS; Yahoo; iOS Messages; Android Messages), When QA executes regression tests, Then ≥95% of test cases pass with no critical defects and all failures have documented workarounds or are out-of-scope exceptions. - Then UAT sign-off is obtained from one dentist, one hygienist, and one office manager from pilot practices confirming trust and clarity of the safe preview across channels.
A/B Testing & Conversion Analytics
"As a product manager, I want to experiment with safe preview variants and see their impact on verification and confirmations so that we can maximize patient trust and conversion."
Description

Enable configuration to A/B test teaser variants (copy tone, badge placement, CTA wording) within the strict whitelist and measure effects on OTP completion, time-to-verify, bounce rate, and opt-out signals. Provide dashboards segmented by practice, channel, and cohort with statistically-sound results and guardrails to stop underperforming or risky variants. Emit events to the analytics pipeline and expose summary metrics via the admin console and API.

Acceptance Criteria
Configure Whitelisted A/B Variants for Safe Preview
- Admin can create 2–5 variants per test with only editable fields: copy tone (predefined list), badge placement (top/inline), and CTA wording (preapproved phrases) - System blocks any non-whitelisted HTML, styling, links, or dynamic tokens; attempt returns validation error and does not save - Variant preview renders exactly as delivered for SMS, email, and voice landing flows without exposing PHI - RBAC: only users with "Experiment Manager" role can create/edit/pause tests for assigned practices - All changes (create/edit/delete) are recorded with user, timestamp (UTC), before/after values in an immutable audit log - Only one active A/B test per practice per channel at a time; enabling a new test on the same scope requires pausing the existing one
Deterministic Assignment & Traffic Splitting
- Supports equal split and custom weighted allocation (e.g., 10/20/70) per practice and channel - Assignment is deterministic per test using anonymized_patient_id + channel + test_id; a patient sees the same variant on repeat exposures during the test - Assignment persists for 30 days or until test is paused; after pause, all new traffic routes to control - Excludes patients who have opted out on that channel within the past 30 days from being assigned - Minimum sample size and max exposure caps are configurable per test; once caps are reached, remaining traffic routes to control - Concurrency rule enforced: a patient is assigned to at most one active test per channel to prevent interaction effects
Event Emission for Conversion, Timing, Bounce, and Opt-Out
- Events emitted for: preview_view, otp_start, otp_success, otp_failure, session_bounce (no otp_start within 3 minutes of preview_view), opt_out - Each event includes: event_name, timestamp_utc, practice_id, channel (sms/email/voice), test_id, variant_id, cohort_tags (from approved list), session_id, anonymized_patient_id, schema_version - P95 end-to-end delivery latency to analytics pipeline <= 5s; end-to-end loss rate < 0.1% with at-least-once delivery and idempotent event keys - Payloads contain no PHI/PII beyond anonymized_patient_id; content fields are redacted/omitted by design - Retries with exponential backoff for transient failures up to 6 attempts; dead-letter queue retains failures for 7 days - Data quality monitor alerts if variant_id or test_id is missing on >0.5% of events over a 15-minute window
Dashboard: Segmented Metrics and Statistical Results
- Admin console shows, by selected date range and scope (practice/channel/cohort), per-variant metrics: OTP completion rate, median and p95 time-to-verify, bounce rate, opt-out rate - Variant comparisons display absolute and relative lift vs. control with 95% confidence intervals and p-values; clearly labels "insufficient sample" when thresholds unmet - Supports filtering by practice, channel, and cohort; results update within 15 minutes of new data (data freshness SLA) - Sample size guardrails configurable (e.g., min 500 conversions per variant or 7 days, whichever later) and enforced before declaring a winner - Dashboard indicates current test status (Running/Paused/Completed) and traffic allocation per variant in real time - All numbers reconcile with underlying events; variance between dashboard and raw counts is <0.1% over the same window
Guardrails and Auto-Pause Underperforming or Risky Variants
- Configurable thresholds to auto-pause a variant when OTP completion shows ≥-5% relative lift vs. control with ≥95% statistical confidence or opt-out rate increases by ≥+0.5 pp with ≥95% confidence - When triggered, system stops assigning new traffic to the variant within 10 minutes and routes it to control; existing sessions proceed without interruption - Alert sent to configured recipients (email and in-console notification) with test_id, variant_id, metric breaching threshold, confidence, and timestamp - Auto-pause and manual overrides require a reason note and are recorded in audit logs - Paused variants remain visible in dashboards with a "Paused by Guardrail" badge and the trigger details - Re-enabling a paused variant resets future traffic but preserves historical metrics
API: Programmatic Access to A/B Summary Metrics
- GET /admin/ab-tests/{test_id}/summary returns per-variant metrics (completion rate, lift, CI, p-value, median/p95 time-to-verify, bounce, opt-out) and allocation - Supports query params: practice_id, channel, cohort, start_utc, end_utc, granularity (hour/day), page, page_size - OAuth2 client-credentials required; scope "ab.read"; rate limit 60 req/min per client; 429 returned with Retry-After on limit exceed - Responses are cached; p95 latency <= 500 ms for cached queries and <= 1500 ms for uncached - Values match dashboard within 0.1% tolerance; includes ETag and last_updated_utc for cache validation - API returns HTTP 400 for invalid filters and 403 for unauthorized practice/channel access; no PHI/PII in payloads
Accessibility & Localization
"As a patient with accessibility needs or a non-English speaker, I want a clear, readable, and localized preview so that I can trust and understand the message before proceeding."
Description

Ensure the teaser meets WCAG 2.2 AA: proper semantic structure, focus states, contrast ratios, keyboard navigation, and screen reader labels. Localize fixed copy and date/time formats, supporting at least EN and ES at launch, with automatic locale detection and manual override. Ensure all trust badges and images have accessible text equivalents and that voice channel scripts are concise and clear for diverse audiences.

Acceptance Criteria
Accessible Semantic Teaser Structure
Given the Safe Preview screen loads Then the document includes exactly one H1 that describes the screen purpose And practice name, provider name, and appointment date are grouped with semantic elements (list or definition list) preserving info and relationships per WCAG 1.3.1 And each item has an accessible name exposed via native semantics or aria-labelledby And html lang attribute matches the active locale en or es per WCAG 3.1.1 and language of parts for localized snippets per WCAG 3.1.2 And reading order announced by screen readers matches visual order on NVDA, JAWS, and VoiceOver And no PHI beyond practice name, provider, and appointment date is exposed in accessible names or descriptions
Keyboard Navigation and Focus Visibility
Given a keyboard-only user interacts with the Safe Preview When tabbing from the browser address bar Then focus lands first on the main content skip link and then proceeds in a logical order through language toggle and primary action And all interactive elements are reachable and operable with keyboard only per WCAG 2.1.1 And there is no keyboard trap per WCAG 2.1.2 And focus indicator is clearly visible with minimum 2 CSS pixel thickness and 3 to 1 contrast against adjacent colors per WCAG 2.4.11 and 2.4.13 And Space and Enter activate buttons and links appropriately And Esc dismisses any transient UI without losing context
Color and Non Text Contrast Compliance
Given the Safe Preview renders text, icons, and controls Then normal text contrast ratio is at least 4.5 to 1 and large text at least 3 to 1 per WCAG 1.4.3 And visual focus indicators, control boundaries, and essential icons meet at least 3 to 1 contrast per WCAG 1.4.11 And color is not the sole means to convey information or state per WCAG 1.4.1 And link text is distinguishable from surrounding text by more than color alone And contrast checks pass in both light and dark brand themes if provided
Automatic Locale Detection and Manual Override
Given a first time visitor opens the Safe Preview via SMS or email link When the app inspects browser or device Accept Language headers Then the UI loads in English or Spanish according to the highest supported preference with fallback to English And a language toggle is available and operable by keyboard and screen readers with name role and state exposed And selecting a language immediately updates all fixed copy without page reload and sets lang attribute accordingly And the selection persists for at least 30 days using non PHI storage and is respected on return visits And screen readers announce the language change without moving focus unexpectedly
Localized Date and Time Formatting EN ES
Given the Safe Preview displays the appointment date and time When locale is English Then the format uses locale appropriate month weekday and 12 hour or device preference with AM PM and includes appointment time zone label When locale is Spanish Then the format uses locale appropriate month weekday and 24 hour format with leading zeros and includes appointment time zone label in Spanish And midnight and noon are displayed without ambiguity And switching locale updates the date and time format instantly and consistently across UI and voice copy And no PHI beyond practice name provider and appointment date time is revealed
Accessible Non Text Content and Trust Badges
Given the Safe Preview shows logos badges and decorative images Then each meaningful image has concise alt text or an accessible name that describes purpose not appearance And decorative images are marked with empty alt and aria hidden true so they are ignored by assistive tech And the practice logo alt conveys practice name And trust badges are announced with a short textual description and are not the only way trust information is conveyed And if any image fails to load the essential information remains available as text
Concise Clear Voice Script Localization EN ES
Given the voice channel delivers the Safe Preview teaser by phone Then scripts exist in English and Spanish and contain only practice name provider and appointment date time with no PHI And each script duration is 20 seconds or less at typical 140 to 170 words per minute And the call offers controls to repeat the message and to switch language before proceeding to OTP And DTMF input is recognized for controls using common keys and confirmed via brief auditory feedback And English script readability is at or below 8th grade by Flesch Kincaid and Spanish script uses plain language comparable grade level And date and time are pronounced correctly for each locale including weekday and time of day
Configurable Teaser Rules & Fallbacks
"As an office manager, I want to configure the teaser within safe limits and have sensible fallbacks so that patients get a trustworthy preview even when some details are unavailable."
Description

Provide admin controls to toggle which approved fields appear (within the whitelist), manage copy and branding elements, and define fallbacks when data is missing (e.g., hide provider if unavailable, display generic safe copy). Include feature flags per practice, environment-based defaults, and graceful degradation when network or asset loads fail. All configurations must be validated against PHI policies and logged for auditability.

Acceptance Criteria
Whitelist Toggle Enforcement
Given I am an admin with permission to edit Safe Preview settings When I open Safe Preview configuration Then only the approved fields Practice Name, Provider, and Appointment Date are available to toggle Given I attempt to add any dynamic token outside the whitelist (e.g., {{patient_name}}, {{dob}}) When I click Save Then the save is blocked, an inline error states Only approved fields are allowed, and the API responds 400 with error_code PHI_VALIDATION_FAILED Given I toggle any approved field ON or OFF When I click Save Then the API responds 200, the change persists, and the preview reflects the new state within the same session
Fallback Rendering for Missing Data
Given provider data is unavailable for the appointment When the teaser renders Then the provider line is omitted with no blank placeholders Given provider and appointment date are both unavailable When the teaser renders Then only the practice name and generic safe copy are displayed Given any single approved field is missing When the teaser renders Then no non-approved data is substituted, and no error is shown to the patient
Per-Practice Feature Flagging
Given Practice A has the Safe Preview feature flag ON and Practice B has it OFF When patients from each practice access the pre-OTP link Then Practice A sees the Safe Preview teaser and Practice B sees the default pre-OTP experience Given I toggle the feature flag for a practice When I save the change Then the change takes effect for new sessions within 60 seconds and is recorded in the audit log
Environment Default Configuration
Given the environment is Staging When a new practice enables Safe Preview without overrides Then defaults are applied: Practice Name ON, Provider ON, Appointment Date ON, Branding uses environment default, Copy uses default safe copy Given the environment is Production When a new practice enables Safe Preview without overrides Then the same safe defaults are applied and no non-approved tokens are present Given a practice override exists When rendering the teaser Then practice-level settings take precedence over environment defaults
Graceful Degradation on Asset or Network Failure
Given the logo asset fails to load or the CDN request exceeds 2 seconds When the teaser renders Then a text-only header with the practice name is shown, no broken image icon is displayed, and the OTP flow remains accessible Given any network request for branding assets fails When the teaser renders Then the layout remains usable on mobile and desktop, and a non-blocking event branding_fallback is logged
PHI Policy Validation on Save
Given I edit teaser copy and branding When I include only approved tokens {{practice_name}}, {{provider_name}}, {{appointment_date}} and click Save Then the save succeeds and the preview reflects the content Given I include any disallowed token or PHI pattern outside the whitelist When I click Save Then the save is blocked with a clear error and the attempt is logged with user_id, practice_id, and reason PHI token blocked
Configuration Change Audit Trail
Given any create, update, or delete to Safe Preview settings is performed When the operation completes whether success or validation failure Then an immutable audit entry is recorded with timestamp, actor, practice_id, environment, action, before and after values when applicable, and outcome Given an authorized auditor requests the audit log for a practice and date range via the API When the query executes Then matching entries are returned and include a unique audit_id for each record

Power Planner

Right-size every experiment before you launch. Power Planner calculates required sample size and run time by cohort and goal (confirmations, time-to-fill, no-shows, revenue saved), accounts for day-of-week seasonality, and supports sequential testing with smart early-stop criteria. You get trustworthy winners faster, without overexposing patients or wasting weeks on underpowered tests.

Requirements

Multi-Goal Sample Size & Runtime Calculator
"As an office manager, I want accurate sample size and run-time estimates for my chosen goal so that I can plan realistic tests without underpowering or delaying scheduling operations."
Description

Calculates required sample size and expected calendar run time per variant and per cohort for selected goals (confirmations, time-to-fill, no-shows, revenue saved). Supports binary and continuous metrics, baseline inputs or auto-derived baselines from SmileCue historical data, minimum detectable effect (MDE), target power, and alpha. Incorporates traffic allocation, send caps, and cohort volumes to translate sample needs into days/weeks. Provides UI and API output, validation warnings for infeasible or underpowered plans, and exportable design summaries for stakeholder review.

Acceptance Criteria
Configure Multiple Goals and Compute Per-Cohort/Variant Sample Sizes
Given a plan with at least one binary goal and one continuous goal, valid baselines, MDEs, target power, alpha, and N≥2 variants (including control) across ≥1 cohorts When the user clicks Calculate Then the system returns per-cohort x per-variant required sample sizes for each goal and an overall required sample size per cohort x variant equal to the maximum across goals And the calculation method uses a two-proportion test for binary goals and a two-sample t-approximation for continuous goals with two-sided alpha unless one-sided is explicitly selected And all sample sizes are rounded up to the nearest whole number and are ≥2 per variant per cohort And changing inputs behaves monotonically: decreasing MDE or increasing power increases required sample size; increasing alpha decreases required sample size And the UI labels the "driver goal" that determines the overall sample size for each cohort x variant
Baseline Source Selection and Auto-Derivation from SmileCue History
Given a metric set to Manual baseline source with valid values (binary: 0<p<1; continuous: finite mean and sd>0) When Calculate is triggered Then the entered baselines are used in all computations and are echoed in results Given a metric set to Auto baseline source and a selected lookback window and cohort filter with sufficient historical data (meets configured min-days and min-events per goal & cohort) When Calculate is triggered Then baseline mean/proportion and variance (or sd) are auto-derived from SmileCue aggregates for the selected cohorts and window, displayed read-only with the window, N used, and timestamp And no patient-level identifiers or PHI appear anywhere in the UI or exports Given Auto is selected but the data do not meet sufficiency thresholds When Calculate is triggered Then a blocking validation "Insufficient historical data for baseline" is shown and calculation is disabled until Manual baselines are provided or the window is adjusted
Runtime Estimation With Traffic Allocation, Send Caps, and Cohort Volume
Given per-cohort expected daily eligible volume, selected send-day schedule, per-cohort send caps, and per-variant traffic allocation that sums to 100% within each cohort When Calculate is triggered Then for each cohort x variant the expected daily assigned volume is computed as eligible daily volume × allocation constrained by send caps and active send days And expected calendar runtime (in whole days) per cohort x variant is computed as ceiling(overall required sample size for that cohort x variant / expected daily assigned volume) And the plan summary displays runtime per cohort x variant and the test-level runtime equal to the maximum across all cohorts and variants, with units in days and weeks And if allocations do not sum to 100% in any cohort, a blocking validation error is shown and runtime is not computed for that cohort
Validation Warnings for Infeasible or Underpowered Plans
Given any input is invalid (e.g., binary baseline not in (0,1); continuous sd≤0; MDE=0; power≤0.5 or ≥0.99; alpha≤0 or ≥0.5; allocations not summing to 100% per cohort) When Calculate is triggered Then a blocking validation error identifies the specific field(s) and prevents calculation Given inputs are valid but expected daily assigned volume per cohort x variant < 1 on active send days When Calculate is triggered Then a blocking error "No feasible traffic to reach required sample" is shown for those cohorts/variants Given inputs are valid and volumes are >0 but estimated test-level runtime exceeds the configurable long-run threshold (default 12 weeks) When Calculate is triggered Then a non-blocking warning "Long estimated runtime" is displayed with the computed duration Given an MDE for a binary goal implies a variant rate outside (0,1) when applied to the baseline When Calculate is triggered Then a blocking validation "MDE incompatible with baseline" is shown for that goal
UI and API Output Parity and Contract
Given identical inputs are submitted via the UI and the Calculate API endpoint When results are returned Then per-cohort x variant sample sizes per goal, overall sample sizes, and expected runtimes match within 0.5% or 1 unit (whichever is larger) And both surfaces return/Display: echo of inputs, per-goal assumptions (baseline, MDE, power, alpha, tail), per-cohort volumes and allocations, per-cohort x variant outputs, test-level summary, and any validations/warnings And the API responds 200 with application/json on success and 4xx with structured error codes and messages on validation failure And the API response conforms to the published schema, including version, calculationId, and traceId fields
Exportable Design Summary for Stakeholder Review
Given a successful calculation exists When the user selects Export and chooses JSON, CSV, or PDF Then a downloadable file is generated within 5 seconds that includes: inputs, baseline sources and windows, derived baselines (with N and date range), per-goal and overall sample sizes per cohort x variant, expected runtimes, allocations, volumes, driver goal per cohort x variant, and all warnings/errors And exports contain only aggregate, de-identified data and no PHI And file names follow the pattern power-plan_<calculationId>_<YYYYMMDD>.{json|csv|pdf} And the exported values match the on-screen/UI values within the same tolerances defined for UI/API parity
Day-of-Week Seasonality Adjustment
"As a practice owner, I want Power Planner to account for weekday and holiday patterns so that my test timelines and power estimates reflect real patient behavior."
Description

Models day-of-week and holiday seasonality using practice-level historical messaging and appointment data to adjust volume forecasts and variance used in power calculations. Allows admins to review and tune seasonality factors, exclude anomalous periods, and simulate alternate schedules. Updates duration projections and early-stop thresholds accordingly, with visualizations showing the impact of specific days on expected progress and confidence.

Acceptance Criteria
Seasonality Factors Derived from Historical Data
Given a practice has ≥6 months of historical messaging and appointment events per cohort and goal When the seasonality model is run Then day-of-week multipliers (Mon–Sun) and holiday adjustments are computed per cohort and goal and normalized to mean 1.00 And per-day variance inflation factors are produced per cohort and goal And US federal and practice-defined holidays are included; closed days receive a factor ≤0.10 And the model run completes within 60 seconds for ≤24 months of data and ≤10 cohorts
Admin Review and Tuning of Factors
Given seasonality factors have been computed When an admin opens Power Planner → Seasonality Then a table and chart display Mon–Sun factors per cohort and goal with two-decimal precision And the admin can edit any factor within 0.20–2.00 with inline validation and see live recalculation preview And Save persists the new factors as Version N+1 with timestamp, user, and change summary And Reset restores the latest computed model outputs And all edits update subsequent forecasts and power calculations within 3 seconds
Exclude Anomalous Periods from Training
Given the admin selects one or more date ranges or tags (e.g., outage, snowstorm) When exclusions are applied Then excluded periods are removed from training data and recomputation completes within 60 seconds And the UI displays before/after factors with percent change per weekday And a warning prevents exclusions that leave <8 weeks of data or <200 events per weekday per goal And all exclusions are logged with reason, user, and timestamp and are reversible
Alternate Schedule Simulation
Given a test configuration with cohorts and goals When the user simulates an alternate send schedule (enable/disable weekdays, adjust daily volumes by ±0–100%) Then the planner outputs adjusted daily forecast, cumulative expected N, and per-day variance for the selected horizon And it calculates projected run time to reach 80–95% power at chosen alpha and expected effect size And it estimates probability of early stop under the selected sequential rule And two scenarios can be compared side-by-side with deltas; results exportable as CSV and PDF
Power, Duration, and Early-Stop Recalculation
Given a configured sequential test with seasonality enabled When any factor, exclusion, or schedule is changed Then required sample size and minimum duration are recomputed using day-level heteroskedastic variance and displayed within 3 seconds And the minimum duration ensures each active weekday is observed at least twice, or a warning is shown And early-stop thresholds/bounds are updated to reflect seasonality and shown alongside prior values And a downloadable calculation log includes inputs, formulas used, and version IDs
Visualization of Day and Holiday Impact
Given a planning horizon is selected When the seasonality view is opened Then a chart displays expected daily accrual vs uniform baseline with color-coded weekdays and 95% CI bands And holidays and closures are annotated on the timeline And tooltips show day, factor, expected N, variance, and CI; no PHI is shown And pan/zoom and date range filters respond within 300 ms on datasets ≤2 years
Data Sufficiency, Fallbacks, and Auditability
Given insufficient historical data exists When a weekday has <200 events per goal in the training window Then the model applies shrinkage toward the practice-wide mean and flags the weekday with an “Insufficient Data” badge And if overall data <8 weeks, neutral factors of 1.00 are applied and holiday adjustments disabled with a warning banner And all model inputs/outputs are versioned with a hash and timestamp; repeated runs with identical inputs reproduce identical outputs And the seasonality model retrains nightly at 02:00 local, completing within 15 minutes or sending an alert to admins on failure
Sequential Testing with Smart Early-Stop Rules
"As a data-savvy office manager, I want safe early-stopping rules so that I can declare trustworthy winners sooner and avoid wasting patient messages on losing variants."
Description

Implements pre-registered sequential analysis with configurable alpha-spending (e.g., O’Brien–Fleming or Pocock) for frequentist tests and optional Bayesian monitoring, enabling early stop for efficacy or futility while preserving error rates. Supports interim looks at calendar-based or information-based intervals, compatible with binary and continuous goals. Provides clear decision guidance, intervals, and auto-generated recommendations. Locks parameters at start to prevent peeking misuse and records all analyses for audit.

Acceptance Criteria
Parameter Locking and Pre-Registration
Given a user configures an experiment (overall alpha=0.05, alpha-spending function, interim schedule, metric type, tails, MDE, Bayesian option flag, stop thresholds) When the user starts the experiment via UI or API Then the system persists an immutable pre-registration record with content hash and timestamp And Then all test parameters become read-only in UI and API; any edit attempt returns HTTP 409 with message "Parameters locked after start" And Then the lock status is shown on the experiment detail view And Then the denied edit attempt is appended to the audit log with user id, timestamp, diff preview, and outcome "denied"
Alpha-Spending Configuration and Error Control
Given a frequentist test with K=5 interim looks and O’Brien–Fleming spending at alpha=0.05 When boundaries are computed Then the cumulative alpha spent across looks equals 0.05±1e-6 and the z-boundaries match reference values within ±0.01 And Then the p-value used for stopping is the stagewise-adjusted p-value for the current look Given the same setup with Pocock spending When boundaries are computed Then each interim boundary matches standard Pocock values within ±0.01 and overall alpha is preserved at 0.05±1e-6
Interim Looks Scheduling (Calendar and Information-Based)
Given a schedule of calendar-based looks (e.g., every 7 days at 18:00 local) and information-based looks at info fractions [0.25, 0.5, 0.75, 1.0] When the experiment runs Then an interim analysis triggers at the first satisfied condition with a tolerance window of ±1 hour (calendar) and ±0.02 (info fraction) And Then unplanned ad-hoc looks are blocked; attempts return HTTP 403 And Then the audit log records planned vs actual trigger, data cut timestamp, and info fraction at each look
Early Stop for Efficacy and Futility (Frequentist)
Given two cohorts with a binary goal and an O’Brien–Fleming plan When the z-statistic at an interim look crosses the upper efficacy boundary Then the system sets decision=Stop for Efficacy, recommends Adopt Variant, freezes enrollment, and prevents further looks And Then it reports a group-sequential adjusted 95% confidence interval for the effect size and the look number at stop Given a pre-specified futility boundary or conditional power < 10% When that condition is met at a look Then the system sets decision=Stop for Futility, recommends Do Not Adopt, freezes enrollment, and prevents further looks
Bayesian Monitoring Option and Labeling
Given Bayesian monitoring is enabled with prior Beta(1,1) for binary goals and thresholds efficacy≥0.95, futility≤0.05 When an interim look yields P(variant>control|data) ≥ 0.95 Then the system sets decision=Stop for Efficacy, reports posterior probability, 95% credible interval, and recommended action And Then all UI labels and exports indicate "Bayesian" and do not claim frequentist error control Given P(variant>control|data) ≤ 0.05 When that occurs at a look Then the system sets decision=Stop for Futility with the same reporting and labeling requirements
Comprehensive Audit Trail Without PHI
Given any interim analysis or attempted parameter change When it occurs Then an immutable audit entry is created including experiment id, user id, event type, timestamp (ISO-8601), app version, pre-registration hash, boundary values, test statistics, decision, recommendation, and data snapshot checksum And Then exporting the audit trail as JSON and PDF omits PHI (names, phone numbers, emails) as validated by schema checks; export succeeds within 5 seconds for experiments up to 20 looks
Metric Types Support and Reporting
Given a binary goal (e.g., confirmations) When running a sequential test Then the system uses an appropriate frequentist test for proportions and reports absolute and relative effect with a group-sequential adjusted 95% interval Given a continuous goal (e.g., time-to-fill) When running a sequential test Then the system uses an appropriate test for means (e.g., t-test/Welch) or the configured Bayesian normal model and reports mean difference with an adjusted 95% confidence interval or 95% credible interval And Then all reports show per-cohort sample sizes, total information fraction, and current look number
Cohort Targeting & Eligibility Rules
"As a hygienist, I want to target and balance tests across the right patient groups so that results are relevant and fair without interfering with other experiments."
Description

Lets users define cohorts (e.g., new patients, overdue recalls, payer type, age bands) and inclusion/exclusion criteria for each experiment. Pulls attributes from SmileCue integrations and local EHR/PM systems via existing HIPAA-compliant connectors, with safe mapping and validation. Ensures stratified randomization within cohorts, enforces mutual exclusivity across overlapping live experiments, and supports per-cohort quotas to balance exposure.

Acceptance Criteria
Cohort Definition from Integrated Data Sources
Given SmileCue and EHR/PM connectors are authenticated and healthy When a user creates a new cohort and selects attributes across connected systems Then only mapped, validated attributes are available for selection with their data types And saving the cohort stores a normalized, versioned definition without raw PHI fields And a preview member count is returned within 5 seconds for practices with ≤100k active patients
Inclusion and Exclusion Rule Evaluation with Real‑Time Preview
Given a saved cohort When a user adds inclusion and exclusion rules (e.g., payer type, age band, visit reason) Then the preview updates within 3 seconds to show total eligible, included, and excluded counts And contradictory or unsatisfiable rules are flagged with an explanation and Save is disabled And authorized users can sample up to 50 anonymized member records to verify rule effects
Safe Attribute Mapping and Validation Guards
Given an admin maps external fields to SmileCue attributes When the admin saves a mapping Then the system validates type compatibility, allowed values, and nullability And mappings with >0.5% sample validation errors over 1,000 records are rejected with actionable errors And unmapped or invalid attributes cannot be used in cohorts until passing validation
Stratified Randomization per Cohort with Allocation Tolerances
Given an experiment with variants and target allocation ratios per cohort (e.g., 50:50) When eligible patients are assigned within a cohort Then block randomization is applied to maintain per‑cohort balance And for N ≥ 200 assignments in a cohort, observed allocation deviates ≤ 2 percentage points from target And for N < 200, the absolute difference in variant counts within the cohort never exceeds 2
Mutual Exclusivity Across Overlapping Live Experiments
Given two or more live experiments with overlapping eligibility When a patient qualifies for multiple experiments Then the patient is assigned to only one experiment according to a configurable priority rule And the system records an audit entry listing excluded experiments and reasons And no patient receives concurrent treatments from multiple experiments within a 30‑day cooldown
Per‑Cohort Exposure Quotas with Time‑Window Enforcement
Given daily and total exposure quotas are configured per cohort When assignments would exceed a cohort’s active quota window Then the assignment is skipped and logged with a quota‑exceeded reason And quota windows are enforced in the practice’s local timezone and reset within 5 minutes of window start And dashboards display used, remaining, and reset time for each cohort quota in real time
Overexposure Guardrails & Patient Safety Limits
"As a compliance-conscious office manager, I want automatic guardrails that prevent over-messaging patients so that experiments remain patient-friendly and policy-compliant."
Description

Applies configurable caps per patient and per channel (SMS, email, voice) during experiments, consent and opt-out checks, blackout windows around appointments, and quiet hours enforcement. Blocks configurations that would violate limits given projected volumes, suggests adjusted allocations or extended durations, and requires explicit override with reason and role-based approval. Integrates with Power Planner timelines to prevent unsafe overexposure.

Acceptance Criteria
Per-Patient Channel Caps During Experiment Sends
Given a patient in an active experiment with caps SMS=3 per rolling 7 days, Email=2 per rolling 7 days, Voice=1 per rolling 14 days; When the system attempts a 4th SMS within the last 7 days; Then the send is blocked, an event is logged with {event: "send_blocked", rule: "channel_cap_exceeded", channel: "SMS", patient_id_hash, experiment_id, timestamp}, and no carrier request is issued. Given the system attempts a 3rd SMS within the last 7 days; When the patient has exactly 2 SMS exposures in that window; Then the send proceeds, the SMS counter increments to 3, and an event {event: "send_allowed", channel: "SMS"} is logged. Given the earliest SMS exposure ages beyond 7 days; When a new SMS send is evaluated; Then the rolling window excludes the aged exposure and the decision uses the updated count. Given an overall per-patient cap of 5 across all channels per 7 days; When cumulative SMS+Email+Voice exposures in the last 7 days equal 5; Then any additional send on any channel is blocked with rule "overall_cap_exceeded". Given a decision request at send time; When caps are evaluated; Then the decision latency is ≤200 ms at P95 and ≤500 ms at P99.
Consent and Opt-Out Enforcement
Given a patient lacks explicit consent for SMS; When any SMS send is evaluated; Then the send is blocked with rule "no_consent", and the decision log includes patient_id_hash, channel, experiment_id, without PHI in free-text fields. Given the system receives an inbound SMS with STOP/UNSUBSCRIBE; When processed; Then the patient’s SMS opt-out flag is set within 5 seconds and a single confirmation message is sent (if allowed by policy), and all future SMS sends are blocked. Given a patient has email opt-out recorded; When an email send is evaluated; Then the send is blocked with rule "opted_out" and no SMTP transaction is initiated. Given a patient is on a do-not-call list; When a voice call is evaluated; Then the call is blocked with rule "do_not_call" and no call session is created. Given audit requirements; When any consent-based block occurs; Then an immutable audit record is written with {event, rule, channel, patient_id_hash, experiment_id, timestamp, actor_id/null}.
Quiet Hours and Timezone Compliance
Given quiet hours are configured as 20:00–08:00 in the patient’s local timezone; When a message is scheduled at 07:59 local; Then it is automatically rescheduled to 08:00 local and the schedule change is logged with rule "quiet_hours_reschedule". Given a message is evaluated at 21:00 local; When quiet hours are active; Then the send is blocked or deferred per channel policy, and no carrier/API call is made during quiet hours. Given a patient has no explicit timezone; When determining local time; Then the system infers timezone from confirmed appointment location > patient area code > practice default in that order, and records the source used. Given conflicting daylight saving changes; When calculating quiet hours; Then local time transitions are honored (no duplicate or skipped sends) and next-run time is correct. Given decision and reschedule operations; When executed; Then P95 computation latency remains ≤200 ms and rescheduled send time is visible in the UI within 2 seconds.
Appointment Blackout Windows
Given blackout windows are configured as [-24h, +24h] around any confirmed appointment; When an experimental promotional SMS is due within this window; Then the send is blocked with rule "appointment_blackout" and remains unsent. Given a queued experimental email falls into a blackout because an appointment was created/updated; When the blackout is detected; Then the queued email is canceled prior to handoff to the ESP and the cancellation is logged. Given appointment reminder messages designated as exempt; When evaluated; Then exemption is honored and does not count against experimental exposure caps. Given multiple appointments exist; When computing blackout; Then the union of blackout intervals is applied with no gaps between overlapping windows. Given blackout evaluation; When performed; Then decision latency is ≤200 ms P95 and audit includes appointment_id (hashed) and blackout interval applied.
Pre-Launch Exposure Validator with Suggestions (Power Planner Integration)
Given an experiment configured for SMS frequency 3/week over 4 weeks with overall cap 5/7 days and cohort size 1,200; When Power Planner projects per-patient exposures of 10 in 28 days; Then launch is blocked with severity "error" and rule "projected_overexposure". Given launch is blocked; When the user requests suggestions; Then the system proposes at least one alternative (e.g., reduce frequency to 2/week or extend duration to 7 weeks with 50% allocation) that yields projected exposures ≤ caps, and displays the revised projections. Given suggestions are shown; When the user applies one; Then the configuration updates and the validator re-runs automatically, allowing launch only if all caps are satisfied. Given seasonality adjustments from Power Planner; When projections are calculated; Then day-of-week send distribution is incorporated into exposure counts. Given a validation run; When completed; Then a validation report is stored with {experiment_id, inputs_hash, projections, violations[], suggestions[], timestamp} and is exportable as JSON/CSV.
Override Workflow with Role-Based Approval and Audit Trail
Given a configuration violates caps; When a user with role "Experiment Owner" requests an override; Then the system requires an explicit reason (min 15 chars), defines scope (channels, cohorts, duration), and sets status "Pending Approval". Given an override request is pending; When approved by a user with role "Compliance Admin" or "Practice Owner"; Then the override becomes active only for the defined scope and expires automatically at the configured end time or in ≤14 days, whichever is sooner. Given an override is active; When a send would otherwise be blocked solely by the overridden rule; Then the send proceeds and logs {event: "override_applied", rule_overridden, approver_role, reason_id}. Given an override is denied or expires; When a send is evaluated; Then normal guardrails apply and sends are blocked per rules. Given audit requirements; When any override action occurs; Then an immutable audit entry is created with user_id, role, timestamp, reason_text (no PHI), scope, decision, and is included in quarterly compliance export.
Cross-Experiment Exposure Aggregation and Race Safety
Given a patient is enrolled in two active experiments; When Experiment A has recorded 2 SMS sends in the last 7 days and Experiment B attempts 2 additional SMS within that window; Then the 2nd attempt from Experiment B is blocked to respect the SMS cap=3/7 days, with rule "cap_exceeded_cross_experiment". Given two sends for the same patient and channel are evaluated within 1 second from different experiments; When decisions are made; Then a distributed lock or idempotent counter ensures only one send is allowed up to the cap and the other is blocked, with no duplicate carrier requests. Given exposures are counted; When aggregating; Then counts include control and variant arms if they use the same channel, and exclude non-experimental transactional messages flagged as exempt. Given reporting; When viewing patient exposure ledger; Then a unified view shows per-channel and overall counts across all experiments with timestamps and experiment_ids (no PHI beyond patient_id_hash).
HIPAA-Safe Experiment Data Handling & Audit Logging
"As a privacy officer, I want PHI-safe planning and a complete audit trail so that our experimentation remains compliant and reviewable."
Description

Enforces HIPAA-compliant data minimization by using de-identified IDs in planning, dashboards, and exports; redacts PHI from analysis outputs; and restricts access with RBAC and least-privilege scopes. Captures an immutable audit log of experiment designs, randomization seeds, parameter changes, interim looks, alerts, and decisions with timestamp, actor, and rationale. Provides exportable audit and pre-analysis plan artifacts to support compliance reviews.

Acceptance Criteria
De-Identified IDs in Planner, Dashboards, and Exports
Given a user with experiments:read opens Power Planner planning, dashboards, or exports for any experiment When the UI renders or a file/API response is produced Then only de-identified patient_uid values are displayed and included, and no PHI fields (name, phone, email, address, DOB, MRN, message content) are present Given a scheduled export is generated When a DLP/PHI scan runs on the payload Then the scan returns zero PHI findings and the export schema contains only whitelisted fields: patient_uid, cohort_id, arm, assignment_ts, event_ts, outcome_flag, and non-PHI metadata Given a user attempts to include a PHI field via custom columns or filters When the request is submitted Then the request is rejected with HTTP 400, a user-facing validation error lists disallowed fields, and the attempt is recorded in the audit log
PHI Redaction in Analysis Outputs and Alerts
Given analysis outputs (reports, charts, alerts, downloadable summaries) are generated When any value originates from PHI-bearing sources (e.g., message bodies, phone numbers, emails) Then those values are redacted using the token "[REDACTED]" prior to persistence, display, or export Given an alert is triggered that references individual events When the alert is delivered via UI, email, or webhook Then it contains only de-identified IDs and aggregated metrics, with no direct or indirect PHI Given a user pastes PHI into a free-text rationale or notes field When the record is saved Then PHI patterns are detected and redacted server-side and the audit entry notes PHI_REDACTED=true
RBAC Least-Privilege Access Controls
Given roles and scopes are configured When a user lacks experiments:export_audit or phi:read scopes Then the user cannot access exports, audit bundles, or any PHI endpoints, receiving HTTP 403, and the denial is logged Given a compliance_officer with audit:read can view audit logs When they access patient-level pages Then they still cannot see PHI unless phi:read is explicitly granted Given access occurs via UI, REST API, and background jobs When permissions are evaluated Then a centralized policy enforces least privilege consistently and automated tests verify coverage for all endpoints
Immutable Audit Log of Experiment Lifecycle
Given an experiment is created, edited, randomized, paused or resumed, an interim look is run, an alert is acknowledged, or a decision is recorded When the action is committed Then an audit entry is written with ISO8601 UTC timestamp, actor_id, action_type, request_id, before and after values, rationale (required on changes and decisions), and experiment_version Given audit storage is append-only When any update or delete to an existing audit entry is attempted Then the operation is blocked with HTTP 403, no mutation occurs, and a tamper-attempt audit entry is added Given a daily integrity job runs When it recomputes the hash chain or merkle root over audit entries Then the computed root matches the stored value; on mismatch an alert is sent to the compliance channel within 5 minutes
Exportable Audit Bundle and Pre-Analysis Plan
Given an authorized user selects Export Audit Bundle for an experiment When the export completes Then a ZIP is produced containing audit.jsonl (newline-delimited JSON of audit entries), pre_analysis_plan.pdf, design_params.csv, integrity.txt (SHA-256 checksums), and README.txt with schema versions Given the audit bundle is scanned for PHI When automated DLP runs Then zero PHI findings are reported and only de-identified IDs appear Given the pre-analysis plan is opened When reviewed Then it includes objective, primary and secondary metrics, alpha and power targets, sequential boundaries and alpha spend, cohort definitions, randomization seed, start date, stopping rules, and a data minimization statement
Randomization Seed and Parameter Change Traceability
Given a randomization seed is set at experiment creation When assignments are simulated using the stored seed and algorithm version Then assignments are reproducible and match the audit assignment entries for the same seed Given a parameter change is attempted after experiment start (e.g., power target, metric definition, cohort membership) When the user submits Then the system requires a change rationale, creates a new experiment_version, records before and after values, and flags the plan as amended in the audit Given an interim look is executed under sequential testing When the look completes Then the audit captures look_index, information_fraction, boundary values, observed statistic, decision (continue or stop for efficacy or futility), and alpha spent
Tamper Evidence and Retention Policy Compliance
Given audit log retention is configured to 6 years by default and is tenant configurable When the retention job runs Then entries are retained until expiration and early deletion requests are rejected with HTTP 403 and audited Given each audit entry participates in a hash chain with a stored daily merkle root When any entry is altered at the storage level Then chain validation fails and a critical alert is dispatched and surfaced in the admin UI within 5 minutes Given an audit bundle is exported When integrity.txt checksums are verified by an external tool Then all file hashes match and the bundle includes the merkle root and an export signature for non-repudiation
Real-time Power Tracking & Alerts
"As an office manager, I want real-time updates and alerts on experiment power so that I can act quickly when it’s time to stop, extend, or adjust a test."
Description

Continuously ingests experiment telemetry to update observed information, effect size estimates, variance, and conditional power, showing progress toward stopping boundaries. Sends in-app and email/Slack alerts when power thresholds are achieved, early-stop criteria are met, or a test risks missing power within the planned duration. Exposes a dashboard widget and API endpoints for status, forecasts, and recommended actions.

Acceptance Criteria
Real-time Telemetry Ingestion & Metric Updates
Given an active experiment with SMS, email, and voice telemetry, When a new event is ingested, Then observed counts, effect size, variance, and conditional power are recalculated within 60 seconds of ingestion. Given multiple cohorts and goals are configured, When metrics update, Then updates occur per cohort and per goal independently and display last-updated timestamps accurate to within 1 second. Given a sustained burst of 200 events per second for 60 seconds, When processing completes, Then no events are lost and backlog is cleared within 2 minutes with computed metrics within 0.1% of an offline batch recomputation. Given an ingestion outage of up to 5 minutes, When services recover, Then backfill completes and metrics reflect all missed events within 10 minutes and the freshness indicator returns to “current”.
Power Threshold Achieved Alerting
Given a configured power threshold for a primary goal (e.g., 80%), When conditional power for any cohort crosses or equals the threshold, Then an in-app alert and notifications to email and Slack are sent within 30 seconds of the crossing. Given an alert is triggered, When it is delivered, Then the payload includes experiment ID, cohort, goal, current effect size with 95% CI, conditional power, look number, and a recommended action string. Given the same threshold remains satisfied, When additional recalculations occur, Then duplicate alerts are suppressed for 12 hours unless power falls below the threshold and later re-crosses it. Given a temporary delivery failure, When retries are attempted, Then up to 3 retries occur with exponential backoff and outcomes are logged per channel.
Early-Stop — Efficacy Boundary Reached
Given a pre-specified sequential design with an efficacy boundary and alpha-spending plan, When the test statistic crosses the efficacy boundary at an interim look, Then the system marks “Recommend Stop for Efficacy” and sends in-app/email/Slack alerts within 30 seconds. Given the recommendation is issued, When the dashboard updates, Then it shows look number, p-value, boundary value, estimated uplift, and projected impact, and locks further enrollment forecasts unless manually overridden by a user with proper permissions. Given an efficacy-stop alert was already issued, When subsequent recalculations at the same look do not change state, Then no additional efficacy alerts are sent. Given the API is queried at /experiments/{id}/status, When the efficacy condition is met, Then stop_recommendation="efficacy" is returned with HTTP 200 and p95 latency ≤ 300 ms.
Early-Stop — Futility Boundary or Low Conditional Power
Given a pre-defined futility boundary or conditional power rule (e.g., CP < 5%), When the rule is met at a look, Then the system marks “Recommend Stop for Futility” and sends alerts within 30 seconds. Given the dashboard renders the recommendation, When it presents rationale, Then it includes current effect estimate, variance, conditional power, remaining sample capacity, and expected absolute benefit if continued. Given a futility alert has been sent, When the state remains unchanged, Then duplicate futility alerts are suppressed for 12 hours. Given the API is queried at /experiments/{id}/status, When the futility condition is met, Then stop_recommendation="futility" and recommended_actions (pause test, extend duration, increase sample size) with rationale text are returned.
Risk of Missing Power Within Planned Duration
Given a planned end date and target power (e.g., 90%), When forecasted power at the planned end date is below target by ≥ 5 percentage points considering current enrollment, variance, and day-of-week seasonality, Then a “Risk: Underpowered” alert is issued and visible in-app and delivered via email/Slack within 30 seconds. Given a risk alert is generated, When recommendations are computed, Then the alert includes extend-by-X-days, increase-daily-sample-by-Y, and narrow-scope options with projected power for each option. Given forecasts are recomputed hourly, When projected power meets or exceeds target for 24 continuous hours, Then the risk alert is automatically cleared and a resolution entry is logged. Given multiple recalculations within a day, When the risk level changes by < 5 percentage points, Then no more than one new risk alert is sent per cohort in a 24-hour window.
Dashboard Widget & API Consistency and Performance
Given an active experiment, When the dashboard widget renders, Then it displays status, latest conditional power, look number, next-look ETA, forecasts, and recommended actions consistent with API responses within ±0.1% for rates and ±0.001 for p-values. Given standard load conditions, When the widget and APIs are accessed, Then widget p95 load time ≤ 500 ms and API p95 latency for /experiments/{id}/power and /experiments/{id}/forecasts ≤ 300 ms with ≥ 99.5% success over 30 days. Given a recommendation changes, When recomputation completes, Then both UI and API reflect the change within 60 seconds. Given a cohort filter is selected in the widget, When applied, Then the displayed metrics and underlying API queries are scoped to the selected cohort.
Alert Audit Trail & Recipient Delivery
Given any alert is triggered, When it is recorded, Then an immutable audit entry stores UTC timestamp, triggering rule, metric values, recipients, delivery attempts, and outcomes. Given a user opens alert history for an experiment, When filters by type, cohort, and date range are applied, Then results render within 2 seconds p95 for ≤ 100 records and can be exported to CSV; the API /experiments/{id}/alerts returns equivalent results with pagination. Given HIPAA constraints, When alert content and logs are generated, Then no PHI is included; only experiment metadata and aggregated metrics are present. Given retention policies, When the system stores audit records, Then records are retained for 24 months and remain queryable for the full retention period.

Traffic Shaper

Let the system adaptively steer traffic to better-performing variants while preserving statistical validity. Traffic Shaper uses guardrailed multi-armed bandit logic to boost promising branches, protects minimum volume for each variant and cohort, and caps exposure for sensitive segments. Faster learning, fewer bad sends, and higher confirmation lift—automatically.

Requirements

Guardrailed Bandit Allocation Engine
"As a campaign administrator, I want the system to automatically shift traffic toward better-performing reminder variants while preserving minimum exposure and caps per cohort so that we improve confirmations without compromising statistical validity or patient safeguards."
Description

Implements an adaptive multi-armed bandit policy (e.g., Thompson Sampling) to automatically allocate SMS, email, and voice reminder traffic to better-performing variants while enforcing strict guardrails. Guardrails include per-variant and per-cohort minimum sample floors, exposure caps for sensitive segments, and exploration floors to preserve learning. Supports cold start with equal split and warm start using cohort-specific historical priors. Allocation updates run in near real time with configurable batching windows and delay handling for late outcomes (e.g., confirmations within 48 hours). Includes sequential monitoring controls and stopping rules to maintain statistical validity and prevent premature convergence. Integrates with SmileCue’s campaign engine and template branching, operating transparently across channels and appointment types.

Acceptance Criteria
Cold Start Equal Split per Cohort
Given a new campaign-cohort with no historical priors for the cohort When the allocation engine runs for the first 200 eligible sends in that cohort Then each active variant receives traffic within ±2 percentage points of an equal split And the equal split respects channel and appointment-type scoping with no cross-cohort leakage And the allocation decision and percentages are logged per batch with timestamps and cohort identifiers
Warm Start Using Cohort-Specific Priors
Given historical outcomes exist for the same cohort and variant definitions with at least 30 outcomes per variant within the last 90 days When the campaign starts and the engine initializes posteriors Then priors are loaded from the cohort’s historical data and initial allocation reflects Thompson Sampling using those priors And variants with fewer than 30 historical outcomes default to equal-split priors for that cohort And the priors’ source window and counts are recorded in the audit log
Exploration Floor and Minimum Sample Floors per Cohort
Given exploration_floor = 5% per active variant per cohort and min_sample_per_variant_per_cohort = 30 (both configurable) When allocation updates are computed for a cohort Then no active variant’s allocation drops below 5% until it has received at least 30 sends in that cohort And if cohort volume is low, at least 1 send per variant per batch is preserved until the minimum sample is met And floors are enforced independently per cohort, channel, and appointment type
Sensitive Segment Exposure Caps
Given a cohort is labeled sensitive with per-variant exposure_cap = 20% per rolling 7-day window (configurable) When allocating traffic in that cohort Then no experimental variant exceeds 20% of total eligible sends within the window; the control variant is exempt from this cap And if a cap is reached, excess traffic is reallocated proportionally to other eligible variants while respecting their floors and other caps And cap calculations and reallocation events are recorded in the audit log
Near Real-Time Updates and Late Outcome Handling
Given batch_window = 5 minutes (configurable) and late_outcome_window = 48 hours When outcomes arrive, including confirmations received within 48 hours of send Then posterior updates incorporate each outcome within 5 minutes of receipt and affect the next allocation batch And 95% of allocation decisions are published within 2× the configured batch window after window close And outcomes arriving after 48 hours are excluded from learning and logged as late beyond window
Sequential Monitoring and Stopping Rules
Given min_decision_sample = 200 outcomes per variant per cohort (configurable) and a stop_threshold of 99% posterior probability that a variant is worse than the current best for two consecutive batches When a variant meets both the minimum sample and the stop threshold criteria Then the engine marks that variant as stopped in that cohort and sets its allocation to 0% And no variant is stopped before min_decision_sample is met And each stop decision logs posterior metrics, thresholds, and timestamps
Cross-Channel Campaign Integration and Template Branching
Given a live campaign with SMS, email, and voice variants under a template branch and an active cohort When the engine emits allocation percentages for that cohort Then the campaign engine applies those percentages at send-time across channels and appointment types exactly as provided And observed branch selection in send logs matches the emitted percentages within ±3 percentage points over the next 200 eligible sends for the cohort And no allocation intended for one cohort or channel is applied to another
Cohort & Sensitive Segment Constraints Configuration
"As an office manager, I want to configure minimum volumes and exposure caps for specific patient cohorts and sensitive segments so that the Traffic Shaper respects practice policy and patient safety while learning."
Description

Provides UI and API to define cohorts (e.g., practice, provider, appointment type, language, age band) and mark sensitive segments that require exposure caps and stricter thresholds. Enables configuration of per-cohort minimum sample sizes, exploration floors, daily/weekly send limits, and per-variant caps. Validates configurations for conflicts and infeasible settings and surfaces clear error messages. Supports environment-scoped defaults and campaign-level overrides. Changes are versioned, auditable, and safely rolled out via feature flags.

Acceptance Criteria
Cohort Creation via UI and API
Given a user with TS_CONFIG_WRITE permission When they create a cohort via the UI with practice_id=pr_123, provider_id=dr_456, appointment_type=prophy, language=en, age_band=18-34 Then the cohort is persisted with id=UUIDv4 and created_at/updated_at timestamps and the UI shows a success confirmation And the cohort appears in the UI list and is filterable by any provided attribute within 10 seconds Given the same payload via POST /v1/traffic-shaper/cohorts When the request body matches the published schema Then the API responds 201 Created with a Location header And GET {Location} returns the saved cohort with exact field values
Sensitive Segment Flag and Exposure Cap Configuration
Given an existing cohort When Sensitive Segment is set to true with exposure_cap_percent=20 and min_winning_confidence=95 Then PATCH /v1/traffic-shaper/cohorts/{id}/sensitivity returns 200 and GET returns the saved values And the Allocation Preview endpoint GET /v1/traffic-shaper/allocations/preview?cohort_id={id}&population=1000 proposes no variant exposure above 20% for that cohort And the UI displays a warning if user inputs would violate the exposure cap before save
Per-Cohort Minimum Sample Size and Exploration Floor
Given a cohort with 3 active variants When min_sample_size=300 and exploration_floor_percent=10 are saved Then the save succeeds (200) and GET effective config returns those values And until total sends in the cohort reach 300, each variant's share stays >=10% (preview/runtime); attempts to set a lower share are blocked with 409 exploration_floor_violation And validation fails with 422 if exploration_floor_percent * variants_count > 100
Daily and Weekly Send Limits per Cohort
Given practice timezone America/Chicago and an existing cohort When daily_send_limit=500 and weekly_send_limit=2500 are configured Then allocation requests that would exceed 500 sends since 00:00 local return 429 daily_limit_exceeded with retry_after seconds to next midnight And allocation requests that would exceed 2500 sends since Monday 00:00 local return 429 weekly_limit_exceeded with retry_after seconds to next Monday 00:00 And GET /v1/traffic-shaper/cohorts/{id}/limits returns used and remaining counts for the current day and week
Per-Variant Caps Within a Cohort
Given a cohort with variants A, B, C When caps are set to A=60, B=30, C=25 (percent) Then the save fails with 422 SUM_OF_CAPS_EXCEEDS_100 and message "Sum of per-variant caps (115%) exceeds 100%" Given caps A=50, B=30, C=20 and exploration_floor_percent=10 When the config is saved Then save succeeds and the allocation engine enforces that each variant's rolling 7-day exposure within the cohort does not exceed its cap; attempts to allocate beyond cap return 409 variant_cap_exceeded with offending variant id and window metrics
Configuration Validation and Clear Error Messages
Given min_sample_size=1000 and weekly_send_limit=800 When saving the config Then the API returns 422 MIN_SAMPLE_GT_WEEKLY_LIMIT with field=min_sample_size and message "Minimum sample size (1000) cannot exceed weekly send limit (800)" Given exploration_floor_percent=25 and variants_count=5 When saving the config Then the API returns 422 EXPLORATION_FLOOR_TOTAL_GT_100 with message "Exploration floors total 125% across 5 variants; reduce floor or variant count" Given any variant_cap < exploration_floor_percent When saving the config Then the API returns 422 VARIANT_CAP_LT_EXPLORATION_FLOOR with the affected variant ids And all validation errors are localized (en, es) and mapped to the exact UI form controls via aria-describedby
Environment Defaults, Campaign Overrides, Versioning, Audit, and Feature-Flagged Rollout
Given environment defaults exist for prod When a campaign defines overrides for min_sample_size and daily_send_limit Then GET /v1/traffic-shaper/effective-config?campaign_id=cmp_123 resolves values using precedence campaign_override > env_default > system_default and includes source metadata per field When any config is changed Then a new immutable version (monotonic integer) is created; GET /v1/traffic-shaper/cohorts/{id}/versions lists history with actor_id, timestamp, and field-level diff; reverting creates a new version restoring prior values Given feature flag traffic_shaper_config_v2 is off for prod When a change is saved Then the API returns 202 with status=staged and no changes affect live allocations When the flag is enabled for 10% of practices Then only those practices use the new effective config; disabling the flag rolls back within 60 seconds
Statistical Validity & Performance Reporting
"As a practice owner, I want clear reports on why traffic is being shifted and the statistical confidence behind it so that I can trust the system’s decisions and communicate results to my team."
Description

Delivers a reporting layer that explains allocation decisions and learning progress, including variant lifts, credible intervals/confidence bounds, expected regret, and guardrail status per cohort and channel. Surfaces primary metric (confirmation within 48 hours) and secondary metrics (opt-outs, reschedules, undeliverables, complaint rate) with multiple-comparison controls. Provides timelines, reason codes for pauses/adjustments, and exportable CSV/JSON. Distinguishes learning vs. steady-state phases and highlights when minimum sample requirements are unmet or when caps bind allocation.

Acceptance Criteria
Cohort/Channel Allocation Explanation & Variant Lift
Given a user views the Traffic Shaper report for a selected practice, cohort, channel, and date range When the user selects a variant in the variants table or chart Then the report displays allocation percentage, variant lift on the primary metric (confirmation within 48 hours), 95% interval bounds (confidence or credible, as configured), expected regret, and sample sizes (sends, confirmations) for the same window And the statistical method label and parameters are shown (e.g., “Bayesian beta-binomial, 95% CrI” or “Frequentist Wilson, 95% CI”) And allocation percentages across all active variants in the cohort/channel sum to 100% ± 0.1% And numeric values include units and consistent rounding (percentages to 1 decimal place; rates per 1,000 where applicable) And a “Last updated” timestamp is visible and within the configured freshness SLA for reporting
Multiple-Comparison Control on Primary and Secondary Metrics
Given multiple variants and cohorts are active in the selected date range When the user views primary and secondary metrics in the report Then the report displays the configured multiple-comparison control method and parameters (e.g., BH-FDR q=0.10 or hierarchical Bayesian) And adjusted significance or posterior probability values are shown per variant for the primary metric And a variant is flagged as “Significant” only when the adjusted control threshold is met And secondary metrics (opt-outs, reschedules, undeliverables, complaint rate) display adjusted results or pool-sharing status consistent with the chosen method And the export includes the adjusted values and method metadata for reproducibility
Guardrail Status, Pauses, and Caps Visibility
Given guardrail thresholds are configured for opt-outs, complaint rate, and undeliverables When any variant/cohort breaches a guardrail in the selected date range Then the variant displays status “Paused” or “Capped” with a reason code that references the specific guardrail And the UI shows a badge (e.g., “Guardrail breached”) with the observed metric value and threshold And the allocation history shows the change attributed to the guardrail event with timestamp within the configured reaction SLA And if a segment exposure cap binds, the report highlights “Cap binding” and displays the cap value and the realized allocation And no variant’s allocation falls below the configured per-variant minimum traffic floor unless paused by a guardrail
Learning vs Steady-State Phase Indicators & Minimum Samples
Given minimum sample requirements and stability criteria are configured per cohort/variant When the user opens the report for a cohort/channel Then the current phase is labeled as “Learning” or “Steady-state” based on the configured rules And if any variant/segment is below minimum sample, a banner lists the underpowered entities and the additional sample required to meet the minimums And in Learning, the next evaluation time and decision cadence are displayed And in Steady-state, the freeze date/time and last decision rationale are displayed And allocation adjustments are disabled in Steady-state unless a guardrail breach or manual override occurs, both recorded with reason codes
Timeline of Allocation Decisions with Reason Codes
Given the user opens the Allocation Timeline view for a selected date range When allocation changes, pauses, caps, or method/config changes occurred within the range Then each entry shows ISO-8601 timestamp in the practice’s timezone, actor (system or user), reason code (e.g., MIN_SAMPLE, CAP_BINDING, GUARDRAIL_BREACH, PERFORMANCE_DRIFT, MANUAL_OVERRIDE), before/after allocations, affected cohorts, variants, and channels And entries are filterable by event type, cohort, variant, channel, and reason code And the timeline is chronologically ordered and paginated without gaps or duplicates And clicking an entry deep-links to the corresponding report state
CSV/JSON Export with Validated Schema and Parity
Given the user exports reporting data via UI or API for a selected filter set and date range When the export is generated in CSV and JSON formats Then both formats include the documented schema: date, practice_id, cohort_id, cohort_name, channel, variant_id, variant_name, sends, confirmations_48h, opt_outs, reschedules, undeliverables, complaint_rate, allocation_pct, lift_primary_pct_pts, interval_lower, interval_upper, expected_regret, method_label, phase, guardrail_status, cap_status, reason_code_latest And row counts and aggregate totals in the export match the on-screen totals for the same filters And CSV uses UTF-8 and RFC 4180 quoting; JSON is a UTF-8 array of objects with ISO-8601 dates And exports include a header with generation timestamp, method, and control parameters And the API returns HTTP 200 with appropriate content-type and pagination metadata when applicable
Data Freshness and Rendering Performance for Reports
Given the reporting views are opened for up to the last 30 days across multiple cohorts and variants When new events (sends, confirmations, opt-outs, undeliverables) occur Then the report reflects the changes within the configured freshness SLA and updates the “Last updated” timestamp And visualizations and tables render within the configured p95 render time SLO for the selected scope And all timestamps are shown in the practice’s timezone with the timezone abbreviation/offset indicated And no client-side errors occur in console during normal navigation and filter changes
Safety Guardrails & Anomaly Auto-Pause
"As a compliance-minded administrator, I want automatic detection and pausing of risky variants or segments so that patients are protected and our practice avoids deliverability or regulatory issues."
Description

Continuously monitors safety and deliverability signals (opt-out spikes, complaint rates, undeliverables by carrier, sudden no-show increases) at variant, cohort, and channel levels. Automatically triggers protective actions—pause variant, revert to safest baseline, or return to equal split—when thresholds or trend detectors fire. Sends real-time alerts to admins, logs reason codes, and supports manual override with justification. Integrates with consent management, frequency caps, and carrier rate limits to prevent over-sending and ensure compliant operations.

Acceptance Criteria
Auto-Pause on Opt-Out Spike (Variant × Cohort × SMS)
Given a running experiment for a specific variant V, cohort C, and channel SMS And the 14-day baseline opt-out rate for (V,C,SMS) is b And rolling 60-minute sends N60 for (V,C,SMS) is ≥ 200 When the rolling 60-minute opt-out rate r60 ≥ max(1.5%, 3 × b) Then pause variant V for cohort C on SMS within 2 minutes and set its allocation to 0% And stop further sends for (V,C,SMS) immediately And log an audit entry with reason_code=OPT_OUT_SPIKE, b, r60, N60, timestamp, rule_id, and scope And send real-time alerts to registered admins via Email and Slack including scope, observed_value, threshold, and link_to_logs And expose a Resume control gated by manual override policy
Carrier-Specific Undeliverable Spike Guardrail (SMS)
Given sending to carrier K on SMS across one or more variants/cohorts And the last 30-minute sends N30 to carrier K is ≥ 100 And the 7-day baseline undeliverable rate to carrier K is b7 When the rolling 30-minute undeliverable rate r30 ≥ max(5%, 2 × b7) Then auto-pause sends to carrier K for all affected variants/cohorts within 2 minutes And reallocate eligible traffic to the safest baseline variant where policy allows And create an audit log with reason_code=CARRIER_UNDELIVERABLE_SPIKE, K, r30, b7, N30, timestamp, rule_id And alert admins with severity=High and remediation guidance And auto-recheck every 15 minutes and auto-resume when r30 < max(2%, 1.2 × b7) for 2 consecutive windows with N30 ≥ 100, logging the resume event
Email Complaint Threshold Revert to Baseline
Given email sending for a specific variant V and cohort C And 24-hour email sends N24 for (V,C,Email) is ≥ 1,000 When the 24-hour complaint rate (spam reports) r24 ≥ 0.1% Then set allocation of V to 0% for (C,Email) and route 100% of (C,Email) to the designated safest_baseline variant within 5 minutes And lock variant V from email traffic for 24 hours unless manually overridden per policy And create an audit log with reason_code=EMAIL_COMPLAINT_THRESHOLD, r24, threshold=0.1%, N24, timestamp, rule_id And notify admins immediately with incident severity=High including scope and impact
Sudden No-Show Increase Triggers Equal Split (Voice)
Given appointment outcome tracking for cohort C on channel Voice with variant V And the 14-day baseline no-show rate for (C,Voice) is b14 And the last 7-day completed appointments M7 for (V,C,Voice) is ≥ 100 When the current 7-day no-show rate r7 ≥ 1.5 × b14 and a two-proportion z-test vs baseline yields p < 0.05 Then revert allocation to equal split across all safe variants for (C,Voice) within 10 minutes and disable bandit boosting And maintain equal split until r7 < 1.1 × b14 for 2 consecutive days, then re-enable learning And log reason_code=NO_SHOW_INCREASE with r7, b14, p_value, M7, timestamp, rule_id And alert admins with summary and next review checkpoint
Real-Time Admin Alerts and Audit Logging
Given any protective action is triggered (pause, revert_baseline, equal_split) When the action executes Then send alerts to all registered admins within 60 seconds via Email and Slack And the alert includes: action_type, scope (variant/cohort/channel/carrier), triggering_metric, observed_value, threshold, sample_size, timestamp, rule_id, and link_to_logs And create an immutable audit log entry with the same fields plus actor=SYSTEM and correlation_id And ensure alerts and logs contain no PHI and comply with HIPAA policies And make the log entry queryable in the admin UI within 2 minutes
Manual Override with Justification and Expiry
Given a guardrail-induced pause or reallocation is active for scope S And an Admin with role in {Owner, Compliance} initiates an override When the Admin provides a justification of ≥ 15 characters and an expiry between 1 hour and 72 hours Then apply the override within 2 minutes (resume or adjust allocations as specified) And record an audit entry with actor, justification, expiry, before/after allocations, scope S, timestamp, rule_id, reason_code=MANUAL_OVERRIDE And display an in-product banner indicating override active with expiry countdown And automatically re-enforce guardrails upon expiry if the triggering condition persists And block overrides that would violate consent, frequency caps, or carrier rate limits, returning validation errors
Consent, Frequency Caps, and Carrier Rate Limits Enforced During Mitigations
Given the system must execute a protective action or reallocate traffic When calculating sends to any patient or carrier/domain Then do not send to users without active consent per channel And enforce configured frequency caps (e.g., per-user ≤ 1 SMS/24h, ≤ 2 Emails/24h) and global caps And respect carrier/domain rate limits; throttle or queue sends as needed And if the mitigation would breach any constraint, do not execute; maintain current allocations, alert admins with reason_code=CONSTRAINT_BLOCK, and log the failure with details
HIPAA-Compliant Data Handling & Decision Audit Log
"As a security officer, I want every allocation decision and its inputs auditable under HIPAA controls so that we can demonstrate compliant, traceable decision-making during audits."
Description

Ensures the bandit engine operates under HIPAA requirements by minimizing use of PHI, using de-identified cohort attributes, encrypting data in transit and at rest, and enforcing least-privilege access. Records an immutable audit log of every allocation decision with timestamp, inputs (cohort, constraints, observed outcomes), model version, and resulting action. Supports retention policies, export for compliance reviews, and BAA-aligned controls. Provides redaction for operational views while preserving full detail in secure audit storage.

Acceptance Criteria
PHI-Minimized Bandit Inputs
Given the bandit engine prepares features for allocation, When building the input vector, Then only allow-listed de-identified cohort attributes are accessible and persisted, and any attempt to reference disallowed PHI fields is blocked and logged with reason=PHI_POLICY_VIOLATION. Given a request includes name, full DOB, full address, email, or full phone, When the allocation API is called, Then the service rejects the payload with HTTP 400 and error code=PHI_NOT_ALLOWED, and the payload is not stored. Given CI enforcement is running, When the feature schema is validated, Then the schema exactly matches the allow-list and the build fails if new fields are added without an approved policy change.
End-to-End Encryption Controls
Given any network connection carrying patient- or decision-related data, When a connection is established, Then TLS 1.2+ with AEAD ciphers and forward secrecy is required, and plaintext connections are refused and logged. Given audit and operational data stores, When data is written at rest, Then AES-256-GCM encryption with HSM-backed KMS CMKs is applied, using distinct CMKs for audit vs operational stores. Given key rotation is performed, When a rotation event occurs, Then new writes use the rotated key, historical data remains decryptable, service availability is unaffected, and the rotation is logged with actor, time, and key IDs; automated checks confirm rotation occurs at least every 90 days.
Least-Privilege RBAC and Access Audit
Given roles [FrontOffice, Compliance, Engineer, System] exist, When a user requests an audit log export, Then only the Compliance role receives HTTP 200 and others receive HTTP 403 with event=AUDIT_ACCESS_DENIED. Given the FrontOffice role, When accessing operational views, Then only minimal contact metadata is visible and all other PHI fields are redacted; raw audit records are inaccessible. Given a break-glass access request, When elevation is initiated, Then MFA, justification text, and a time-bound window (≤60 minutes) are required, and all actions during elevation are logged and auto-revoked on expiry.
Immutable Decision Audit Log Contents and Integrity
Given an allocation decision occurs, When persisting the audit record, Then an atomic append-only write stores: decision_id, request_id, timestamp_utc_ms, patient_surrogate_id, cohort_id, segment_id, variant_id, constraints_applied, inputs_snapshot, model_version, hyperparameters_hash, exploration_rate, scores, selected_action, writer_service_version. Given audit storage is configured, When records are retrieved, Then each record’s SHA-256 checksum and hash-chain pointer validate; any verification failure raises an alert and blocks export. Given a decision_id, When a reproducibility job replays the decision using the logged model_version and inputs_snapshot, Then the engine produces the same selected_action and scores.
Data Retention and Deletion Policy Enforcement
Given operational views store PHI and message bodies, When record age exceeds 30 days, Then operational stores purge PHI fields and message bodies, retaining only pseudonymous linkage and delivery/confirmation status. Given immutable audit logs, When record age reaches 6 years, Then records become eligible and are purged within 30 days unless under legal hold; deletion before retention lock expiry is blocked and logged. Given a legal hold is active, When retention jobs run, Then affected records are skipped, and a signed hold receipt (case_id, actor, timestamps) is appended to the compliance ledger.
Compliance Export with Cryptographic Assurance
Given a Compliance user specifies date range and filters (cohort, campaign, segment), When requesting an export, Then the system produces a package (JSONL or CSV) of audit fields without PHI plus a data dictionary and model manifest. Given an export is generated, When delivered, Then the file is encrypted (AES-256) with a unique passphrase delivered out-of-band, accessible via a single-use link that expires in ≤24 hours, and all access is logged to SIEM. Given an export file, When verification runs, Then the detached digital signature validates (integrity and signer), and the package is rejected if signature verification fails.
Redacted Operational Views with Traceability to Secure Audit
Given an operational user views decision history, When records render, Then PHI (name, full DOB, full address, email) is omitted, phone is masked to last 4 digits, and patient_surrogate_id is shown for support traceability. Given a record is opened, When "View in Audit" is invoked by a Compliance user, Then the immutable audit entry opens by decision_id; unauthorized roles receive HTTP 403 and no audit data is leaked. Given operational APIs return payloads, When contract tests execute, Then responses comply with redaction rules across all endpoints and fields.
Offline Simulation & Policy Validation Harness
"As a data analyst, I want to simulate Traffic Shaper policies on historical data so that we can choose settings that learn quickly without sacrificing safety or validity."
Description

Adds a sandbox to replay historical campaigns and synthetic cohorts to evaluate candidate bandit policies and guardrail settings before production. Supports counterfactual evaluation, A/A tests to verify false positive rates, and power calculators to estimate minimum samples and expected time-to-confidence. Produces policy comparison reports (e.g., regret, lift, exposure fairness) and generates safe default settings for new campaigns. Integrates with feature flags for staged rollouts and can backtest across SMS, email, and voice channels.

Acceptance Criteria
Historical Campaign Replay Fidelity
Given a historical dataset of at least 100 campaigns across SMS, email, and voice with baseline policy annotations When the harness replays the campaigns using the baseline policy Then event ordering match rate is ≥ 99.5% and timestamp deviation is ≤ 1s median and ≤ 5s p95 per campaign And aggregate metrics per campaign and per channel (sends, deliveries, confirmations, opt-outs) differ by ≤ 1.0% absolute from the original And no PHI/PII is present in any generated artifact as verified by the redaction scanner (0 findings)
Counterfactual Evaluation Correctness (IPW/DR)
Given logged action propensities (> 0) and outcomes for historical or synthetic cohorts When evaluating a candidate policy using inverse propensity weighting and doubly robust estimators Then on synthetic data with known ground truth, absolute bias of estimated lift and regret is ≤ 1.0% averaged across 1000 simulations And empirical 95% confidence interval coverage is between 93% and 97% And weight clipping (w_max) and propensity floors (ε) are applied as configured, with records having propensity < 0.01 flagged and excluded with counts reported And results are reproducible given a fixed random seed
A/A False Positive Rate Control
Given two or more identical arms with identical reward distributions and sequential testing guardrails at α = 0.05 When running 1000 A/A replays per channel and cohort configuration Then the proportion of runs declaring a winner is ≤ 6% with the 95% binomial CI including 5% And early-stop triggers occur in ≤ 6% of runs And no policy recommendation is emitted for A/A runs And all runs persist seeds, decision boundaries, and stopping times to the audit log
Power and Sample Size Calculator Accuracy
Given inputs MDE, baseline conversion rate, α, β, historical arrival rates, and campaign duration When the calculator computes required sample size and expected time-to-confidence per channel and cohort Then required sample size is within ±5% of closed-form or Monte Carlo benchmarks across at least 50 varied scenarios And expected time-to-confidence is within ±10% of replay-based estimates using the same inputs And infeasible settings (e.g., time-to-confidence exceeds campaign duration) are flagged with an explicit warning and remediation suggestions And outputs include per-channel/cohort breakdowns and assumptions used
Exposure Guardrails and Caps Enforcement in Simulation
Given configured minimum traffic per arm m%, exploration floor ε, per-cohort minimum n events, and sensitive segment exposure cap c% When the simulator allocates traffic adaptively over the replay horizon Then after warmup, each arm receives ≥ (m% − 0.5%) of traffic per cohort per day And no sensitive segment exceeds (c% + 0.5%) cumulative exposure And cohort minimum n events are satisfied in ≥ 99% of allocation windows And any violation is logged with timestamp, cohort, arm, configured thresholds, and observed values
Policy Comparison Reports and Safe Default Generation
Given K candidate policies and a defined baseline When the harness completes replay and counterfactual evaluation Then it produces a versioned report with per-policy metrics: cumulative regret, lift vs baseline, time-to-95% confidence, exposure fairness (Gini), and per-channel/cohort breakdowns And exports JSON and HTML artifacts with identical content hashes for reproducible runs using a fixed seed And selects a safe default policy and guardrail settings that maximize expected lift subject to constraints (false positive rate ≤ 5%, sensitive segment cap c respected, min-traffic floors met) And outputs the selected defaults as signed YAML with rationale fields (top drivers, constraint checks) in under 10 minutes for datasets up to 5M events
Feature Flags and Staged Rollout Integration
Given valid credentials for the feature flag service and environment mappings for staging and production When a user triggers Dry Run Then candidate policy configurations are created behind disabled flags in both environments with no traffic impact When a user triggers Stage Rollout Then flags are enabled in staging only, targeting the specified cohorts and channels, with exposure capped as configured When a user triggers Rollback Then all related flags are disabled within 60 seconds and prior states are restored And all actions are audit-logged with user, timestamp, environment, and diff of flag states

Cohort Carver

Auto-builds the right segments for clean insights: appointment type, provider, location, risk tier, language/age, guardian involvement, and more. Cohort Carver enforces fair splits, excludes tiny cohorts from biasing results, and tags each result with context. You see exactly what works for whom—then roll out with precision.

Requirements

Unified Patient & Appointment Attribute Model
"As a data-minded office manager, I want patient and appointment attributes standardized so that I can create accurate cohorts without manual cleanup."
Description

Standardize and enrich patient and appointment data to power accurate cohorting. Ingest attributes from SmileCue and connected practice systems (appointment type, provider, location, risk tier, language, age band, guardian link, insurance type, recall status, preferred channel, consent status, last confirmation behavior, no-show history) into a normalized schema with consistent IDs. Perform validation, deduplication, derivations (e.g., age bands, first-time patient, pediatric guardian involvement), and field-level sensitivity tagging for PHI. Support incremental updates, late-arriving data handling, and data freshness SLAs. Provide a data dictionary and attribute versioning to ensure analyses remain comparable over time. Expected outcome: reliable, complete inputs for segmentation and unbiased insights.

Acceptance Criteria
Normalized Schema, Stable IDs, and Standardized Enumerations
Given patient and appointment records from SmileCue and connected practice systems When the ingestion and normalization job executes Then 100% of required fields [patient_id, appointment_id, provider_id, appointment_type, location_id, appointment_datetime, source_system] are populated per data dictionary And appointment_type, insurance_type, risk_tier, language, preferred_channel, consent_status conform to the controlled vocabularies defined in the data dictionary (invalid values are rejected or mapped to 'UNKNOWN' with reason logged) And patient_id and appointment_id are stable, unique, and consistent across loads (no changes for the same source keys; collision rate = 0) And cross-source records that refer to the same entity resolve to a single canonical ID with a maintained source_key lineage And <0.5% of daily records are quarantined due to schema/enumeration errors; all quarantined records have actionable error codes
Data Validation, Integrity, and Deduplication
Given normalized tables patient and appointment When validation runs post-load Then referential integrity holds (every appointment.patient_id exists in patient) And uniqueness holds (patient_id and appointment_id are unique keys) And duplicates based on match rules [name+DOB+phone OR source_key exact match] are merged; surviving record selected by latest updated_at; lineage preserved And post-dedup duplicate rate <= 0.1% of total records for the day And validation summary is written with counts for loaded, deduplicated, quarantined, and merged records
Derived Attributes: Age Bands, First-Time Patient, Guardian Involvement
Given patient DOB and appointment history When derivation runs Then age is computed as of appointment_datetime; age_band is assigned as one of [0-5, 6-12, 13-17, 18-34, 35-49, 50-64, 65+] And first_time_patient = true if no completed appointment exists prior to the current appointment for the same practice_id; else false And guardian_involved = true if age < 18 and guardian_link exists; else false And derivation is deterministic and idempotent across re-runs (no change for the same inputs) And unit fixtures covering boundary ages (5,6,12,13,17,18,34,35,49,50,64,65) and history cases all pass
Field-Level PHI Sensitivity Tagging
Given the attribute catalog When sensitivity tags are applied Then 100% of attributes have a sensitivity_tag in {PHI, PII, Sensitive, NonSensitive} And direct identifiers and contact fields [full_name, phone, email, address, DOB, insurance_member_id] are tagged PHI And quasi-identifiers [zip3, language, age_band] are tagged Sensitive And sensitivity_tag is stored with column metadata and exposed in the data dictionary And pipelines prevent export of PHI-tagged fields to non-secure sinks; any attempted export is blocked and logged
Incremental Loads and Late-Arriving Data Handling
Given change streams or updated_at watermarks from sources When an incremental load executes Then only new or changed records since the last successful watermark are upserted (idempotent on re-run) And late-arriving events up to 30 days old are applied correctly, updating derived fields and histories And the watermark advances atomically on successful completion and is unchanged on failure And job restart from last successful checkpoint yields identical table state
Data Freshness SLA and Monitoring
Given production load schedules When source systems emit changes Then 99% of changes are reflected in the unified model within 30 minutes during 7am–7pm local practice time, and within 60 minutes off-hours And freshness, lag, and error rates are monitored with dashboards and alerts And an alert is triggered within 5 minutes when SLA breach is projected or occurs
Data Dictionary and Attribute Versioning
Given the need for stable analytics over time When an attribute definition changes (type, semantics, or allowed values) Then a new attribute_version is created; prior version remains queryable for ≥90 days And the data dictionary exposes name, definition, allowed values, sensitivity_tag, lineage, and version for each attribute And breaking changes require explicit migration entries and release notes; analyses pinned to a version continue to return comparable results And automated tests verify both current and previous versions resolve correctly in queries
Cohort Rule Builder & Saved Templates
"As a hygienist lead, I want an easy way to define and reuse patient cohorts so that I can quickly target reminders tailored to each group."
Description

Deliver a visual, no-code builder to define cohorts using nested AND/OR conditions across demographic, behavioral, and operational attributes (e.g., appointment type, risk tier, guardian presence, confirmed within 24 hours, reschedule intent). Support relative time windows, exclusions, computed fields (first-time patient, recall due), and preview counts with masked sample records. Allow saving, versioning, and sharing of cohort templates across locations, with permission-aware access. Validate rules for syntax and attribute availability, and provide instant feedback on cohort size and coverage before saving. Integrate with SmileCue’s scheduling and messaging modules to ensure cohorts are immediately actionable.

Acceptance Criteria
Nested AND/OR Rule Construction
Given a user opens the Cohort Rule Builder When they create grouped conditions up to 5 nested levels combining AND and OR across supported attributes (appointment type, provider, location, risk tier, guardian presence, language, age, confirmation within 24 hours, reschedule intent) Then the expression renders with correct grouping and operator precedence And the UI prevents creating empty groups or dangling operators And toggling any operator or group recalculates the rule without syntax errors And the generated query preview matches the visual rule 1:1
Relative Time Windows Support
Given the attribute picker includes date/time fields When a user selects relative operators (last N days/weeks/months, next N days/weeks/months, between A and B days ago) Then the builder evaluates using the practice’s timezone And "last N days" includes today from 00:00 local through now; "next N days" excludes today and includes the next N calendar days And boundary values are inclusive And invalid inputs (negative N, A > B) are blocked with inline error messaging and disabled save/action buttons
Exclusions and Attribute Availability Validation
Given a user adds NOT conditions and exclusion groups When an attribute is unavailable for the selected locations or data scope Then the condition is flagged with a clear inline error naming the missing attribute And save and action buttons remain disabled until all errors are resolved And removing or replacing the invalid attribute clears the error state And saved templates cannot contain unavailable attributes
Computed Fields: First-Time Patient and Recall Due
Given computed fields are available in the attribute list When a user filters by "First-time patient = true/false" and "Recall due within next N days" Then "First-time patient" is computed as no completed appointments before the index date And "Recall due" is computed from last completed hygiene appointment plus configured recall interval And preview counts match expected outcomes against seeded test data And inline help surfaces these definitions on hover/click
Real-time Preview Counts and Masked Sample Records
Given a syntactically valid rule When the user pauses typing for 300 ms or changes any condition Then the preview count updates within 2 seconds for datasets up to 100k patients And the sample panel displays 10 masked records with no full names, full phone numbers, full emails, or MRNs And dates are shown as month and year only and ages as whole years; locations/providers shown as codes/initials And a "Data masked" indicator is visible
Template Save, Versioning, Sharing, and Rollback
Given a valid rule and a unique template name within the organization When the user clicks Save Then version 1 is created with immutable rule JSON, creator, timestamp, and change summary And the Owner sets sharing scope (all or selected locations) and permissions (Owner/Editor/Viewer) Then only authorized users see and can act on the template per their role And subsequent edits auto-increment the version and append a changelog entry And rollback promotes a prior version without altering history And all save/share/permission events are captured in the audit log
Immediate Actionability in Scheduling and Messaging
Given a saved template When the user opens Messaging or Scheduling Then the template is searchable and selectable within 60 seconds And launching a campaign or schedule with the template yields a target count equal to the builder’s latest preview ±1% And users lacking location permissions cannot launch actions with that template And cohort tags/context carry into the action creation flow
Fair Split & Minimum Sample Enforcement
"As a practice owner, I want the system to prevent misleading small-sample insights so that decisions are based on statistically reliable comparisons."
Description

Enforce statistically sound cohort comparisons by auto-balancing across key covariates (e.g., provider, location, risk tier) and excluding tiny cohorts that fall below configurable thresholds. Perform power checks and minimum detectable effect estimations to determine whether observed lifts are reliable. Surface guardrail warnings and prevent publishing insights or rollouts when thresholds aren’t met, with optional override requiring justification and audit capture. Output includes effective sample size, coverage, balancing method, exclusions applied, and confidence indicators to reduce bias and confounding in reported results.

Acceptance Criteria
Fair Split Across Key Covariates
- Given a cohort comparison with provider, location, and risk tier selected as balancing covariates, When the split is generated, Then the absolute standardized mean difference (SMD) per covariate (and per level for categorical) is <= 0.10. - Given balancing cannot meet SMD <= 0.10 for any selected covariate, When the system finalizes the split, Then those covariates are flagged as Imbalanced and the comparison is marked Publish Blocked. - Given weighting is applied to achieve balance, When results are computed, Then effective sample size is used (Kish’s formula) and displayed in the Results Context. - Given the split is balanced, When results are displayed, Then the balancing method used (e.g., stratified blocking, reweighting) is shown in the context panel and export. - Given any record lacks required covariate values, When balancing runs, Then the record is excluded from balancing and the exclusion count is shown in Exclusions Applied.
Minimum Sample Thresholds & Tiny Cohort Exclusion
- Given min_cohort_n=50 and min_cell_n=25 are configured, When a cohort or arm falls below its threshold after exclusions, Then it is tagged Excluded—Below Minimum and removed from comparisons. - Given any comparison has fewer than min_cell_n observations per arm after balancing/weighting, When results are computed, Then publishing is blocked and a Low Sample guardrail warning is displayed. - Given thresholds are updated by an admin, When the analysis is rerun, Then exclusions and coverage recalculate using the new thresholds and the change is logged. - Given excluded cohorts exist, When results are exported, Then the export includes an Exclusions Applied section with counts and reasons for each exclusion type.
Power Check and MDE Calculation
- Given alpha=0.05 and target power=0.80 are configured, When baseline conversion is estimated from control and current sample size is N, Then the system calculates and displays achieved power for the observed lift. - Given achieved power < target power, When a user attempts to publish insights, Then publishing is blocked and a Low Power guardrail warning is shown with required additional N to reach target power. - Given target power and alpha are configured, When requested, Then the system computes and displays the minimum detectable effect (MDE) for the primary metric using effective sample size. - Given weighting or clustering is present, When power and MDE are computed, Then effective sample size is used (not raw N) and the method is cited in the context.
Guardrails, Publish Block, and Override with Audit
- Given any guardrail is violated (imbalance, low sample, low power), When a user clicks Publish, Then Publish is disabled with a tooltip enumerating violated guardrails. - Given the user has Override permission, When they choose Override, Then a justification text field (minimum 15 characters) is required to proceed. - Given an override is submitted, When the insight is published, Then an immutable audit record is created capturing user ID, timestamp, violated guardrails, thresholds, and justification. - Given an override occurred, When the insight is viewed, Then it is labeled Overridden with a link to the audit record in both UI and export.
Transparent Results Context Output
- Given analysis completes, When results are displayed or exported, Then the context includes balancing method, effective sample size, coverage %, exclusions applied with counts, and confidence indicators per metric. - Given numbers are rounded for on-screen display, When exports are downloaded, Then full-precision values (>=4 decimal places) are included in the export. - Given a user clicks Confidence Indicator, When the tooltip opens, Then it shows confidence level, interval bounds, and guardrail pass/fail status. - Given results are rerun with new data or settings, When the context refreshes, Then version and timestamp are updated and visible.
Configurable Thresholds and Defaults
- Given no custom settings exist, When a new workspace is created, Then defaults are set to min_cohort_n=50, min_cell_n=25, SMD_threshold=0.10, alpha=0.05, power=0.80. - Given an admin updates any threshold, When values are saved, Then inputs are validated (numeric, correct bounds) and persisted for the workspace. - Given settings are changed, When an analysis runs, Then guardrails use the latest saved settings and the change is logged with user, old value, new value, and timestamp. - Given settings history is requested, When the log loads, Then prior values with who/when are listed and are read-only.
Contextual Result Tagging & Lineage
"As a compliance officer, I want every insight to include its context and lineage so that we can audit decisions and reproduce results when needed."
Description

Attach comprehensive context to every cohort and analysis result, including rule definitions, attribute schema versions, data timeframe, included/excluded populations, sample sizes, balancing methods, thresholds used, creator and approver identities, and system version. Maintain end-to-end lineage from raw events to derived metrics with immutable IDs and timestamps. Expose context tags in the UI, exports, and API to enable reproducibility, auditability, and clear communication of what works for whom. Provide filters and search over tags to quickly locate relevant insights and their provenance.

Acceptance Criteria
UI Context Tags Visible for Cohort Result
Given a completed cohort analysis exists When an authorized user opens the Analysis Details view in the UI Then the Context Tags panel displays non-empty values for: ruleDefinitions.version, ruleDefinitions.hash, attributeSchemaVersion, dataTimeframe.start, dataTimeframe.end, includedPopulations[], excludedPopulations[], counts.included, counts.excluded, counts.totalConsidered, balancingMethod.name, balancingMethod.parameters, thresholds.minCellSize, thresholds.significance, creatorId, approverId, systemVersion, lineage.lineageId, timestamps.createdAt, timestamps.computedAt And all IDs conform to UUIDv4, timestamps are ISO-8601 with timezone, and versions use SemVer And the values shown in the UI exactly match the values returned by the API for the same analysis ID And the UI flags any missing required tag as an error state and blocks export until resolved
API Returns Complete Context Tags and Lineage Metadata
Given an existing analysis ID When GET /v1/analyses/{id} is called with valid auth Then the 200 response includes a tags object containing required fields: ruleDefinitions.version, ruleDefinitions.hash, attributeSchemaVersion, dataTimeframe.start, dataTimeframe.end, includedPopulations[], excludedPopulations[], counts.included, counts.excluded, counts.totalConsidered, balancingMethod.name, balancingMethod.parameters, thresholds.minCellSize, thresholds.significance, creatorId, approverId, systemVersion, lineage.lineageId, lineage.rawEventBatchIds[], lineage.transformStepIds[], metricDefinition.version, timestamps.createdAt, timestamps.computedAt And IDs are immutable across repeated GETs; ETag remains unchanged unless the analysis is re-computed And PATCH/PUT/DELETE to /v1/analyses/{id}/tags is rejected with 405 Method Not Allowed And field formats validate: UUIDv4 for IDs, ISO-8601 for timestamps, SemVer for versions, and balancingMethod.name in {"fair_split_stratified","propensity_score_matching","none"}
Export Files Embed Context Tags and Lineage
Given an analysis result is exported as CSV and JSON by an authorized user When the export completes Then the CSV includes columns: analysisId, lineageId, and ContextTags (JSON-encoded tags object) And the JSON export includes a top-level tags object with the same required fields as the API And the values in both export formats exactly match the API response for the same analysis ID And tags contain no PHI/PII; creatorId and approverId are internal IDs (not names/emails) And if min-cell-size masking is applied, tags.thresholds.minCellSize is present and masked fields are flagged with reason "below_min_cell_size"
Tag-Based Filtering and Search Across Results
Given at least 20 analyses exist with varied tags When a user applies filters appointmentType="Prophy" AND providerId=<UUID> AND locationId=<UUID> AND riskTier in {"High","Medium"} AND dataTimeframe.start >= 2025-06-01 AND dataTimeframe.end <= 2025-06-30 Then only analyses whose tags match all predicates are returned in the UI list and via GET /v1/analyses?... And free-text search for tag key:value (e.g., language:Spanish) returns only analyses whose tags contain that exact key-value And range filters on counts.included (e.g., >= 100) and thresholds.significance (e.g., <= 0.05) return the correct subset And no-results conditions return an empty set with count=0 and no errors
Immutable Provenance IDs and Timestamps
Given an analysis is computed at time T1 with analysisId A and lineageId L When the analysis is retrieved multiple times after T1 Then analysisId A, lineageId L, timestamps.createdAt, and timestamps.computedAt remain unchanged And attempting to modify any tag field via UI or API is prevented (405 or explicit validation error) and no values change And re-running the same cohort definition over a new timeframe or data snapshot creates a new analysisId and lineageId; the prior analysis remains retrievable with unchanged tags
Tag Completeness for Fair Splits and Exclusions
Given Cohort Carver enforces fair splits and excludes tiny cohorts When an analysis is saved Then tags include balancingMethod.name and balancingMethod.parameters capturing the split strategy and inputs And tags.thresholds.minCohortSize is present and > 0 And tags.excludedPopulations[] lists each excluded cohort with reason codes (e.g., "below_min_cohort_size","insufficient_data") And tags.counts.totalConsidered = tags.counts.included + tags.counts.excluded And ruleDefinitions.attributesUsed includes appointmentType, providerId, locationId, riskTier, language, ageBand, guardianInvolved where applicable
Precision Rollout to Campaigns & Branching
"As a dentist, I want to deploy proven reminder strategies to the right patient cohorts so that I can increase confirmations without disrupting other workflows."
Description

Enable targeted deployment of winning strategies to specific cohorts across SMS, email, and voice. Support gradual rollout with percentage-based targeting, holdouts/controls, start/stop scheduling, and automatic fallbacks. Integrate with SmileCue’s adaptive branching engine to vary scripts, cadence, timing, and channel mix per cohort. Include pre-rollout checks for consent status, channel availability, provider/location constraints, and fair-split guardrails, followed by post-rollout tracking of confirmation uplift and no-show reduction by cohort. Provide rollback, versioning, and approval workflows to ensure safe, precise execution.

Acceptance Criteria
Cohort Targeting and Fair Splits
- Given a rollout is configured with cohort rules (appointment type, provider, location, risk tier, language/age, guardian), When a preview is generated, Then only patients matching all selected attributes are included and the preview count is displayed. - Given a cohort preview count is below the organization’s minimum cohort size threshold (default 50, configurable), When attempting to activate the rollout, Then activation is blocked with the reason "Cohort too small" and the blocked cohort is listed. - Given multiple cohorts are targeted in one rollout, When percentage allocation across cohorts is calculated, Then each cohort receives its configured share within ±2% tolerance and no cohort is below 5% of total targeted population unless explicitly marked as exploratory. - Given targeting constraints intersect (e.g., provider not present at selected location), When previewing, Then the system displays zero-count cohorts with a validation warning and excludes them from activation until resolved. - Given a rollout is activated, When messages are sent, Then each patient record is tagged with cohort_id and context metadata (appointment type, provider, location, risk tier) for downstream attribution.
Percentage Rollout and Holdout Controls
- Given a campaign version is selected for rollout, When setting percentages per cohort, Then the system enforces that Variant + Holdout = 100% with 0.1% precision. - Given a patient is assigned to variant or holdout, When the rollout percentage is increased later, Then the patient’s assignment remains sticky for 30 days to prevent crossover contamination. - Given a holdout group exists, When outcomes are collected, Then holdout members receive only the control experience and are excluded from variant sends. - Given a staged rollout plan (e.g., 10% now, 50% tomorrow, 100% Friday) is scheduled, When each stage time arrives, Then the system adjusts traffic within 10 minutes and does not re-send to already messaged patients within a 24-hour window. - Given per-cohort percentages are configured, When saving, Then the UI prevents totals outside 100% and displays validation errors inline.
Pre-Launch Validation and Scheduling Windows
- Given a rollout is configured, When running Pre-Launch Check, Then the system validates per cohort: channel consent status (SMS/email/voice), channel availability (valid phone/email), provider and location constraints, fair-split thresholds, and blackout windows, and returns a pass/fail report. - Given any must-pass check fails, When attempting to Activate, Then activation is blocked and the failing items are listed with remediation guidance links. - Given start and stop times are set (with timezone specified or defaulting to practice timezone), When the clock reaches the start time, Then the rollout activates within 5 minutes; when the stop time is reached, Then all unsent messages are canceled within 5 minutes. - Given practice quiet hours are configured, When a scheduled send falls within quiet hours, Then the send is deferred to the next permitted window and logged. - Given the rollout spans multiple locations with different timezones, When scheduling is applied, Then each cohort respects its location timezone.
Channel Fallbacks with Consent and Availability
- Given a channel priority order is configured (e.g., SMS > Email > Voice), When the primary channel is ineligible due to missing consent or invalid contact, Then the system attempts the next eligible channel within 15 minutes while respecting frequency caps and quiet hours. - Given a delivery failure occurs on the primary channel (hard bounce, carrier block, unreachable), When retry policy is executed, Then the system performs at most one retry on the same channel and, on failure, falls back to the next eligible channel; no patient receives more than one initial-touch message per hour across channels. - Given a fallback is used, When logging, Then the message event includes fallback_reason, original_channel, final_channel, and timestamps. - Given a patient gains consent after initial ineligibility during the rollout window, When re-evaluating eligibility for subsequent cadence steps, Then the system upgrades to the preferred channel for future steps without duplicating the same step’s content.
Adaptive Branching per Cohort Across Channels
- Given a cohort is mapped to a branching strategy version, When a patient responds (confirm/reschedule/stop), Then the next step follows the defined branch for that cohort and channel. - Given per-cohort overrides for script, cadence, timing, and channel mix are configured, When sends are generated, Then the content, send intervals, send times, and channel weights match the configuration within ±1 minute and ±1% tolerance respectively. - Given multiple channels are in the mix, When message variants are sent, Then UTM/message tags include version_id, branch_id, and cohort_id for each event. - Given a cohort has no explicit override, When executing, Then the global default branching strategy is applied.
Post-Launch Metrics and Attribution by Cohort
- Given a rollout is active, When daily metrics are computed, Then the system reports per cohort: confirmations (numerator/denominator), confirmation rate, uplift vs holdout (if configured) or vs 8-week baseline, and no-show rate within 24 hours of appointment. - Given cohorts below the reportable threshold (default 30 outcomes), When rendering reports, Then point estimates are flagged as "Low sample size" and excluded from aggregated uplift. - Given filters (date range, provider, location, appointment type) are applied, When viewing metrics, Then all charts and exports reflect the filters and maintain cohort context tags. - Given a CSV export is requested, When generated, Then it includes patient_id (pseudonymized), cohort_id, variant/holdout assignment, timestamps, outcomes, and channel used.
Rollback, Versioning, and Approval Workflow
- Given a new rollout configuration is created, When submitted for approval, Then at least one approver with the proper role must approve before activation becomes available; all actions are audit logged with user, timestamp, and diff. - Given a rollout is active, When a rollback to a prior version is initiated, Then new sends stop within 5 minutes, queued messages for the superseded version are canceled, and assignment stickiness is preserved. - Given a rollback completes, When system state is inspected, Then the prior version’s configuration is reinstated, a new version is created capturing the rollback event, and stakeholders receive notifications. - Given any change is saved post-approval, When detected, Then approval status resets to "Pending" and the rollout cannot be activated until re-approved.
Role-Based Access, PHI Protections & Audit Logging
"As an administrator, I want strict access controls and audit logs around cohorting and rollouts so that we remain HIPAA-compliant and minimize risk."
Description

Implement granular role-based access controls for creating, editing, viewing, and rolling out cohorts and insights, aligned to dentist, hygienist, office manager, and admin roles. Apply HIPAA-compliant protections including PHI masking in previews/exports by default, encryption in transit and at rest, session timeouts, and consent checks at action time. Require approvals for high-impact changes and guardrail overrides. Capture detailed audit logs for data access, cohort changes, result publication, and rollout actions, with exportable reports for compliance reviews and incident response.

Acceptance Criteria
Enforce Role-Based Permissions for Cohort Operations
Given an admin has configured permissions: Admin=all; Office Manager=create/edit/view/rollout; Dentist=view only; Hygienist=view insights only When a user attempts to create, edit, view, publish insights, or roll out a cohort Then the action is permitted only if the user's role has the corresponding permission And forbidden actions are hidden/disabled in the UI and rejected by the API with HTTP 403 and no PHI in the response body And permission checks are performed server-side on every request, independent of client state
Default PHI Masking in Previews and Exports
Given any user previews cohort members or results When the preview renders identifying fields Then PHI is masked by default (e.g., names initialed, phone last 4, email local part masked, DOB as age band, address city/state only) And export files default to a de-identified schema unless a user with "Unmask PHI" permission explicitly selects Include PHI and provides a reason And masked previews and de-identified exports contain zero direct identifiers or sensitive notes
Consent Verification at Action Time
Given a user initiates a rollout (SMS/email/voice) or an export containing patient records When the system assembles the target population Then each patient’s current consent and channel preferences are checked at action time And patients without valid consent for the selected channel are excluded and surfaced in a preflight summary with counts And the action is blocked if exclusion exceeds a configurable threshold, unless an approved override is obtained And no communications or PHI are sent/exported for excluded patients
Encryption In Transit and At Rest
Given any client or integration connects to SmileCue When negotiating transport security Then only TLS 1.2+ is accepted with strong ciphers; TLS < 1.2 is rejected And HSTS is enabled for all web endpoints When data is stored in databases, object storage, or backups Then encryption at rest is enabled using KMS-managed AES-256 keys And key access is restricted by IAM and audited
Idle and Absolute Session Timeouts with Re-authentication
Given a user is logged in When there is 15 minutes of inactivity Then the session is locked and the user must re-authenticate to continue When 12 hours elapse from login regardless of activity Then the session is terminated and a full re-authentication is required And refresh/access tokens created prior to timeout are invalidated and cannot be reused
Dual Approval for High-Impact Changes and Guardrail Overrides
Given thresholds and guardrails are configured (e.g., rollouts affecting >100 patients, PHI export with identifiers, disabling consent checks) When a user initiates a high-impact action or attempts to override a guardrail Then submission requires entry of a business reason and routes to a second approver with Admin or Office Manager role who is not the requester And the action remains pending until approved; on rejection, no changes are applied And the system records requester, approver, timestamps, and reason
Comprehensive Audit Logging and Exportable Compliance Reports
Given a user performs data access, cohort create/edit/delete, insight publication, rollout initiation/cancellation, permission changes, approvals, or export/download When the event occurs Then an audit log entry is written capturing timestamp (UTC), user ID, role, action, object type and ID, before/after values (for edits), IP, and user agent And audit logs are append-only and tamper-evident And authorized admins can filter logs by date range, user, role, action, object, and export to CSV with column headers within 60 seconds for up to 100,000 rows

Consent Guard

Keep every test compliant by design. Consent Guard preflights variants against Jurisdiction Rules, quiet hours, consent class (informational vs. marketing), and template approvals. It blocks risky sends, logs decisions to Evidence Vault, and recommends safe alternates—so you innovate confidently without TCPA or HIPAA missteps.

Requirements

Jurisdiction Rule Engine
"As a compliance administrator, I want outgoing messages automatically checked against applicable laws by jurisdiction so that non-compliant sends are blocked before they reach patients."
Description

A rules engine that evaluates each outbound message against federal and state regulations (e.g., TCPA), HIPAA treatment-versus-marketing distinctions, and channel-specific carrier policies before send. Policies are stored as versioned, machine-readable rule packs that can be hot-updated by authorized admins without code deployment. The engine ingests message purpose, content metadata, channel (SMS, email, voice), recipient location, consent scope, and campaign settings to compute allow, warn, or block outcomes with rationale. It integrates with the SmileCue composer, automations, and scheduler to intercept risky sends pre-dispatch and propagate decisions to downstream delivery services. The engine supports rule precedence, exception handling for emergencies, and produces consistent, explainable decisions that reduce legal risk while maintaining throughput for compliant traffic.

Acceptance Criteria
Pre-Dispatch Decisioning and Propagation
Given an outbound message with attributes purpose, contentMetadata, channel ∈ {SMS, Email, Voice}, recipientLocation, consentScope, campaignSettings, correlationId When the message is evaluated pre-dispatch Then the engine returns a Decision {status ∈ [ALLOW, WARN, BLOCK], decisionCode, rationale, ruleVersion} within 100 ms p95 and 300 ms p99 under 200 RPS And if status == BLOCK, the scheduler prevents dispatch and downstream delivery services receive no send request And if status == WARN, the send proceeds but is tagged with warningCode and rationale in metadata passed to downstream delivery services And the decision is propagated to composer, automations, and scheduler via event bus with the same correlationId
Rule Pack Versioning and Hot Update
Given an authorized admin with role RuleAdmin and a valid, signed rule pack v1.3.0 with effectiveAt timestamp When the admin publishes the rule pack via the Rules API Then new evaluations created after effectiveAt use v1.3.0 without service restart and return ruleVersion=v1.3.0 And in-flight evaluations started before effectiveAt complete with their original ruleVersion And the system supports rollback to the previous version within 1 minute by re-publishing, recorded in audit log And unauthorized users receive 403 and no rule changes occur
Jurisdiction and Consent Precedence Resolution
Given overlapping federal, state, and carrier policies applicable to a recipient’s location and channel, and the message’s consent class When the engine evaluates the message Then the most restrictive applicable rule determines the outcome per precedence: EmergencyExceptions > LegalStop (revoked consent) > State > Federal > CarrierPolicy > CampaignSettings And quiet hours defined by jurisdiction are enforced per recipient’s local time And evaluation includes geo-fallback: if precise location is unavailable, default to recipient’s area code for SMS/Voice or mailing ZIP for Email; if unknown, BLOCK with reason=UnknownJurisdiction
HIPAA Treatment vs Marketing Enforcement
Given message purpose=Marketing and contentMetadata includes PHI=true and consentScope lacks Marketing consent When evaluated Then the engine returns BLOCK with decisionCode=HIPAA_MARKETING_NO_CONSENT and a rationale describing missing consent And given message purpose=Treatment with PHI=true and appropriate Treatment consent When evaluated within allowed quiet hours Then the engine returns ALLOW with decisionCode=HIPAA_TREATMENT_ALLOWED And when BLOCK is returned, the engine includes at least one safe alternate suggestion (e.g., remove PHI, switch to Email with de-identified template, or obtain marketing consent)
Emergency Override Controls
Given an authorized user with role EmergencyPublisher sets emergencyOverride=true with scopedReason and expiresAt When the engine evaluates a message that would otherwise be blocked or warned Then for messages with purpose=Emergency and now < expiresAt, the engine returns ALLOW with decisionCode=EMERGENCY_OVERRIDE_APPLIED And all such decisions require two-person approval recorded in audit, and are rate-limited to 20 RPS per tenant And after expiresAt, evaluations revert to normal rules with no override applied
Deterministic, Idempotent, Explainable Decisions
Given identical input payloads (including ruleVersion) evaluated multiple times within 24 hours When evaluated concurrently across multiple instances Then the engine returns identical outcomes and rationales, and includes a rulesFired array with stable ruleIds and their evaluation results And providing the same correlationId results in exactly-once decision persistence (no duplicate Evidence Vault records)
Evidence Vault Decision Logging and Traceability
Given any evaluation When a decision is made Then the engine writes an immutable record to Evidence Vault containing: correlationId, tenantId, timestamp (UTC), input summary, decision status/code, ruleVersion, rulesFired IDs, precedence path, actor (system or user), and signatures And records are queryable by correlationId and date range within 2 seconds for 95th percentile queries over 1 million records And tamper attempts are detectable via integrity checks; failed writes cause the decision to be retried up to 3 times and, if still failing, the send is BLOCKED with reason=AuditWriteFailure
Quiet Hours & Timezone Guard
"As an office manager, I want SmileCue to detect each patient’s local time and honor legally mandated quiet hours so that reminders are delivered compliantly without disturbing patients."
Description

Detects each recipient’s local timezone and applies jurisdiction-defined quiet hour windows for SMS, email, and voice. Time resolution uses a hierarchy of explicit patient timezone, verified address, number portability lookup, and area code, with DST-aware calculations and fallbacks. When a message falls inside a restricted window, the system automatically reschedules to the next compliant time and annotates the schedule with the reason. Practice-level quiet hours and channel overrides can be configured provided they remain within legal bounds, with guardrails preventing unsafe settings. All rescheduling decisions are exposed in the composer and scheduler and are included in compliance logs for auditability.

Acceptance Criteria
Local Timezone Detection Hierarchy (DST-aware)
Given patient record has explicit timezone "America/Chicago" And verified address and portability data are present When local time is computed for send_at "2025-10-15T20:00:00Z" Then detected_timezone = "America/Chicago" And timezone_source = "explicit" And local_send_time = "2025-10-15T15:00:00-05:00" Given patient record has no explicit timezone And verified address geocodes to timezone "America/Los_Angeles" When local time is computed for send_at "2025-10-15T20:00:00Z" Then detected_timezone = "America/Los_Angeles" And timezone_source = "verified_address" And local_send_time = "2025-10-15T13:00:00-07:00" Given no explicit timezone and no verified address And number portability lookup returns timezone "America/New_York" When local time is computed for send_at "2025-10-15T20:00:00Z" Then detected_timezone = "America/New_York" And timezone_source = "portability_lookup" And local_send_time = "2025-10-15T16:00:00-04:00" Given no explicit timezone, no verified address, and no portability result And phone area code "307" maps to timezone "America/Denver" When local time is computed for send_at "2025-10-15T20:00:00Z" Then detected_timezone = "America/Denver" And timezone_source = "area_code" And local_send_time = "2025-10-15T14:00:00-06:00"
Quiet Hours Enforcement per Jurisdiction & Channel
Given jurisdiction "US-CA" quiet_hours.sms = 21:00–08:00 local And detected_timezone = "America/Los_Angeles" And channel = "sms" And desired_send_time_local = "2025-06-12T22:15:00" When the system schedules the message Then outcome = "rescheduled" And scheduled_time_local = "2025-06-13T08:00:00" And reason_code = "quiet_hours_violation" And rule_ref = "US-CA:SMS:21:00-08:00" Given jurisdiction "US-NY" quiet_hours.voice = 21:00–08:00 local And channel = "voice" And desired_send_time_local = "2025-03-05T07:59:00" When the system schedules the message Then outcome = "rescheduled" And scheduled_time_local = "2025-03-05T08:00:00" And reason_code = "quiet_hours_violation" And rule_ref = "US-NY:VOICE:21:00-08:00" Given jurisdiction "US" quiet_hours.email = 22:00–06:00 local And channel = "email" And desired_send_time_local = "2025-09-01T05:30:00" When the system schedules the message Then outcome = "rescheduled" And scheduled_time_local = "2025-09-01T06:00:00" And reason_code = "quiet_hours_violation" And rule_ref = "US:EMAIL:22:00-06:00"
Automatic Reschedule Annotation on Schedule Item
Given a message is rescheduled due to quiet hours When the schedule item is saved Then schedule_item includes non-null fields: original_time_utc, rescheduled_time_utc, detected_timezone (IANA), timezone_source, jurisdiction_code, channel, rule_ref, reason_code, decision_timestamp_utc, decided_by = "system" And original_time_utc < rescheduled_time_utc And values in schedule_item match the computed scheduling decision exactly
Practice Quiet Hours Overrides with Legal Guardrails
Given legal quiet_hours.sms = 21:00–08:00 local And practice_override.sms = 20:00–09:00 local When saving the override Then status = "accepted" And effective_quiet_hours.sms = 20:00–09:00 local Given legal quiet_hours.voice = 21:00–08:00 local And practice_override.voice = 22:00–07:00 local When saving the override Then status = "rejected" And error_code = "override_out_of_bounds" And error_message contains "must be equal to or stricter than legal bounds" And suggestion contains "start no later than 21:00 and end no earlier than 08:00" Given an unsafe override exists from a prior config When computing a schedule Then legal bounds are applied instead of the unsafe override And a compliance log entry is created with reason_code = "guardrail_correction"
Composer & Scheduler Surfacing of Reschedule Decisions
Given the user opens the composer with at least one recipient whose desired time is within quiet hours When preflight runs Then for each affected recipient the UI displays: original_send_time_local, new_send_time_local, detected_timezone, timezone_source, jurisdiction_code, rule_ref, reason_code = "quiet_hours_violation" And before send, the scheduler list shows a reschedule badge and details per affected recipient And the user can copy a compliance_log_id linked to the decision
Compliance Logging to Evidence Vault
Given a quiet-hours decision (rescheduled or blocked) occurs When the decision is made Then a compliance log entry is written within 10 seconds And the entry includes fields: message_id, practice_id, patient_id, channel, jurisdiction_code, rule_ref, rule_version, detected_timezone, timezone_source, original_time_utc, rescheduled_time_utc (nullable if blocked), decision ("rescheduled"|"blocked"), reason_code, decision_timestamp_utc, actor = "system", correlation_id And the entry is immutable and retrievable via Evidence Vault API by message_id And the retrieved entry matches the schedule item values exactly
DST Transition Handling and No Duplicate Sends
Given detected_timezone = "America/Chicago" And desired_send_time_local = "2025-03-09T02:30" (non-existent local time due to spring forward) When scheduling the message Then the system rolls forward to the next valid local time = "2025-03-09T03:00" And if that time is within quiet hours, it further reschedules to the next compliant boundary per jurisdiction Given detected_timezone = "America/New_York" And desired_send_time_local = "2025-11-02T01:30" (ambiguous local time due to fall back) When scheduling the message Then exactly one send is scheduled And the resolved local time is the earliest instance that is compliant with quiet hours And the resolved UTC timestamp is recorded in the schedule item and compliance log
Consent Classifier & Enforcement
"As a practice marketer, I want campaigns enforced by the correct consent level so that only patients with appropriate permissions receive promotional messages."
Description

Classifies each template and campaign as transactional/informational or marketing and maps that classification to required consent levels per channel and jurisdiction. At send time, verifies the presence and currency of consent artifacts (timestamp, scope, channel, provenance, double opt-in where applicable) and checks for revocations or STOP keywords across channels. Blocks or downgrades delivery when consent is insufficient and records the consent snapshot used in the decision. Supports HIPAA treatment exceptions, ensuring PHI-related informational messages are permitted within regulatory boundaries while marketing communications require heightened consent. Provides guardrails to include required disclosures and opt-out instructions for marketing SMS and voice.

Acceptance Criteria
Template classification and rule mapping
Given a message template and campaign metadata (channel, locales, jurisdictions, org policy) When the classifier runs Then the template is labeled as Marketing or Informational with a confidence score >= the configured threshold And the mapped consent requirements are resolved per channel and jurisdiction (e.g., US SMS Marketing => double opt-in; CA SMS Marketing => express consent; Email Marketing => explicit opt-in; Voice Marketing => recorded consent) And the mapping includes required disclosures and opt-out instructions for marketing SMS/voice And any manual override requires a reason and user id, and is captured in the decision snapshot and audit log
Marketing SMS blocked without double opt-in
Given a US recipient with only single opt-in SMS marketing consent and no double opt-in artifact (timestamp, channel, provenance) And a campaign classified as Marketing targeting SMS When send-time enforcement runs Then the system blocks SMS delivery before carrier submission And the decision includes reason=insufficient_consent and missing_artifact=double_opt_in And an Evidence Vault snapshot is recorded with consent artifacts, revocation status, classifier version, ruleset version, evaluation timestamp, and hashed recipient identifiers And a safe alternate is recommended (e.g., send double opt-in request via SMS or switch to Email if permitted)
Marketing SMS/Voice disclosures and opt-out enforcement
Given a marketing SMS or outbound voice call template lacking required jurisdiction-specific disclosures and opt-out instructions When preflight validation runs Then the system prevents approval and shows missing_requirements=[disclosure,opt_out] And if auto-remediation is enabled, the platform appends the configured disclosure and opt-out snippet for the jurisdiction/channel And the final composed message/IVR script preview reflects the inserted content And send-time enforcement blocks delivery if disclosures/opt-out are still absent after preflight
HIPAA treatment exception allows PHI informational reminder
Given a template classified as Informational and tagged PHI under HIPAA treatment exception And a patient with an active treatment relationship and no revocation for SMS informational messages When send-time enforcement evaluates an SMS reminder within allowed quiet hours and jurisdiction rules Then delivery is permitted without marketing consent And the Evidence Vault snapshot records treatment_exception=true, minimum_necessary=true, and included PHI fields metadata (not content) And any inclusion of marketing content causes reclassification to Marketing and blocks delivery until marketing consent is present
Revocation detection across channels
Given revocation events exist: SMS reply "STOP", Email unsubscribe link clicked, Voice DNC IVR selection recorded When a new send is evaluated for each respective channel Then the system blocks delivery on the revoked channel with decision=blocked reason=consent_revoked and records the revocation source and timestamp And if organizational policy is set to propagate revocations across channels, the system applies the propagation rules and blocks those channels accordingly, capturing the policy id in the snapshot And an attempt to re-consent via the revoked channel is allowed only for regulatory-approved re-opt-in messages (e.g., SMS START/UNSTOP), which, upon success, updates consent status and unblocks subsequent sends
Consent snapshot logging and audit retrieval
Given any send decision (allow, block, downgrade) When the decision is made Then a consent snapshot is written to Evidence Vault with immutable ID, message/campaign ID, classifier label and version, ruleset version, evaluated jurisdiction, channel, consent artifacts (timestamp, scope, channel, provenance, double opt-in details), revocation status, disclosures enforcement outcome, user overrides, and decision outcome And the snapshot is immutable (WORM) and retrievable via API by message ID within <200 ms p95 And audit search supports filtering by recipient hash, decision outcome, date range, jurisdiction, and campaign id
Downgrade delivery to permitted channel
Given a campaign classified as Marketing targeting SMS and Email And the recipient lacks SMS marketing consent but has Email marketing consent When send-time enforcement runs Then the system downgrades delivery by suppressing SMS and sending via Email only And the decision outcome reflects action=downgrade with affected_channels=[SMS] and sent_channels=[Email] And the Evidence Vault snapshot records rationale and the alternate channel chosen And no SMS is submitted to carrier
Template Approval Workflow
"As a compliance reviewer, I want a controlled template approval process so that staff can only use content that has been vetted for regulatory compliance."
Description

Provides a governed lifecycle for message templates with statuses including Draft, In Review, Approved, Rejected, and Expired. Compliance reviewers can compare revisions with diffs, validate dynamic placeholders, enforce prohibited phrasing lists, and bind templates to consent classes and allowed channels. Only approved templates are selectable in campaigns and automations; attempts to use unapproved or expired templates are blocked at composition and send time. Templates auto-require reapproval when underlying policies change, with notifications and migration assistance. All actions are permissioned and logged to support separation of duties and audit requirements.

Acceptance Criteria
Only Approved Templates Selectable in Campaign Composer
Given I am a user with access to Campaign Composer or Automation Builder And templates exist in Draft, In Review, Approved, Rejected, and Expired statuses When I open the template picker or search by name/ID Then only templates with status Approved are selectable And non-Approved templates are hidden or disabled with a status-specific tooltip And attempting to paste or reference a non-Approved template ID yields an inline validation error preventing selection
Block Unapproved or Expired Templates at Send Time
Given a campaign or automation references a template whose status is Draft, In Review, Rejected, or Expired When a user attempts to schedule or send Then the send operation is blocked with a descriptive user-facing error citing the template status And no messages are dispatched And an Evidence Vault entry is recorded including template ID, status, actor, action, and timestamp
Compliance Review: Diff and Placeholder Validation
Given a compliance reviewer opens a template submission When they select "Compare to previous version" Then a side-by-side diff highlights added/removed text and placeholder changes And the system validates that all dynamic placeholders are whitelisted and syntactically correct And any invalid placeholders are listed with line/section, and approval is blocked until resolved
Prohibited Phrasing Enforcement
Given an organization prohibited phrase list exists When a template is submitted for review or approval Then the system scans all content, including dynamic branches, for prohibited phrases And any matches are flagged with exact phrase and location And approval cannot be completed until violations are removed or an explicit, permissioned compliance override with justification is recorded and logged
Bind Templates to Consent Class and Allowed Channels
Given consent classes and allowed delivery channels are configured When a template is created or edited Then the author must select exactly one consent class and one or more allowed channels And at approval time the selection is validated against jurisdictional rules And at composition/preflight the system blocks use on channels not allowed or without matching recipient consent, with actionable guidance
Auto-Reapproval Triggered by Policy Change
Given a policy impacting consent, channels, or prohibited phrases is updated and published When the policy effective date is reached or revalidation is triggered Then all impacted Approved templates automatically transition to In Review and are removed from selectable lists And template owners and reviewers receive notifications with the affected list and recommended safe alternates And running automations using affected templates may complete the current step but cannot schedule further sends with those templates until reapproved
Permissioning and Audit Logging (Separation of Duties)
Given roles exist for Author, Reviewer, Approver, and Compliance Override When a user performs actions (create, edit, submit, approve, reject, expire, override) Then permissions are enforced so a user cannot approve their own authored template and only Approvers can approve And every action is logged to Evidence Vault with actor, action, template ID, from/to status, diff hash, timestamp, and justification And unauthorized attempts are blocked and logged with reason
Evidence Vault Decision Logging
"As a practice owner, I want an auditable record of every allowed or blocked decision so that I can demonstrate compliance during regulatory reviews or disputes."
Description

Captures an immutable record for every preflight decision including inputs (message hash, template ID, recipient attributes), rules evaluated with versions, consent artifacts referenced, quiet-hour calculations, outcome, and rationale. Stores records in tamper-evident storage with configurable retention, encryption at rest, and PHI minimization through tokenization and redaction. Provides search, filtering, and export capabilities with role-based access controls to support audits and incident response. Correlates decisions with delivery events using trace IDs and exposes downloadable compliance reports by time range, campaign, or provider location. Integrates with SIEM and eDiscovery workflows via secure API endpoints.

Acceptance Criteria
Log Completeness and Schema for Preflight Decisions
Given a preflight decision is executed for a recipient and template When the decision is persisted to Evidence Vault Then exactly one record is written per decision with fields: decision_id, trace_id, schema_version, created_at (ISO 8601 with timezone, ms precision), environment, service_id, message_hash (SHA-256), template_id, consent_class, recipient_attribute_tokens, rules_evaluated [{rule_id, rule_name, jurisdiction, version, result}], consent_artifacts [{artifact_id, type, version}], quiet_hour_evaluation {local_timezone, window, source, result}, outcome (allow|block), rationale, record_hash And the record validates against the current schema with all mandatory fields non-null And the record write latency is p95 ≤ 150 ms and p99 ≤ 400 ms measured over 10k decisions And the outcome and rationale reflect the evaluated rules results deterministically And a unique trace_id is generated if not supplied and is globally unique
Tamper-Evident, Encrypted, and Minimized Storage
Given decision records are stored in the Evidence Vault When integrity verification is performed Then each record includes a content hash and participates in an append-only hash chain (prev_hash, record_hash) And any post-write modification causes verification to fail and emits a security alert within 5 minutes And records are encrypted at rest using AES-256 with KMS-managed keys and keys rotated at least every 90 days And PHI minimization is enforced: no raw phone numbers, emails, names, or message bodies are stored; only tokens and message_hash are present; free-text rationale is redacted to remove PHI And decryption requires service principal with least-privilege IAM; access is audited
Configurable Retention and Legal Hold
Given an organization retention policy (e.g., 6 years) and redaction schedule are configured When records exceed the configured retention and are not under legal hold Then they are purged automatically within 24 hours and a purge manifest (counts, time range, actor, policy_id) is immutably logged And legal holds prevent deletion until explicitly removed by a Compliance Admin with dual authorization And policy changes are versioned and auditable with effective_from timestamps And a dry-run mode shows projected deletions before activation
Search, Filter, and Export with RBAC
Given users with roles Compliance Admin, Auditor, Support, and Clinic Staff When they search by time range, campaign_id, jurisdiction, rule_name, rule_version, outcome, template_id, consent_class, provider_location, trace_id, and recipient_token Then results reflect filters exactly and return within p95 ≤ 2 s for up to 100k matching records And Clinic Staff receive access denied; Support can view metadata only (no export); Auditor can search and export; Compliance Admin has full access And exports are available as CSV and JSON up to 1,000,000 records per export via asynchronous jobs with signed URLs expiring in ≤ 24 hours And exported fields preserve redaction/tokenization; filter criteria and generation timestamp are embedded in export metadata And all access and export actions are audited
Trace ID Correlation to Delivery Events
Given a message undergoes preflight and proceeds to delivery pipeline When delivery or suppression events are recorded Then the same trace_id is present in both the decision record and the delivery/suppression event And at least 99.9% of decision records within a 24-hour window have a linked delivery or suppression event discoverable via API and UI And the UI provides a deep link from a decision record to its delivery timeline within 1 click And for blocked messages, a synthetic suppression event is created with the decision rationale
Compliance Report Generation by Time, Campaign, and Location
Given a user with Auditor or Compliance Admin role requests a compliance report for a date range, one or more campaign_ids, and provider_locations When report generation is initiated Then a downloadable CSV and PDF are produced within 5 minutes for up to 10,000,000 decisions And the report includes counts of allow vs block, breakdown by rule and jurisdiction, quiet-hour blocks by timezone, consent class distribution, top rationale categories, and template approval status And the report is digitally signed (hash + signature) and embeds generation timestamp, requester, filters, and schema version And no PHI is included; tokens and hashes only And access is enforced by RBAC; links expire within 24 hours
SIEM and eDiscovery API Integration
Given SIEM/eDiscovery integration is configured with OAuth2 client credentials or HMAC and optional mTLS When a client requests decision logs via the API using time-bounded, cursor-based pagination or receives webhook deliveries Then the API requires TLS 1.2+ and responds with signed NDJSON/JSON events matching the published schema and including integrity hashes and redacted fields only And pagination supports forward-only cursors with deterministic ordering and idempotent retries; 429/5xx responses include Retry-After and exponential backoff guidance And webhooks are HMAC-signed, retried with exponential backoff up to 24 hours, and support replay by time range and cursor And eDiscovery endpoints support creating/removing legal holds, fetching immutable audit packages for a trace_id or time range, and are RBAC-restricted to Compliance Admin And integration health endpoints expose last delivery timestamp, backlog, and signature verification status
Safe Alternate Recommendations
"As a campaign creator, I want compliant alternatives suggested automatically when something is blocked so that I can fix issues quickly without deep regulatory expertise."
Description

When a send is blocked or warned, generates actionable, compliant alternatives such as rescheduling to the next safe window, switching to a permitted channel, substituting an approved informational template, or adding required disclosures. Presents ranked recommendations with explanations that map to the triggering rules and projected risk reduction. Enables one-click apply in the composer and provides equivalent fields in the API response so integrators can automate remediation. Learns from accepted recommendations to improve future suggestions while preserving rule determinism. Ensures any proposed alternative re-runs preflight checks before finalization.

Acceptance Criteria
Quiet Hours Block: Next Safe Window Recommendation
Given a message preflight fails due to quiet hours based on jurisdiction rules and patient timezone When recommendations are generated Then at least one reschedule option within the next permitted window is returned with ISO-8601 timestamp and timezone And each recommendation includes rule_refs, explanation, and projected_risk_reduction (0–100%) And recommendations are ranked by projected_risk_reduction in descending order And one-click apply updates the composer scheduled_at to the chosen time and queues an automatic preflight re-check And preflight re-check must Pass before the send can be finalized; otherwise the choice is rejected with a user-visible reason code And the API response includes an equivalent recommendations array with identical content and order And an Evidence Vault entry records block_reason, recommended_options, selected_option, rule_versions, timestamps, and actor_id
Consent Class Violation: Channel Switch Recommendation
Given a marketing SMS is blocked for insufficient consent class When recommendations are generated Then permitted alternate channels (e.g., email, voice) are suggested based on consent and jurisdiction rules And each suggestion specifies the channel, required disclosures, and any template adjustments needed to remain compliant And one-click apply switches the channel in the composer and inserts required disclosures automatically And an automatic preflight re-check runs and must Pass before finalization And if no safe alternate channel exists, a "no safe alternates" state is returned in UI and API with reason codes And UI and API recommendations are identical in content, order, and identifiers
Marketing Block: Approved Informational Template Substitution
Given a message using a marketing template is blocked by consent rules When recommendations are generated Then at least one approved informational template is suggested that conveys the appointment-critical information without marketing content And variable mapping is validated; any unmapped variables are flagged with suggested fallbacks before apply And HIPAA constraints are enforced (no unnecessary PHI; minimum necessary only) And one-click apply replaces the template and preserves personalization where allowed And an automatic preflight re-check runs and must Pass before finalization And explanation includes the triggering rules and the approved template IDs used
Missing Disclosures: Auto-Add Compliance Language
Given a message triggers a warning/block due to missing required disclosures (e.g., identity, opt-out language) When recommendations are generated Then an option to add the required disclosures is provided with the exact text per jurisdiction and channel And the recommendation estimates the final SMS segment count or email length impact And one-click apply appends the disclosures in the correct position and format And an automatic preflight re-check runs and must Pass before finalization And explanation maps each added disclosure to the specific rule reference(s)
Ranked Recommendations with Rule-Mapped Explanations and API/UI Parity
Given any block or warning outcome When recommendations are generated Then the list is sorted by projected_risk_reduction then by deliverability_impact, both provided as numeric scores And each item includes id, type (reschedule|channel_switch|template_substitution|add_disclosures), changeset preview, explanation text, rule_refs[], projected_risk_reduction (0–100%), and confidence (0–100%) And the composer displays the same list, order, and fields as returned by the API And one-click apply is available for each item in UI and via an equivalent API payload And selecting any item triggers an automatic preflight re-check that must Pass before send
Learning from Accepted Recommendations Without Breaking Rule Determinism
Given users accept or reject recommendations over time When the system updates its ranking model Then only recommendation ranking weights are adjusted; rule pass/fail outcomes remain strictly determined by rule engine And the same inputs (message, metadata, rule set version) always produce the same pass/fail decision and the same recommendation set, with ordering influenced by learned weights And model versions and weight changes are recorded with timestamps and are auditable in Evidence Vault And an opt-out toggle exists to disable learning-based re-ranking per tenant without affecting rule enforcement
Real-time Preflight & Bulk Precheck API
"As a developer integrating SmileCue, I want a real-time preflight API and composer feedback so that I can prevent non-compliant sends programmatically and during authoring."
Description

Exposes a low-latency preflight API and in-composer validator that simulate send decisions in real time for single messages and perform batch prechecks for campaigns. Guarantees performance targets suitable for authoring workflows and high-volume scheduling, supports idempotency keys, rate limiting, and detailed error taxonomy. Returns structured decisions with rationale, affected rules, and recommendation payloads, and supports localization of messages for staff-facing UI. Integrates with SmileCue’s automation engine to gate triggers and with delivery services to enforce blocks at dispatch time. Provides webhooks for decision events and degradation-safe defaults if the service is temporarily unavailable.

Acceptance Criteria
Single Message Real-Time Preflight in Composer
- Given a valid single-message preflight request with recipient jurisdiction, consent class, message template/content, and send time, When POST /v1/preflight is called, Then p95 latency <= 150 ms and p99 latency <= 300 ms, and the response includes decision ∈ {ALLOW, WARN, BLOCK}, decisionId, correlationId, timestamp. - Given a user edits message content in the in-composer validator, When a keystroke pauses for 200 ms, Then the UI validator refreshes within 300 ms end-to-end and reflects the latest preflight decision. - Given a decision is BLOCK or WARN due to quiet hours, consent class, jurisdiction rule, or template approval, When the response is returned, Then affectedRules[] includes at least one item with ruleId, category ∈ {jurisdiction, quiet_hours, consent, template_approval}, severity, and a shortCode, and recommendations[] contains at least one actionable alternative (e.g., nextAllowedSendTime or approvedTemplateId). - Given a successful decision, When logging is enabled, Then the response includes decisionId suitable for audit linkage and is traceable via correlationId across services.
Bulk Campaign Precheck at Scale
- Given a campaign batch of 10,000 recipients with mixed jurisdictions and consent classes, When POST /v1/bulk-precheck is initiated, Then an async jobId is returned within 200 ms and processing begins immediately. - Given the job is running, When fetching results via GET /v1/bulk-precheck/{jobId}/results with pagination size=1000, Then overall throughput is >= 110 recipients/second and 10,000 recipients complete in <= 90 seconds, with stable pagination cursors supporting resume-on-failure. - Given mixed outcomes, When the job completes, Then the summary includes counts for ALLOW/WARN/BLOCK, and each item contains decision, affectedRules[], and recommendations[]; BLOCK reasons are present for 100% of blocked recipients. - Given invalid recipient records are present, When processing, Then those are returned with error items using the defined error taxonomy (see criteria on taxonomy) and do not halt the job. - Given the same jobId is requested after completion, When results are fetched, Then the same decisions are returned and are immutable for 24 hours.
Idempotency & Rate Limiting Semantics
- Given POST /v1/preflight or POST /v1/bulk-precheck is called with Idempotency-Key header, When the exact same request (method, path, body, tenant) is retried within 24 hours, Then the service returns 200 with an identical response body (excluding Server-Date) and header Idempotent-Replay: true. - Given a different body is sent with a previously used Idempotency-Key within 24 hours, When processed, Then the service returns 409 Idempotency-Key-Conflict with stable error code PRECHK.IDEMPOTENCY_CONFLICT. - Given a tenant sends sustained traffic, When calling /v1/preflight, Then per-tenant rate limit is >= 100 RPS sustained with burst up to 200 RPS for 60 seconds; excess requests receive 429 with Retry-After, X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers. - Given rate limited requests are retried respecting Retry-After, When retried, Then at least 99% succeed without further throttling under the stated limits.
Structured Decision Payload & Error Taxonomy
- Given any decision response, When inspecting the JSON, Then it includes: decision, decisionId (UUIDv4), correlationId, timestamp (RFC3339), affectedRules[] [{ruleId, category, severity, shortCode, description}], and recommendations[] [{type, value, rationale}]. - Given the client supplies locale=es-ES (or Accept-Language), When receiving the response, Then rationale.description and recommendation.rationale are localized to the requested locale with fallback to en-US if unavailable; decision enums remain in English. - Given a request fails, When returning an error, Then the payload includes errors[] [{code, message, field?, docsUrl, retryable}], where code is stable and namespaced (e.g., PRECHK.INVALID_INPUT, PRECHK.RATE_LIMIT, PRECHK.OUTAGE, PRECHK.UNAUTHORIZED, PRECHK.IDEMPOTENCY_CONFLICT), and HTTP status aligns with the code. - Given WARN outcomes, When recommendations are present, Then at least one recommendation reduces risk to ALLOW (e.g., schedule change or approved template id) and includes sufficient data for UI action without additional API calls.
Webhook Emission for Decision Events
- Given a single-message decision is produced, When webhooks are enabled, Then an event type preflight.decided is delivered within 5 seconds with eventId, decisionId, tenantId, and HMAC-SHA256 signature (header X-SmileCue-Signature: t=epoch,sig=hex) using the configured shared secret. - Given a bulk precheck job completes, When emitting webhooks, Then event type bulk_precheck.completed is delivered within 10 seconds including summary counts and a URL to fetch paginated results. - Given the subscriber endpoint returns non-2xx, When retrying, Then the service performs at least 6 retries with exponential backoff (initial 5s, max 5m) and dead-letters after final failure; deliveries are at-least-once with eventId enabling deduplication by the consumer. - Given multiple events for the same decisionId, When delivered, Then ordering is preserved per decisionId.
Automation Engine Gate & Dispatch Enforcement
- Given an automation trigger attempts to enqueue a message, When the preflight decision is BLOCK, Then the automation engine prevents scheduling, records the reason, and surfaces the recommendation; no downstream delivery task is created. - Given the preflight decision is ALLOW, When enqueueing, Then the automation engine proceeds and attaches decisionId to the delivery task for traceability. - Given a delivery adapter is invoked at dispatch time, When the attached decisionId corresponds to BLOCK or is missing, Then the adapter MUST refuse dispatch and log PRECHK.ENFORCEMENT_BLOCK with the decisionId/correlationId. - Given the preflight service is unreachable at dispatch time for messages without cached decisions, When attempting to dispatch, Then the adapter blocks send and emits a degraded.enforced event.
Degradation-Safe Defaults & Decision Cache
- Given the preflight service is unavailable or exceeds a 300 ms timeout, When a decision is required, Then the system checks a local/cache or Evidence Vault entry for an identical input fingerprint; if a valid ALLOW decision exists from <= 24 hours ago, it is reused; otherwise the decision is UNKNOWN_BLOCKED and the send is prevented. - Given degraded mode is entered, When operating, Then a degraded.mode event is emitted once per tenant per 5 minutes and the UI displays a banner via the in-composer validator indicating conservative blocking. - Given service recovery, When health checks pass for 2 consecutive minutes, Then degraded mode auto-clears and normal decisions resume; any pending queued sends are re-evaluated before dispatch. - Given cached WARN decisions exist, When recommendations can be auto-applied (e.g., nextAllowedSendTime within 2 hours), Then the system schedules a recheck at the recommended time automatically.

Branch Diff

Visually compare message trees at a glance. Branch Diff highlights copy, timing, and channel changes node-by-node, shows expected impact and past performance annotations, and supports one-click reuse of winning nodes across templates. Clear, actionable diffs make iteration fast and collaborative.

Requirements

Node-by-Node Diff Visualization
"As a practice manager, I want to see a clear, node-by-node comparison of two outreach templates so that I can quickly understand what changed and assess risk before publishing."
Description

Render two message templates (or versions) as aligned trees and highlight granular changes at the node level, including copy edits, timing offsets, channel switches, property additions/removals, and node moves. Use consistent color-coding and icons for change types, with toggles to show/hide categories (copy/timing/channel/structure). Support large templates via virtualized tree rendering, search, and focus/expand controls. Perform tree-diff using stable node IDs with fallback fuzzy matching on path and content to handle renamed or moved nodes. Provide a summary header with counts of changes and quick-jump navigation. Integrates with SmileCue’s template store and permissions model to ensure users only diff templates they can access. Outcome: practitioners can see what changed at a glance, reducing review time and errors.

Acceptance Criteria
Aligned Tree Rendering and Change Highlighting
Given two templates (A and B) are selected and the user has read access to both When the diff view loads Then both templates render as side-by-side aligned trees with nodes matched across versions And copy edits are highlighted as "copy" changes, timing offsets as "timing" changes, channel switches as "channel" changes, and adds/removes/moves as "structure" changes And each change type is consistently annotated with a distinct icon and color as shown in the on-screen legend And hovering or selecting a changed node reveals before/after values and the exact delta And moved nodes display their source and destination paths And unchanged nodes are visually de-emphasized
Category Toggles and Legend
Given the diff view is loaded When the user toggles off a change category (copy, timing, channel, structure) Then all annotations of that category are hidden, affected nodes are visually de-emphasized, and the summary counts update accordingly And quick-jump navigation and search results respect the active category filters And the legend remains visible, reflecting the active categories And the toggle state persists for the user across sessions within the same workspace
Virtualized Rendering and Performance at Scale
Given two templates each containing at least 5,000 nodes When the diff view is opened and the user scrolls from top to bottom Then initial content renders within 2 seconds on Chrome desktop (v120+), 4-core 2.5 GHz CPU, 8 GB RAM And average scroll frame rate is at least 45 FPS with no frame exceeding 100 ms at p95 And concurrent DOM element count does not exceed 800 during scrolling And expanding or collapsing a subtree completes within 150 ms at p95
Search, Focus, and Expand Controls
Given the diff view is loaded When the user searches for text "recall" Then the number of matches is shown, matched nodes are highlighted in both trees, and each matching node's ancestors auto-expand to be visible And pressing Next/Prev navigates sequentially to each match and scrolls it into view When the user searches by node ID "node-123" Then that node is located, focused, and scrolled into view with its change annotation (if any) When the user enables Focus mode on a node Then only that subtree is displayed, breadcrumbs show the full path, and exiting Focus restores the previous expanded/collapsed state
Stable ID and Fallback Fuzzy Matching
Given nodes with identical stable IDs exist in both templates When the diff is computed Then these nodes are matched even if their names or positions have changed Given a node lacks a matching stable ID When fallback matching runs Then a deterministic fuzzy match based on normalized path and content pairs the node only if the similarity score is at least 0.85; otherwise it is treated as added/removed And if a matched node's parent path differs between versions it is flagged as "moved" And copy differences within matched nodes are shown as token-level inline deltas And running the same diff twice on the same inputs yields identical mappings and change counts
Summary Header and Quick-Jump Navigation
Given the diff view is loaded Then the summary header displays total changes and counts by category (copy, timing, channel, structure) When the user clicks a category chip or the "next change" control Then the viewport jumps to the next change of that category and visibly selects it And a progress indicator shows the current index and total for the active filter set When category filters or search are applied Then the summary counts and progress indicator update to reflect only visible changes
Template Access and Permissions Enforcement
Given the user navigates to Branch Diff When selecting templates to compare Then only templates the user has READ access to are searchable and selectable Given the user opens a saved diff URL without READ access to either template Then an access denied screen is shown without revealing template names or content, and no diff data is fetched And an audit event is recorded with user ID, attempted template IDs, timestamp, and outcome And the diff view does not load or display any patient PHI; only template metadata and copy are queried
Performance & Impact Annotations
"As an office manager, I want to see historical results and expected impact next to each change so that I can choose the best version with confidence."
Description

Overlay historical performance metrics and projected impact for each changed node directly within the diff. Pull node-level KPIs (confirmation rate, response rate, opt-outs) from analytics by selected timeframe and segment (e.g., hygiene recall, new patients), and display confidence indicators and significance badges. Show projected impact deltas for proposed changes using a lightweight prediction service (heuristics initially, model-driven later) with transparent assumptions. Provide tooltips linking to underlying data and a per-diff summary of expected overall effect. Enforce PHI minimization by aggregating metrics and filtering small cohorts. Outcome: users make evidence-based edits faster, improving confirmation rates while reducing trial-and-error.

Acceptance Criteria
Node Metrics Overlay by Timeframe and Segment
Given Branch Diff is open and a timeframe and segment are selected When the diff renders Then each changed node displays confirmation rate (%), response rate (%), and opt-out rate (%) aggregated for the selected filters, plus sample size n Given the same filters are applied in Analytics When KPI values are compared Then node-level KPIs match within ±0.1 percentage points for rates and ±1 for sample size Given a node has no qualifying events in the selection When the diff renders Then the node shows "No data" with a tooltip explaining the reason Given a user changes the timeframe or segment When the selection changes Then KPIs refresh within 2 seconds and the selection persists for that user on next load
Confidence and Significance Indicators Display
Given baseline metrics exist for a changed node and cohort size ≥ 20 When current vs baseline KPIs are compared Then a confidence indicator (95% CI) is shown and a badge displays "Significant" if p < 0.05, otherwise "Not significant" Given cohort size < 20 or opt-out events < 5 When rendering indicators Then confidence and significance badges are suppressed and an "Insufficient data" helper appears Given the confidence level setting is 95% When recalculating indicators Then CIs and significance use the 95% level consistently across all nodes
Projected Impact Deltas and Assumptions Panel
Given a proposed change exists for a node When the prediction service responds Then the node shows projected delta for confirmation and response rates as +/-% with a low–high range and a confidence label Given the user clicks Assumptions on a node When the panel opens Then it lists baseline values, heuristic parameters, channel weights, timing adjustments, sample size used, and last updated timestamp Given the prediction service is unavailable or exceeds a 2s timeout When rendering projections Then the UI displays "Prediction unavailable" without blocking the diff and logs a non-blocking error event
Tooltip Links to Underlying Data
Given a KPI or badge is hovered When the tooltip appears Then it contains a "View in Analytics" link pre-filtered to node ID, timeframe, and segment and opens in a new tab Given the user lacks analytics permission When hovering or clicking the link Then the link is disabled and a tooltip states "Insufficient permissions" Given the link is followed by an authorized user When the analytics page loads Then the report shows the same values as the diff within the specified tolerances
Per-Diff Overall Effect Summary
Given at least one node has a projection When the diff loads Then a summary displays weighted overall expected change in confirmation rate and no-show rate with a low–high range, number of nodes included, and count excluded for insufficient data Given node reach weights are available When computing the summary Then weights are derived from historical node reach within the selected timeframe and segment and totals are auditable from node-level values Given no nodes have projections When the diff loads Then the summary states "No projections available" and indicates the reason (e.g., insufficient data)
PHI Minimization and Small Cohort Suppression
Given annotations, tooltips, and summaries are rendered When inspecting UI and network payloads Then no patient identifiers, phone numbers, email addresses, or message bodies are present; only aggregated metrics, node IDs, timeframes, and segments Given cohort size < 20 or opt-out events < 5 for a node When rendering that node Then KPIs, badges, links, and projections are suppressed and an "Insufficient data" label is shown Given usage and error events are logged When reviewing logs Then entries contain no PHI and only aggregate values and metadata required for diagnostics
One-Click Node Reuse Across Templates
"As a hygienist lead, I want to reuse a proven reminder node in another recall flow so that I can roll out what works without rebuilding it from scratch."
Description

Enable users to copy a winning node or subtree from the diff view and insert it into another template with a single action. Perform compatibility checks for variables, channels, timing constraints, and guardrails (e.g., quiet hours, consent). Map and validate merge fields, suggest fixes for missing variables, and preserve formatting and branching logic. Maintain provenance metadata (source template, version, timestamp, author) to support future audits and rollbacks. Provide optional link-and-sync behavior so updates to a canonical node can be propagated. Outcome: best-performing content is easily reused, accelerating iteration and standardizing quality across campaigns.

Acceptance Criteria
One-Click Insert From Diff View
Given a user is in Branch Diff with a source template and a target template loaded And the user has edit permission on the target template When the user selects a node or subtree and chooses "Reuse in…" and selects an insertion point in the target Then the system inserts the selected node/subtree into the target at the chosen location And preserves copy, formatting, channels, timing offsets, and branching logic exactly as in the source And displays a success message indicating the number of nodes inserted And completes the insertion within 2 seconds for a single node and within 5 seconds for subtrees up to 50 nodes
Compatibility Validation and Blocking Rules
Given the selected node/subtree includes variables, channels, timing, and guardrail rules And a target template with its own configuration is selected When the user initiates reuse Then the system validates variable availability, channel support, timing constraints, quiet hours, and consent requirements before insertion And prevents insertion if any blocking incompatibilities exist (e.g., unsupported channel, missing required consent) And presents a validation report listing all issues with severity (Blocker/Warning) and suggested fixes And allows insertion only when all blockers are resolved; warnings may be acknowledged to proceed
Merge Field Mapping and Suggestions
Given the source node/subtree contains merge fields And the target template has a defined merge field schema When the user initiates reuse Then merge fields with identical names and compatible types are auto-mapped And unmapped fields are suggested based on name similarity and data type And the user can confirm or adjust mappings prior to insertion And insertion is blocked if any required merge field remains unresolved And a preview displays example resolved values using a selectable test patient profile
Quiet Hours and Consent Enforcement
Given the reused node triggers outbound messages (SMS, email, voice) And the account defines quiet hours and consent policies per channel When the proposed send time or channel would violate quiet hours or consent Then the system adjusts timing according to policy or blocks the insertion with an explanation of violations And records the policy evaluation outcome in the audit log tied to the reused node And ensures scheduled sends produced by the reused node respect quiet hours and consent at runtime
Provenance Metadata Captured
Given a node or subtree is successfully reused When the insertion completes Then the system records provenance metadata including source template ID, version, node ID(s), author, timestamp, and diff reference And displays provenance in the node properties panel in the target template And includes provenance fields in exports and API responses for the node And ensures metadata supports traceability for audit and rollback operations
Link-and-Sync Propagation
Given the user chooses to insert the node/subtree as a linked reusable component And the source (canonical) node is later updated to a new version When the update is available Then linked instances show a pending update with a change summary and preview diff And the user can apply, schedule, or skip the update per target template And applying the update propagates content, formatting, timing offsets, and branching logic And target-specific variable mappings are preserved when still compatible And all propagation actions are logged with user, time, source version, and target versions
Rollback to Prior Reused Version
Given a reused node with provenance exists in a target template And subsequent edits or sync updates have been applied When the user selects Rollback and chooses a prior version Then the node reverts to the selected version And provenance and version history remain intact And future sync eligibility is recalculated based on the reverted version And the rollback event is recorded in the audit log
Template Version & Comparison Selector
"As a dental office administrator, I want to quickly select and compare any two template versions so that I review the correct changes before approval."
Description

Provide a selector to choose any two items to compare: template-to-template, version-to-version, or draft vs. published. Include filters by date range, author, tag, and patient segment; show key metadata (publish date, approvals, change notes) for context. Support diffing against baselines (e.g., last published) and quick actions to promote or rollback. Offer deep links that encode the comparison for easy sharing and review. Integrates with SmileCue’s versioning, release workflow, and access controls. Outcome: users can consistently pick the right artifacts to compare, reducing mis-comparisons and rework.

Acceptance Criteria
Selecting Two Artifacts for Comparison
- Rule: The selector supports these valid pairings: (a) Template A (latest published) vs Template B (latest published); (b) Version X vs Version Y of the same template; (c) Draft vs Last Published of the same template. - Rule: The Compare action remains disabled until exactly two valid artifacts are selected. - Rule: Each selection visibly includes: template name, template ID, version label (Draft/Published vN), and patient segment badge. - Rule: Selecting the identical artifact on both sides is blocked with an inline error explaining the conflict. - Rule: Search and pickers allow lookup by template name, ID, author, and tag; pressing Enter confirms the highlighted choice.
Filtering Comparison Candidates by Date, Author, Tag, Segment
- Given the selector is open, when a date range is applied, then only artifacts with last modified/published dates within the range are shown. - When multiple filters (author, tag, patient segment) are applied, the result set is the intersection (AND) of those filters. - Clearing filters returns the candidate list to the default (unfiltered) state. - Active filters are displayed as removable chips and are persisted while the selector is open. - The applied filters are encoded into the comparison deep link.
Displaying Metadata for Each Candidate in Selector
- For each candidate item, the list shows: publish date (or — for drafts), approvals status/count, and the latest change notes (truncated to 120 chars) with tooltip for full text. - Metadata values match the backend versioning records for the selected artifact. - Draft items are clearly labeled "Draft"; published items show version label "vN" and publish date. - Items without approvals or change notes display explicit placeholders (e.g., "No approvals", "No change notes").
Baseline Diff and Quick Promote/Rollback Actions
- The selector offers "Baseline: Last Published" as a selectable comparator for the current template. - When a draft is selected against the baseline, quick actions include: Promote Draft to Published and Rollback to Previous Published (if a prior published version exists). - Quick actions require the user to have Release:Publish permission; otherwise, actions are hidden or disabled with an explanatory tooltip. - Executing an action shows a confirmation modal with the target version and impact summary; on confirm, the action completes and the selector refreshes to reflect the new baseline/version. - Each action writes an audit log entry with actor, timestamp, artifact IDs, and action type.
Deep-Linking a Specific Comparison State
- A "Copy Link" control generates a URL that encodes left/right artifact IDs, baseline flag (if used), and any active filters. - Opening the deep link reconstructs the exact selector state (both selections, filters, and baseline) for any authorized user. - If an encoded artifact no longer exists, the selector loads with a clear "Item not found" message on that side and prompts to pick a replacement. - If the user lacks access to an encoded artifact, the selector loads with an "Access denied" state on that side and prevents Compare. - Deep links are stable across sessions and environments of the same workspace/tenant.
Access Control Enforcement in Selector and Deep Links
- The candidate list only includes artifacts for which the user has read access; restricted items are not displayed or selectable. - Quick actions (promote/rollback) are only visible and executable for users with the required permissions; server-side enforcement rejects unauthorized attempts. - When opening a deep link that includes an unauthorized artifact, the UI redacts details and displays an access warning without leaking metadata. - All access decisions are logged with user ID, artifact ID, decision, and reason code.
Mis-Comparison Prevention and Validation
- Attempting to select versions from different templates for a version-to-version comparison is blocked with the message: "Select versions from the same template". - For template-to-template comparisons across different patient segments, the selector shows a prominent non-blocking warning: "Different patient segments" and allows the user to proceed. - If both sides reference the same artifact (same template and version), the Compare action is disabled and an inline hint suggests selecting a different item. - When launched from a specific template page, the selector pre-fills one side with that template's Last Published as the default baseline to reduce mis-selections.
Collaborative Comments & Suggestions
"As an office coordinator, I want to leave comments tied to exact changes so that my team can resolve questions and approve updates faster."
Description

Allow users to comment on specific nodes or changes within the diff, mention teammates, attach rationale, and resolve threads. Support suggestion mode to propose copy/timing edits that can be accepted into the draft. Send in-app and email notifications respecting user preferences; maintain an activity timeline per comparison. Enforce HIPAA-safe guidelines by blocking PHI in comments via pattern checks and providing admin-configurable retention/redaction rules. Outcome: cross-role teams collaborate asynchronously, speeding approvals while maintaining compliance.

Acceptance Criteria
Node-Level Commenting, Mentions, and Thread Resolution
Given a Branch Diff view, When a user clicks Comment on a node or specific change, Then the comment is anchored to that element and a visible pin/badge appears on the node/change. Given a comment composer, When the user types @ and selects a teammate, Then the mention is inserted, the teammate is recorded as a mention target, and the mention is highlighted in the draft. Given a thread exists, When another user replies, Then replies appear in chronological order with avatar, role, and timestamp in the practice timezone and unread indicators for non-viewers. Given a thread is open, When a user with Resolve Comments permission marks it Resolved, Then the thread status changes to Resolved, collapses, and is hidden by default unless Show resolved is enabled. Given a comment posted within 15 minutes, When the author edits or deletes it, Then the change is applied and an edited/deleted marker and immutable edit history are recorded for admins.
Suggestion Mode Edits and Acceptance into Draft
Given Suggestion Mode is enabled, When a user proposes an edit to a node’s copy, timing, or channel, Then the suggestion is displayed inline with add/delete markup and attribution to the proposer. Given a suggestion is created, When the user adds rationale text, Then the rationale is saved and displayed with the suggestion in its thread (optional by default). Given a suggestion is pending, When a user with Accept Suggestions permission clicks Accept, Then the draft template updates to the suggested value, the diff refreshes, and an audit record (who, what, when, before/after) is added to the timeline. Given a suggestion is pending, When a user clicks Reject and provides a reason, Then the suggestion is marked Rejected with the reason stored and no draft changes are applied. Given multiple suggestions target the same field, When one is accepted, Then conflicting suggestions are auto-marked Superseded with a link to the accepted change. Given a timing suggestion is accepted, When recalculation runs, Then downstream schedule previews are updated within 5 seconds.
Notification Preferences and Delivery SLAs
Given a user has notification preferences (in-app, email, digest, quiet hours), When they are mentioned, assigned, or their suggestion is accepted/rejected, Then notifications are sent according to those preferences and quiet hours are respected. Given an in-app notification is enabled, When a triggering event occurs, Then the in-app badge increments within 30 seconds and the notification contains a deep link to the anchored node/change. Given email notifications are enabled and not in quiet hours, When a triggering event occurs, Then an email is sent within 5 minutes containing comparison name and action type and excluding any PHI content. Given a user has disabled email for mentions, When they are mentioned, Then no email is sent while in-app notification is still delivered. Given a notification is received, When the user clicks its link, Then the Branch Diff opens to the correct comparison and auto-scrolls/highlights the anchored item.
HIPAA PHI Detection and Blocking in Comments and Suggestions
Given the comment/suggestion composer, When content includes PHI patterns (e.g., full name with DOB, 10+ digit phone, email address, SSN/MRN), Then submission is blocked, matched substrings are highlighted, and an error explains PHI is not allowed. Given an attachment is added, When client-side and server-side scans detect PHI indicators, Then the attachment is rejected before storage and no file bytes are persisted. Given admin-configured PHI rules (allow/deny patterns and exceptions) exist, When content is validated, Then those rules are applied before storage and the decision is logged for audit. Given a submission is blocked, When the user requests guidance, Then allowed examples and suggestions are displayed without storing the blocked content. Given a posted comment passes initial checks, When an asynchronous PHI re-scan detects PHI, Then content is auto-redacted with [REDACTED], the author is notified, and a timeline event is recorded.
Admin Retention and Redaction Policies
Given workspace retention is set to N days, When a comment or suggestion reaches day N+1, Then its content is auto-redacted and replaced with a placeholder while metadata (author, timestamps, action type) is preserved. Given a legal hold is applied by an admin, When retention would otherwise redact content, Then the content remains accessible to admins and is hidden from non-admins with a Held banner. Given a data export is requested by an admin, When exporting comparison activity, Then redacted content remains redacted in the export and no PHI is included. Given a user deletes their own comment, When deletion is confirmed, Then the content is removed for all users and a tombstone entry displays comment deleted by author with timestamp. Given retention settings are changed, When saved, Then the new policy applies prospectively and a configuration change event appears in the audit log.
Per-Comparison Activity Timeline and Export
Given a Branch Diff comparison, When any collaboration event occurs (comment, mention, suggestion created/accepted/rejected, resolve/reopen, PHI redaction, notification delivery), Then the per-comparison timeline records the event with actor, UTC and local timestamp, and a link to the anchored item. Given the timeline view, When filters by event type, actor, or date range are applied, Then results update within 1 second and persist across page refresh for that comparison. Given the timeline exceeds 1000 events, When the user scrolls, Then infinite loading is used with no more than 200 ms frame delay on median hardware. Given an export is requested from the timeline, When the user clicks Export CSV, Then a CSV is generated within 30 seconds containing the currently filtered events and an integrity hash. Given a timeline event points to deleted or redacted content, When opened, Then the viewer shows available metadata and a clear message without exposing removed content.
Role-Based Permissions and Access Controls
Given workspace roles (Admin, Editor, Commenter, Viewer), When a user attempts to comment or suggest, Then only roles with permission can perform the action; others see disabled controls with a tooltip explaining required permission. Given an external collaborator has restricted access, When they view a comparison, Then they can see threads they are mentioned in but cannot accept suggestions unless explicitly granted by an Admin. Given a template is locked, When an Editor attempts to accept a suggestion affecting that template, Then the action is blocked and a Request approval workflow can be sent to Admins. Given a private thread is created with role restrictions, When a non-authorized user views the comparison, Then the thread is not visible or discoverable via search or notifications. Given an SSO user is deprovisioned, When they previously authored comments or suggestions, Then their content remains with a Deactivated badge and the user immediately loses access.
HIPAA-Compliant Audit Logging for Diff Actions
"As a compliance officer, I want complete audit trails of diff views and edits so that we can meet HIPAA and internal audit requirements."
Description

Capture immutable audit logs for all Branch Diff activities, including views, comparisons made, node reuse operations, suggestions accepted, and exports. Record user ID, timestamp, artifact IDs, before/after snapshots, and rationale where provided. Store logs in write-once storage with encryption at rest and in transit, apply retention policies, and expose admin search/export for compliance reviews. Integrate with SSO/role-based access to ensure least-privilege access to logs. Outcome: the feature remains fully auditable and compliant with HIPAA and organizational policies.

Acceptance Criteria
Log Mandatory Fields for Branch Diff Actions
- Given an authenticated user performs a Branch Diff action (view diff, run comparison, accept suggestion, reuse node, export), When the action completes (success or failure), Then a single audit log record is appended within 1 second containing userId (from SSO), actionType, timestamp (UTC ISO-8601 with millisecond precision), artifactIds (e.g., templateId, diffId, nodeIds as applicable), requestId, and outcome (success|failure with errorCode if failure). - Given a Branch Diff view action, When the view is rendered, Then an audit record is created with the above mandatory fields and actionType=view. - Given a Branch Diff comparison action, When the comparison is executed, Then an audit record is created with the above mandatory fields and actionType=comparison. - Given a Branch Diff export action, When the export is initiated, Then an audit record is created with the above mandatory fields and actionType=export and includes exportFormat. - Then the audit log entry becomes queryable via the admin search within 5 seconds of creation.
Before/After Snapshots and Optional Rationale for Mutating Actions
- Given a node reuse operation, When the operation is executed, Then the audit log record includes beforeSnapshot and afterSnapshot for affected nodes in JSON, each with schemaVersion and sha256 checksum, and contains the affected artifactIds. - Given a suggestion is accepted, When the acceptance is confirmed, Then the audit log record includes beforeSnapshot and afterSnapshot of the changed nodes or template segments, and includes the suggestionId. - Given the user provides a rationale during a mutating action, When the log is written, Then rationale is captured verbatim; When no rationale is provided, Then rationale is stored as null. - Then snapshots exclude patient-identifiable data and contain only template or configuration content. - Then each snapshot is immutable and verifiable by its checksum.
Immutable WORM Storage and Encryption for Audit Logs
- Then audit logs are written to append-only, write-once-read-many (WORM) storage where modification and deletion are technically blocked until retention expiry. - Then encryption at rest is enabled using AES-256 or stronger, and encryption in transit uses TLS 1.2+ for all write/read paths. - Given an attempt to update or delete a log record before retention expiry, When the request is made, Then the system rejects it with a 403/AccessDenied and records the attempt in a separate security log. - Then cryptographic integrity (e.g., per-record checksum or chain) allows detection of tampering for any log batch.
Retention Policy Enforcement and Legal Hold
- Given an organization-level retention policy (default 6 years) is configured, When audit logs are stored, Then their retention expiration is computed and persisted per record and cannot be shortened below policy by non-privileged users. - When a log passes its retention expiration, Then it is purged within 30 days and a purge summary record is generated and retained separately per policy. - Given a legal hold is applied to a scope (org/user/time range/artifact), When retention expiration is reached, Then the affected logs are not purged until the hold is released and the hold metadata (reason, appliedBy, appliedAt) is auditable. - Then changes to retention settings or legal holds require an authorized role and are themselves audited.
Least-Privilege RBAC and SSO Integration for Log Access
- Given SSO is enabled, When a user signs in, Then roles are derived from SSO groups and only users with Compliance Auditor or Super Admin may view/search/export audit logs. - Given a user without an authorized role requests log access, When the request is made, Then access is denied (403) and the attempt is audited. - Then users can only access audit logs within their own tenant/organization scope. - Then all read, search, and export access to audit logs is itself recorded as audit events with userId, timestamp, actionType=log.access and filters used.
Admin Search and Export for Compliance Reviews
- Given an authorized admin, When they search logs by filters (date range, userId, actionType, artifactId, outcome), Then the results match the filters exactly and return within 5 seconds for a dataset up to 1 million records. - When an export is initiated from a filtered result set, Then the system generates CSV and JSON exports containing the selected records and an export manifest including filter criteria, time window, record count, and SHA-256 checksum. - Then the export files are encrypted in transit, stored with server-side encryption at rest, and delivered via a time-limited signed URL that expires within 24 hours by default. - Then the export action is audited with userId, timestamp, filters used, export formats, file sizes, and checksums.
Secure Share & Export of Diffs
"As a practice owner, I want to share a read-only diff with my consultant so that they can review proposed changes without accessing patient data."
Description

Provide secure sharing and export options for diffs, including expiring view-only links and watermarked PDF/PNG exports. Enforce access controls, optional password protection, and IP allowlisting. Redact or obfuscate patient-identifiable placeholders and variable previews in exports. Embed metadata (template IDs, versions, generated date) for traceability. Outcome: stakeholders can review changes outside the app when needed without risking data leakage.

Acceptance Criteria
Expiring View-Only Share Links
Given an authorized SmileCue user generates a share link for a Branch Diff with an expiration time and optional password and IP allowlist When a recipient opens the link before expiration and meets IP and password requirements Then the diff renders read-only with no edit, reuse, or export controls visible And the link enforces expiration at the configured time; after expiry or revocation, requests return 410 with a generic, non-identifying message And mismatched IP or invalid/missing password returns 403 without revealing whether the link exists And the link token is unguessable (>=128 bits entropy); access attempts are rate-limited to mitigate brute force And each access and denial is written to the audit log with timestamp (UTC), IP, user agent, link ID, and outcome
PDF Export with Watermark, Metadata, and Redaction
Given a user exports a Branch Diff to PDF Then the PDF includes a visible repeating watermark containing "SmileCue Confidential", export ID, template IDs and versions, and generated date/time (UTC) And the PDF document properties embed metadata: templateA.id, templateA.version, templateB.id, templateB.version, branchDiff.version, exportId, generatedAt And any PHI/PII placeholders and variable previews (e.g., {{patient_name}}, {{phone}}) are redacted or obfuscated in all pages, headers, footers, and annotations And the visual diff (copy, timing, channel icons, highlights) matches the in-app view for the selected templates And if the user enables password protection, the PDF requires a password to open
PNG Export with Watermark and Redaction
Given a user exports a Branch Diff to PNG Then the export produces one or more PNG files that include a visible repeating watermark as in the PDF export And all PHI/PII placeholders and variable previews are redacted or obfuscated And if password protection is enabled, the PNGs are delivered as a password-protected ZIP archive And the visual diff content matches the in-app view
IP Allowlisting on Share Links
Given a share link configured with one or more allowlisted CIDR ranges (IPv4 and IPv6) When a recipient requests the link Then access is granted only if the source IP falls within an allowlisted range And non-allowed requests receive 403 with no resource existence disclosure And allowlist configuration supports at least 50 entries and validates format at save time And all allow/deny decisions are logged with evaluated IP and matched rule
Redaction Coverage and Verification
Given any share view or exported asset produced by Secure Share & Export of Diffs Then zero patient-identifiable data is present: placeholders rendered as tokens (e.g., {{patient_*}}) remain tokenized or are replaced with [REDACTED]; sample data previews are suppressed And email addresses, phone numbers, and names are masked if present in message copy And a redaction test suite with representative templates passes, detecting 0 unredacted PHI instances
Audit Trail and Traceability
Given a user generates a share link or an export, and recipients view/download them Then the system records audit events for create, view, deny, download, revoke with fields: actor (user ID if authenticated), timestamp (UTC), IP, user agent, action, link/export ID, template IDs/versions And admins can filter and retrieve these events by date range, action, and identifier And audit records are immutable and retained per policy
Revocation and Regeneration Behavior
Given a link owner revokes a share link or changes its password/allowlist When a recipient attempts access afterward Then the link is invalid within 60 seconds across caches and returns 410 (revoked) or 403 (policy change) without content leakage And the owner can generate a new link; the new link uses a new token and does not reactivate the old link And previously generated exports remain accessible only to the owner in-app and carry watermarks; they are not accessible via the revoked link

Safe Publish

Promote winners without stress. Safe Publish stages rollouts by location/provider, supports switchbacks and holdouts, and auto-rolls back if KPIs dip. One click updates live templates, writes an audit trail, and notifies stakeholders. Improvements go live smoothly, with protection for your schedule and patients.

Requirements

Segmented Staged Rollouts
"As an office manager, I want to roll out template updates by location and provider so that I can minimize risk and validate impact before a full release."
Description

Enable staged deployments of messaging template changes by segment (location, provider, insurance cohort, or percentage-based canary). Provide scheduling windows, ramp-up percentages, and eligibility rules aligned with SmileCue’s patient segmentation. Ensure atomic, isolated activation per segment with real-time status, progress, and the ability to pause/resume without affecting other segments. Integrate with existing template engine and scheduling to avoid sending during blackout hours and respect patient communication preferences.

Acceptance Criteria
Location-Based Staged Rollout with Scheduled Windows
Given a rollout R for template T1 targeting Location=Downtown only with ramp schedule [10%, 50%, 100%] and scheduling window Mon–Fri 09:00–17:00 in the practice timezone, and blackout hours 12:00–13:00 And there are 1,000 eligible Downtown patients and 800 eligible Uptown patients When R is activated at 08:50 on Monday Then no messages are sent before 09:00 And between 09:00–12:00 only Downtown patients are messaged and the sent count is 100 ±1 due to rounding (10% of eligible respecting opt-outs/channel preferences) And no messages are sent between 12:00–13:00 And between 13:00–17:00 additional messages are sent to Downtown to reach 50% cumulative (500 ±1 total), Uptown remains at 0 And at the next ramp to 100%, remaining eligible Downtown patients are messaged only within the allowed windows And total sent never exceeds the count of eligible Downtown patients after applying opt-outs and channel preferences And no messages are sent to Uptown during the rollout
Provider Segment Atomic Activation and Isolation
Given a rollout R with two provider segments: Provider=Dr. Lee and Provider=Dr. Chen, each with independent activation toggles but the same template T2 When the Dr. Lee segment is activated and the Dr. Chen segment remains inactive Then only patients scheduled with Dr. Lee receive messages; Dr. Chen’s patients receive none And pausing the Dr. Lee segment immediately halts new scheduling and queue dispatch for that segment without canceling already sent messages And resuming the Dr. Lee segment schedules from the next eligible times without duplicating any previously sent messages And actions (activate, pause, resume) are isolated to the selected segment and do not impact the other segment’s schedules, queues, or metrics
Insurance Cohort Eligibility and Preference Compliance
Given a rollout R targeting InsuranceCohort=PPO-A with dynamic cohort membership and defined patient communication preferences (opt-out, channel priority) And there are 2,000 eligible patients at creation time When R is active and a patient changes insurance cohort before their scheduled send Then inclusion is recalculated at send time so only current PPO-A patients are messaged And patients who opt out after scheduling but before send are excluded And if a preferred channel is unavailable, the system applies channel fallback rules without violating do-not-contact flags And no messages are sent during defined blackout hours for any included patient
Percentage-Based Canary Ramp-Up with Stable Membership
Given a rollout R using percentage-based selection with a stable hashing strategy over eligible patient identifiers And the eligible population size after applying preferences and blackout constraints is N When the ramp is configured to 5% -> 25% -> 50% -> 100% Then the selected subset at each ramp equals floor(p% * N) ±1 due to rounding And the selected set grows monotonically: patients included at 5% remain included at 25%, 50%, and 100% And non-selected patients receive no messages until their cohort becomes included at a higher ramp And rerunning selection with the same rollout ID and inputs yields the same patient subset
Real-Time Segment Status and Metrics Accuracy
Given an active rollout R with multiple segments producing message events (queued, sent, delivered, failed) When a user opens the rollout status view or calls the status API for a specific segment Then status reflects the true lifecycle state (Planned, Active, Paused, Completed) within 10 seconds of a change And metrics for Eligible, Selected, Queued, Sent, Delivered, Failed reconcile to underlying message logs within ±0.5% or 5 messages, whichever is larger And progress percentage is computed as Sent/Selected and matches the count-based metrics And timestamps are shown in the practice timezone with explicit timezone labels
Per-Segment Pause, Resume, and Switchback Safety
Given two active segments S1 and S2 in rollout R using template version v2 (previous version v1 available) When S1 is paused Then S1 stops scheduling and dispatch immediately while S2 continues unaffected And unsent S1 messages remain pending and are not delivered until resume When S1 is resumed Then S1 resumes scheduling from the next eligible windows without duplicating any messages previously sent When S1 is switched back to template version v1 Then subsequent S1 messages use v1, previously sent S1 messages remain immutable, and S2 remains on v2 And no patient receives more than one message per appointment per channel due to pause/resume/switchback actions
Template and Scheduler Integration with Blackout and Timezone Compliance
Given a rollout R referencing template T3 with tokens for appointment, provider, and location, and scheduler rules with blackout windows and quiet hours And patients may have timezones different from the practice timezone When messages are prepared for dispatch Then T3 renders without unresolved tokens; messages with missing required data are skipped and logged with error details And blackout/quiet hours are enforced using patient timezone when available, otherwise practice timezone And scheduling ensures no dispatches outside allowed windows and no duplicate sends occur if existing messages were already scheduled for the same appointment And the applied template version is consistent for each segment at send time (atomic per segment)
KPI Guardrails & Auto-Rollback
"As a practice operations lead, I want automatic rollback when KPIs dip so that schedule health and patient experience are protected without constant monitoring."
Description

Continuously monitor key KPIs (confirmation rate, opt-out rate, delivery failures, reply sentiment, and no-show proxy) during and after rollout. Allow configurable thresholds, evaluation windows, and anomaly detection. Automatically roll back affected segments to the last stable template if thresholds are breached, with cooldown/hysteresis to prevent oscillation. Provide instant alerts, a root-cause summary, and a clear record of the rollback action, including the exact versions and segments impacted.

Acceptance Criteria
Auto-rollback on confirmation rate threshold breach
Given segment "Downtown" is on template v3.2 And confirmation rate threshold is >= 75% over a 24h rolling window with min 200 deliveries When the confirmation rate for "Downtown" is < 75% for two consecutive 24h windows Then the system automatically rolls back "Downtown" to last stable template v3.1 And marks the rollback reason as "Confirmation rate threshold breach" And prevents re-promotion of v3.2 for "Downtown" for a 72h cooldown period And records the action in the audit trail with timestamp, actor=system, affected segment, from/to versions, and KPI values
Hysteresis and cooldown prevent oscillation
Given a segment was auto-rolled back within the last 72h When the KPI returns above threshold for one evaluation window Then the system does not auto-promote until KPIs remain above threshold for three consecutive windows And the 72h cooldown has elapsed And any manual re-publish requires an override reason captured in the audit log
Configurable thresholds and windows per KPI and segment
Given thresholds exist per KPI (confirmation rate, opt-out rate, delivery failures, reply sentiment, no-show proxy) and per segment And each includes operator, value, rolling window duration, and minimum sample size When an admin updates thresholds for segment "Provider A" via UI or API Then the configuration takes effect within 5 minutes And evaluations for other segments remain unaffected And the change is versioned and auditable with before/after values and actor
Anomaly detection alerts with optional rollback
Given anomaly detection is enabled with a 7-day seasonal baseline and min sample size 200 When a KPI deviates by ≥ 3 standard deviations from its baseline for a segment Then an "Anomaly detected" alert is emitted within 2 minutes including KPI, deviation, segment, and link to details And if rollback_on_anomaly=false, no rollback occurs And if rollback_on_anomaly=true, rollback follows the same cooldown and hysteresis rules as threshold breaches
Partial rollback isolates only affected segments
Given segments "Downtown", "Uptown", and "Eastside" are on template v3.2 And only "Uptown" breaches the opt-out rate threshold When rollback is triggered Then only "Uptown" reverts to last stable template v3.1 And "Downtown" and "Eastside" remain on v3.2 And live traffic routing reflects the change within 2 minutes
Instant stakeholder alerts on rollback with context
Given notification channels email and Slack are configured for group "Hygiene Ops" When an auto-rollback occurs for any segment Then alerts are sent to all configured channels within 2 minutes And the alert includes segment(s), KPI(s), observed value(s), threshold(s), from/to template versions, timestamp, and incident link And notification delivery is retried for up to 15 minutes on failure
Root-cause summary and audit trail completeness
Given a threshold breach or rollback event occurs When the incident record is generated Then it includes recent template changes (last 7 days), message variants/channels, A/B arms, deployment timeline, affected segments, KPI time series, and ranked suspected drivers And the audit trail stores initiator (system/user), timestamps, before/after configuration, affected segments, and from/to versions And the audit trail is immutable and exportable via API (CSV/JSON) And the incident detail page loads within 3 seconds at the 95th percentile
Holdouts & Switchbacks Manager
"As a data-minded office manager, I want configurable holdouts and quick switchbacks so that I can compare outcomes and revert safely if results are worse than control."
Description

Support randomized or rules-based holdout groups and fast switchbacks to a control template for comparison. Maintain consistent cohort assignment to prevent contamination and support per-segment holdout ratios. Display side-by-side performance for variant vs control with confidence indicators to guide promotion decisions. Allow emergency switchback across selected segments with one action and clear confirmation.

Acceptance Criteria
Randomized Holdout Creation and Cohort Stickiness
Given an active campaign with eligible segments When an admin configures a randomized holdout of 20% for Segment A Then the system assigns patients to control or variant using a deterministic method based on stable identifiers (e.g., patient_id + campaign_id hash), ensuring the same patient remains in the same cohort for the campaign’s active duration And the realized holdout proportion for Segment A over a rolling 7-day window is within ±2 percentage points of 20% when the sample size is ≥ 500 patients And a patient assigned to control receives only control templates across SMS, email, and voice for that campaign And editing the campaign templates does not change existing cohort assignments
Rules-Based Holdout by Segment and Provider
Given rules are defined (e.g., location = Clinic X, provider_specialty = Pediatric, patient_type = New) When an admin creates a rules-based holdout of 25% targeting patients who match all rules Then only patients who match the rules are eligible for holdout assignment, and non-matching patients are excluded And assignment is deterministic and persists for the campaign’s active duration And a patient is assigned to at most one holdout per campaign even if multiple rules would apply, with the most specific rule taking precedence And saving the rules validates that the targetable population is ≥ 200 patients over the last 30 days or warns that results may be underpowered
Per-Segment Holdout Ratios Enforcement
Given Segment A is configured with a 10% holdout and Segment B with a 25% holdout When the campaign runs over time Then the realized holdout ratio per segment over a 7-day rolling window remains within ±2 percentage points of the configured ratio for sample sizes ≥ 300 per segment And the UI displays current realized ratios per segment with a status badge (On target / High / Low) And if the realized ratio drifts outside tolerance for 24 hours, the system raises an alert to admins and logs the event And updates to ratios are applied without reassigning existing cohorts; only new eligible patients are randomized to meet the new target
Side-by-Side Performance with Confidence Indicators
Given at least 100 outcomes per arm in the selected date range When a user opens the Variant vs Control view Then the system displays side-by-side metrics (confirmation rate, no-show rate, response rate) for variant and control with absolute and relative lift And significance is computed using a two-proportion z-test at 95% confidence and labeled as Significant, Not significant, or Insufficient data And 95% confidence intervals for the primary KPI (confirmation rate) are shown for both arms And filters for date range, segment, and provider update the view within 2 seconds for datasets ≤ 50k records And CSV export includes arm, metrics, confidence intervals, p-values, filters applied, and timestamp
Fast Switchback to Control for Selected Segment
Given a user with Admin permissions selects a single segment with an active variant When the user clicks "Switch back to control" and confirms in the modal Then within 2 minutes all future outbound messages for that segment use the control template And scheduled messages more than 5 minutes in the future are updated to control; messages within 5 minutes are not modified and are flagged as "Late window" And the UI displays a success banner with timestamp and user id; an audit log entry records segment, from_template, to_template, reason (user-entered), and a metrics snapshot And stakeholders subscribed to the campaign receive a notification within 5 minutes
Emergency Multi-Segment Switchback with Confirmation and Audit
Given a user with Admin or Owner role selects multiple segments from the segments list When the user initiates "Emergency switchback" and types the required confirmation phrase Then all selected segments revert to the control template within 2 minutes And a bulk audit record is created with child entries per segment capturing initiator, timestamp, affected templates, and pre/post KPI snapshots And notifications are sent to the stakeholder list via email (and SMS if enabled) within 5 minutes, including impacted segments and links to the audit trail And if any segment cannot be updated, the operation is partial-success: affected segments are listed, retries are queued, and the user sees a detailed error for failures
One‑Click Promotion & Versioning
"As a content editor, I want one‑click promotion with built-in validation so that updates go live quickly without breaking compliance or delivery."
Description

Provide a single action to promote approved draft templates to live across SMS, email, and voice, with atomic, multi-channel updates. Validate dependencies and required compliance elements (e.g., merge tags, opt-out language, send windows) before promotion. Maintain full version history with labels, diffs, and restore points to enable precise rollbacks to any prior version per channel and segment.

Acceptance Criteria
Atomic Multi-Channel Promotion
Given a user with Publish permission selects an approved draft release containing SMS, email, and voice templates for specified locations/providers/segments When they click "Promote Now" Then the system executes a single atomic transaction applying the release to all selected channels and segments And either all updates succeed or no live content is changed And the promotion completes within 5 seconds for 100 or fewer templates or returns a progress handle for larger batches And the UI displays a success summary with counts per channel And an immutable audit log entry is created with actor, timestamp, environment, affected channels, counts, and version label
Pre-Promotion Compliance Validation
Given a draft release is selected for promotion When validation runs prior to execution Then promotion is blocked if any template has missing/invalid merge tags, missing required opt-out language (SMS/email), missing voice disclosure, or invalid send window configuration And the validation report lists each failing template with channel, segment, and the exact rule violated And the Promote action is disabled until all blocking issues are resolved or items are deselected And non-blocking warnings are shown but do not prevent promotion And validations complete within 3 seconds for 100 or fewer templates
Audit Trail and Stakeholder Notifications
Given a promotion or rollback completes When the event is recorded Then the audit log entry includes actor, UTC timestamp, environment, scope (locations/providers/segments), channels, from-version and to-version IDs, diff reference, and release notes And audit entries are immutable and filterable by date, actor, channel, and scope And configured stakeholders receive a notification via email and/or Slack within 60 seconds containing summary, diff link, and rollback link And duplicate notifications are not sent for the same event
Version History, Labels, and Diffs
Given a user views version history for a template or release bundle When versions are listed Then each version shows label (required), sequential identifier, timestamp, actor, channel, and notes And labels are unique per template within the environment And users can compare any two versions and see highlighted diffs of content and metadata including send windows, merge tags, and opt-out text And the system retains at least the last 200 versions per template with pagination and search
Precise Rollback by Channel and Segment
Given a prior version exists for a specific channel and segment When a user selects Restore for that channel and segment Then only the selected channel/segment is rolled back atomically without impacting others And the restore creates a new version labeled "rollback-YYYYMMDD-HHMM" referencing the source version And all compliance validations re-run before restore; failing validations block the rollback and present a report And the rollback completes within 5 seconds for 50 or fewer templates And audit log and stakeholder notifications are generated
Promotion Dry Run and Dependency Report
Given a user selects Dry Run for a draft release When the system evaluates the release Then no live content is modified And a downloadable report is produced listing items to be promoted, dependent assets (merge tags, media), validation results, and estimated impact counts by channel/segment And the report is generated within 10 seconds for 500 or fewer templates
Concurrency and Idempotency Controls
Given two promotion requests target overlapping templates/channels in the same environment When they are triggered concurrently Then optimistic locking ensures only one proceeds and the other fails gracefully with a retry message And repeated clicks of Promote Now for the same request within 60 seconds do not create duplicate promotions And transactional guarantees prevent mixed-version live states at all times And a conflict event is logged with correlation IDs
Immutable Audit Trail & Compliance Logging
"As a compliance administrator, I want an immutable audit trail of all publish actions so that our practice can pass audits and investigate issues confidently."
Description

Record a tamper-evident audit trail for every change, rollout, rollback, approval, and notification, including who, what, when, where, before/after diffs, and affected segments. Hash and timestamp entries, redact PHI, and enforce retention aligned to HIPAA policies. Provide exportable, filterable logs and scheduled compliance reports for internal reviews and external audits.

Acceptance Criteria
Event Capture for Changes, Rollouts, Rollbacks, Approvals, and Notifications
- Given an authenticated user or system actor commits a change, rollout, rollback, approval, or notification, When the action is finalized, Then an audit entry is created within 1 second capturing: event_type, actor_id, actor_role, auth_method, client_id, correlation_id, timestamp_utc (ISO 8601), tenant_id, location_id, provider_id, environment, source_ip, user_agent, object_type, object_id, version_before, version_after, and outcome (success/failure with error_code). - And When the entry is stored, Then it is assigned a unique monotonically increasing identifier and stored append-only (no update/delete endpoint exists). - And Given the last-30-days partition, When retrieving by correlation_id or object_id, Then p95 read latency is <=2 seconds for a 1M-row tenant.
Tamper-Evident Hashing and Append-Only Storage
- Given any new audit entry is persisted, When written, Then the system computes SHA-256 content_hash over a canonicalized payload and stores previous_hash to form a per-tenant hash chain. - And Then entries are stored on WORM-compliant, server-side encrypted storage; only append operations are permitted outside of governed purge workflows. - Given the daily verification job runs, When it validates N latest entries per tenant, Then any chain break or timestamp anomaly triggers a Sev-2 alert within 5 minutes and is logged with details. - Given the verification API is called with entry_id, When requested, Then it returns content_hash, previous_hash, chain_status, and verified=true/false in <300 ms p95 for the most recent 10k entries.
PHI Redaction and Field-Level Controls
- Given an audit payload includes patient identifiers (e.g., name, phone, email, MRN, DOB, full address), When serialization occurs, Then PHI fields are irreversibly redacted or tokenized so no raw PHI is persisted in the audit store. - And When a disallowed PHI field is attempted, Then the write is rejected with error AUDIT_PHI_BLOCKED and a minimal non-PHI audit of the rejection is recorded. - And Given redaction policies are updated, When changes are published, Then the policy change is audited and takes effect for all subsequent entries without altering existing stored entries.
Before/After Diffs and Affected Segments
- Given a template or targeting rule is changed and promoted, When the audit entry is created, Then it includes a normalized JSON Patch (RFC 6902) diff of changed fields and a 500-character max human-readable summary. - And Then the entry records affected_segments with IDs and estimated_count at commit time and actual_count within 24 hours, plus rollout scope (locations/providers) and change_id linkage. - And Given a rollback occurs, When logged, Then the entry references the original change_id and version restored, with a reverse diff included.
Filterable and Exportable Audit Logs
- Given a user with Audit.View permission, When filtering by date range (UTC), event_type, actor_id, tenant/location/provider, object_type/id, environment, outcome, and keyword, Then matching entries are returned paginated and sortable with p95 query time <=2 seconds for a 1M-row tenant. - And When exporting, Then CSV and JSON exports include export_time_utc, filters_applied, and column definitions; support up to 250k rows per file via streaming; and are available for secure download for 7 days. - And Then export and download actions are themselves audited with actor_id, filters, and file checksum.
Scheduled Compliance Reports for Internal/External Audits
- Given a compliance admin schedules weekly or monthly reports to secure email or SFTP, When the schedule triggers, Then the report includes counts by event_type, rollouts, rollbacks, approvals, notifications, hash verification pass/fail, PHI-block incidents, and purge actions for the period. - And Then delivery uses TLS 1.2+ with 3 retry attempts (exponential backoff) on failure and notifies designated recipients of success/failure. - And Given a report is regenerated for the same period and filters, When generated, Then contents are byte-for-byte identical; report metadata (no PHI) is retained and audited.
Retention Policy Enforcement and Legal Hold
- Given tenant-level retention is configured (default >=6 years) and legal holds may be applied, When the nightly purge runs, Then entries older than retention without legal hold are purged and a tombstone entry with time window and counts is appended. - And Then purged data is unrecoverable from primary and backups within 30 days; purge start/end, counts, and any errors are audited. - And When retention or legal hold settings change, Then only Admins can enact the change; the change is versioned, audited, and applies prospectively; misconfigurations that block purge raise an alert.
Stakeholder Notifications & Approval Gates
"As a practice manager, I want structured approvals and timely notifications so that the right people review changes and stay informed throughout the rollout."
Description

Notify designated stakeholders (dentists, hygienists, office managers, compliance) via in-app, email, or Slack with preflight summaries, blast radius, KPIs under watch, and rollback plan. Support configurable approval gates and role-based access before promotion, with deadline reminders and escalation. Provide post-deploy updates on rollout progress, KPI status, and any automated actions taken.

Acceptance Criteria
Multi-Channel Preflight Notifications Delivered and Tracked
Given a promotion with designated stakeholders and preferred channels (in-app, email, Slack) When the preflight is initiated Then each stakeholder receives a preflight summary within 2 minutes via their preferred channel And the summary includes: change overview, blast radius (locations/providers), KPIs under watch, rollback plan link, and approval deadline timestamp in the stakeholder’s local timezone And delivery status (sent, delivered, read/open where available) is recorded per recipient And undeliverable notifications are retried up to 3 times with exponential backoff and flagged in the preflight report
Role-Based Approval Gate Enforcement
Given configurable approval gates mapped to roles (dentist, hygienist, office manager, compliance) When any user attempts to approve or promote Then only users with the required role for the current gate can approve And all gates must be satisfied in sequence before promotion is enabled And all approvals are recorded with user, role, timestamp, and checksum in the audit trail And any attempt to bypass gates blocks promotion and notifies the promotion owner and compliance
Approval Deadline Reminders and Escalation
Given an approval deadline T and an escalation list When 50% of the time window to T has elapsed and approvals remain outstanding Then reminder notifications are sent to only the outstanding approvers via their preferred channels And when 90% of the time window to T has elapsed and approvals remain outstanding Then an escalation notification is sent to the escalation list with the list of missing approvals And when T is reached with outstanding approvals Then the promotion is automatically blocked and the owner is notified with next steps And all reminders and escalations are logged in the audit trail
Post-Deploy Rollout Progress and KPI Updates
Given a staged rollout by location/provider and configured KPI thresholds When deployment progresses Then stakeholders receive rollout progress updates at 25%, 50%, 75%, and 100% completion within 1 minute of each threshold And each update includes counts of locations/providers enabled, failures (if any), and current KPI deltas vs baseline with threshold annotations And any automated actions taken (pause, holdout expansion, auto-rollback) are explicitly listed with timestamps And all updates are available in-app and mirrored to email/Slack for subscribed stakeholders
Auto-Rollback KPI Dip Alerting
Given KPI thresholds and a configured breach duration window When KPIs breach thresholds for the configured duration and auto-rollback is triggered Then an immediate high-priority alert is sent to all stakeholders via in-app and Slack, and to email for compliance And the alert includes impacted scope, trigger reason, KPIs breached, time of rollback, and current system state And duplicate alerts for the same incident are suppressed for 30 minutes And the event is recorded in the audit trail with full context and links to logs
Preflight Blast Radius Accuracy
Given a promotion scope (locations, providers, patient segments) and messaging templates When the preflight summary is generated Then the blast radius shows exact counts and explicit lists of locations/providers affected with zero variance from the simulation results And the summary includes estimated outbound volume per channel for the first 24 hours And a link to the switchback/rollback plan is present and accessible And a checksum of the evaluated scope is stored to ensure the deployed scope matches the preflight
Stakeholder Subscription and Channel Preferences
Given a stakeholder notification matrix with channel opt-ins and mandatory roles When a new promotion is created or updated Then notifications are sent only via the stakeholder’s opted-in channels, unless the role is marked mandatory (e.g., compliance), which always receives all notifications And if a preferred channel is unavailable, a defined fallback channel is used and recorded And stakeholders can opt out per notification type without affecting mandatory roles And all preference changes are audited with user, old value, new value, and timestamp
Preview, Dry‑Run & Simulation
"As a template author, I want previews and safe dry-runs so that I can verify content and expected impact before affecting real patients."
Description

Offer channel-specific previews with real patient-safe placeholders, merge tag validation, and voice readbacks. Enable dry-runs that exercise the full pipeline without sending to patients, plus historical data simulations to estimate KPI impact and detect likely failures (e.g., missing tags, blackout conflicts). Provide a sandbox environment and test cohorts for end-to-end verification before live rollout.

Acceptance Criteria
Channel-Specific Preview with Patient-Safe Placeholders
Given a user selects SMS, Email, or Voice for a template And the template includes merge tags and dynamic sections When the user opens Preview Then the preview renders channel-specific formatting (SMS segments, Email HTML, Voice transcript) And all placeholders are populated with synthetic, patient-safe values with no PHI And unknown or unresolved tags are highlighted with inline errors And link tracking parameters are shown as they will appear in production without calling external endpoints
Merge Tag Validation and Blocking Errors
Given a template contains merge tags And a location and provider context is selected When the user runs Validation Then any undefined, misspelled, or out-of-scope tags are listed with line and position And default values are required or suggested where configured And validation fails with a blocking status until all critical tag errors are resolved And a validation summary is recorded in the audit log
Voice Readback and SSML Preview
Given the Voice channel is selected for a template When the user clicks Readback Preview Then a TTS readback plays using the selected voice profile and locale And the system displays the SSML used and an estimated duration in seconds And pronunciation anomalies are flagged with suggestions for phonetic/alias entries And no outbound calls or voicemails are placed during preview
End-to-End Dry-Run Without Sending
Given a user starts a Dry-Run for a selected campaign/template, location(s), provider(s), and time window And a test cohort of N synthetic or opted-in internal contacts is chosen or generated When the Dry-Run executes Then all pipeline stages execute (branching, scheduling, blackout checks, rate limits, throttles, deduplication, opt-out checks) And zero external deliveries are made to real patients or carriers And the system produces a report with counts per branch, blocked messages by reason, and timing And an immutable audit trail entry is created with actor, inputs, outputs, and timestamps
Historical Simulation for KPI Impact and Risk Detection
Given at least D days of historical delivery, confirmation, and no-show data exist And baseline KPIs are defined (confirmation rate, no-show rate, send volume) When a user runs a Historical Simulation for a template change Then the system estimates KPI deltas versus baseline with 95% confidence intervals And identifies likely failures including missing tags, blackout conflicts by location/time, opt-out collisions, and carrier filtering risks And outputs a simulation report with per-location/provider breakdowns and a Pass/Fail recommendation based on thresholds
Sandbox Environment with Test Cohorts and Safe Endpoints
Given a Sandbox environment is selected And a test cohort and safe endpoints (test phone numbers/emails) are configured When an end-to-end test is executed Then messages are sent only to safe endpoints while exercising the full production pipeline And all PHI fields are redacted or replaced with synthetic data at rest and in transit And sandbox metrics are captured and visible, segregated from production analytics And promotion to production is gated on all required checks passing

Wallet QuickPay

Offer Apple Pay, Google Pay, Click to Pay, and ACH inside the payment link with device-aware buttons. Patients pay in one tap without typing card numbers; authorizations clear in seconds and confirmations write back instantly. Practices see fewer declines, faster collections, and less staff time on the phone.

Requirements

Device-Aware Wallet Buttons
"As a patient, I want to see payment methods optimized for my device so that I can pay in one tap without entering card details."
Description

Render Apple Pay, Google Pay, Click to Pay, and ACH buttons contextually based on device, browser, and merchant configuration to enable true one-tap payments. Detect ApplePaySession on Safari/iOS, Google Pay API readiness on Chrome/Android, EMV SRC for Click to Pay on desktop, and always-present ACH when enabled. Order methods by likelihood of success, show disabled states while initializing, and fall back gracefully to a compliant card entry option when no wallets are supported. Ensure WCAG AA accessibility, localization, and branded theming. Provide feature flags, sandbox/prod separation, and analytics events for impressions, initializes, taps, and renders to measure adoption.

Acceptance Criteria
Apple Pay on Safari iOS
Given Safari on iOS 16+ with ApplePaySession defined and ApplePaySession.canMakePayments() returns true When the payment link loads Then an Apple Pay button is rendered in the primary row, enabled, within 1000 ms of first paint Given the Apple Pay button is enabled When the user taps the button Then the Apple Pay sheet opens and, upon user authorization, the payment is created and confirmed within 5 seconds and a success confirmation screen is shown Given ApplePaySession is defined but canMakePayments() returns false or the merchant has Apple Pay disabled When the payment link loads Then the Apple Pay button is not rendered and an alternative supported payment method is surfaced Given Apple Pay initialization has started When readiness is pending Then the Apple Pay button is visible but disabled with a spinner and becomes enabled on readiness or is removed on init failure Given any Apple Pay lifecycle event occurs (impression, initialize_start, render, tap, authorize_success, authorize_fail) When the event occurs Then an analytics event is emitted with method=apple_pay, event_name, device, browser, environment, merchant_id, and latency_ms
Google Pay on Chrome Android
Given Chrome on Android with the Google Pay API available and PaymentsClient.isReadyToPay returns true for configured networks When the payment link loads Then a Google Pay button is rendered in the primary row, enabled, within 1000 ms of first paint Given the Google Pay button is enabled When the user taps the button Then the Google Pay sheet opens and, upon successful authorization, the payment is created and confirmed within 5 seconds and a success confirmation screen is shown Given PaymentsClient.isReadyToPay returns false or the merchant has Google Pay disabled When the payment link loads Then the Google Pay button is not rendered and an alternative supported payment method is surfaced Given Google Pay initialization has started When readiness is pending Then the Google Pay button is visible but disabled with a spinner and becomes enabled on readiness or is removed on init failure Given any Google Pay lifecycle event occurs (impression, initialize_start, render, tap, authorize_success, authorize_fail) When the event occurs Then an analytics event is emitted with method=google_pay, event_name, device, browser, environment, merchant_id, and latency_ms
Click to Pay on Desktop Browsers
Given a desktop browser (Windows/macOS) on Chrome, Edge, Firefox, or Safari with EMV SRC (Click to Pay) libraries loaded and merchant networks configured When the payment link loads Then a Click to Pay button is rendered in the primary row, enabled, within 1200 ms of first paint Given the Click to Pay button is enabled When the user taps the button Then the SRC identity flow opens, the user can select or add a network card, and upon authorization the payment is created and confirmed within 7 seconds and a success confirmation screen is shown Given EMV SRC readiness check fails or merchant has Click to Pay disabled When the payment link loads Then the Click to Pay button is not rendered and an alternative supported payment method is surfaced Given Click to Pay initialization has started When readiness is pending Then the Click to Pay button is visible but disabled with a spinner and becomes enabled on readiness or is removed on init failure Given any Click to Pay lifecycle event occurs (impression, initialize_start, render, tap, authorize_success, authorize_fail) When the event occurs Then an analytics event is emitted with method=click_to_pay, event_name, device, browser, environment, merchant_id, and latency_ms
ACH Availability and Flow
Given the merchant has ACH enabled in configuration When the payment link loads on any supported device or browser Then an ACH button is rendered within 1000 ms of first paint, regardless of wallet availability Given the ACH button is visible When the user taps the button Then the ACH collection flow (hosted, compliant) opens to collect account and routing details and, upon successful authorization, the payment is created and confirmed within 10 seconds and a success confirmation screen is shown Given the merchant has ACH disabled When the payment link loads Then the ACH button is not rendered Given any ACH lifecycle event occurs (impression, initialize_start, render, tap, authorize_success, authorize_fail) When the event occurs Then an analytics event is emitted with method=ach, event_name, device, browser, environment, merchant_id, and latency_ms
Wallet Ordering and Initialization States
Given the device/browser context is Safari on iOS and both Apple Pay and ACH are enabled When the payment methods are rendered Then the order is Apple Pay first, ACH second, followed by any other supported methods, and Card Entry last Given the device/browser context is Chrome on Android and both Google Pay and ACH are enabled When the payment methods are rendered Then the order is Google Pay first, ACH second, followed by any other supported methods, and Card Entry last Given the device/browser context is desktop (non-iOS) with Click to Pay readiness true and ACH enabled When the payment methods are rendered Then the order is Click to Pay first, ACH second, followed by any other supported methods, and Card Entry last Given any wallet method is initializing When the page first paints Then that method’s button is visible but disabled with a spinner until readiness resolves, with a maximum init wait of 2000 ms after which the method is hidden or marked unavailable and remaining methods reflow without layout shift > 0.1 CLS Given feature flag wallet_quickpay or per-method flags are off for the merchant or environment When the payment link loads Then the flagged methods do not render and no initialization calls are made for them Given the environment is sandbox When any wallet initializes or a payment is attempted Then only sandbox keys, endpoints, and tokens are used and no production credentials or tokens are accepted or emitted, and vice versa for production
Fallback to PCI-Compliant Card Entry
Given no wallet methods are supported or all supported wallets fail initialization When the payment link loads or after initialization timeout Then a PCI-compliant card entry option (hosted fields or redirect) is rendered within 1000 ms and becomes the primary payment path Given the card entry form is visible When the user enters card details Then basic client-side validations run (Luhn check, expiry in the future, CVC required per brand) and invalid fields are announced with inline errors and ARIA attributes Given the user submits valid card details When the payment is processed Then authorization completes or fails with a visible outcome message within 8 seconds and analytics events are emitted for impression, render, submit, and outcome with method=card
Accessibility, Localization, and Theming Compliance
Given a keyboard-only user navigates the payment link When tabbing through the interface Then all buttons (Apple Pay, Google Pay, Click to Pay, ACH, Card) are reachable in a logical order, have visible focus indicators, and activation is possible via Enter/Space Given a screen reader is active When the wallet buttons render Then each button has an accessible name announcing the payment method and state (enabled/disabled) and dynamic state changes are announced via an aria-live region Given WCAG 2.1 AA requirements When the UI renders in light or dark themes Then all text and interactive elements meet contrast ratio >= 4.5:1 and disabled states remain discernible Given the user locale is set (e.g., en-US, es-ES, fr-FR, ar-SA) When the payment link renders and amounts are displayed Then all labels and messages are localized, RTL layouts are respected for RTL locales, and currency/number formats follow the locale Given merchant branding tokens (colors, fonts, corner radius) are configured When the payment link renders Then wallet buttons and fallback form adopt the brand theme without degrading contrast or usability
One-Tap Payment Link Experience
"As a patient, I want a secure, prefilled payment link so that I can quickly pay my dental bill without logging in or calling."
Description

Deliver a secure, prefilled payment link that opens a lightweight checkout with device-aware wallet buttons and ACH. Generate signed, short-lived tokens with no PHI in the URL; auto-populate patient name (masked), invoice/balance, and practice branding. Achieve <2s first paint on 4G, offline-safe errors, and clear states (amount due, selected method, confirmation). Support partial amounts when allowed, optional card-on-file consent, link expiration/revocation, and rate limiting. Deep link from SMS/email/voice, preserve UTM/source for attribution, and provide a post-payment thank-you screen with receipt options.

Acceptance Criteria
Signed, Short-Lived, PHI-Free Payment Link
Given a payment link is generated, Then the URL contains no PHI and only a signed, short-lived token. Given a payment link URL, When the token is tampered or signature is invalid, Then the request is rejected and checkout is not rendered. Given the link is opened from SMS, email, or voice channels, Then UTM/source parameters are captured and persisted through payment for attribution.
Prefilled Checkout Data and Clear, Validated States
Given a valid token, When checkout loads, Then the patient name is masked, the invoice/balance is displayed, and practice branding is shown. Given a valid token, Then the amount due defaults to full balance. Given partial payments are allowed for this invoice, Then the user can enter a partial amount within configured min/max and not exceeding the balance, with inline validation. Given partial payments are not allowed, Then the partial amount control is not shown. Given card-on-file is enabled by the practice, Then an optional, unchecked consent control with clear legal text is present; When the user opts in, Then the instrument is tokenized for future use; When the user does not opt in, Then no card is stored. Given a payment method is selected, Then the current selected method is clearly indicated and persists until changed.
Device-Aware Wallet Buttons and ACH
Given iOS Safari with Apple Pay available, Then display an Apple Pay button; When tapped, Then the Apple Pay sheet appears and the user can authorize without typing card numbers. Given Android Chrome with Google Pay available, Then display a Google Pay button; When tapped, Then the Google Pay sheet appears and the user can authorize without typing card numbers. Given a browser that supports EMVCo Click to Pay, Then display a Click to Pay button; When tapped, Then the Click to Pay flow is presented and can complete. Given checkout is rendering, Then an ACH payment option is available unless disabled by practice settings; When ACH is selected, Then bank details entry is validated and securely submitted. Given no wallet is available, Then wallet buttons are not shown and standard card entry is available.
Performance: <2s First Paint on 4G
Given a cold load on a 4G profile (400 ms RTT, 1.6 Mbps), Then First Contentful Paint is <= 2.0 s at the 75th percentile. Given the checkout bundle, Then total JS on the critical path is <= 150 KB gzipped and <= 10 critical requests. Given server response, Then TTFB is <= 500 ms at the 75th percentile in primary regions; Time to Interactive is <= 3.5 s at the 75th percentile.
Offline-Safe Errors and Retry
Given the device is offline or behind a captive portal, When the link is opened, Then an offline-safe error view renders from the service worker within 500 ms and offers a retry action. When connectivity is restored and retry is tapped, Then the checkout reloads to the last known state without data loss or duplicate submissions. Given a wallet payment attempt while offline, Then the user is shown a clear offline message and no authorization is attempted.
Post-Payment Confirmation, Writeback, and Receipt Options
Given a successful authorization and capture, Then a confirmation screen is shown within 2 s including amount paid, masked payment method, timestamp, and confirmation ID. Then receipt options are available to send via SMS, send via email, and download PDF; When selected, Then the corresponding receipt is generated and delivered successfully. Then the payment confirmation is written back to the practice system within 5 s at the 95th percentile; On transient failure, Then a retry is queued and the practice dashboard indicates pending sync without impacting the patient's confirmation. Then analytics events include preserved UTM/source values associated with the payment.
Link Expiration, Revocation, and Rate Limiting
Given a token that is past its configured expiry, When the link is opened, Then an expired state is shown with no payment form and HTTP 410 is returned. Given a token that has been revoked by staff, When the link is opened, Then a revoked state is shown with no payment form and HTTP 403 is returned. Given repeated requests or failed attempts exceed thresholds (e.g., >20 requests/min per IP or >10 failed payment attempts per token), Then a 429 rate limit response is returned and the link is temporarily blocked for 15 minutes.
Gateway & Wallet Tokenization Integration
"As a practice manager, I want wallet payments processed and tokenized through our gateway so that transactions are secure and future payments are faster."
Description

Integrate with the primary payment processor(s) to support Apple Pay (merchant/domain verification), Google Pay, EMV SRC Click to Pay, and network tokenization. Create payment intents with idempotency keys, handle 3DS/SCA when required, and normalize gateway responses and decline codes. Vault tokens per practice with clear PCI scope (SAQ A), support multi-location MIDs, and enable refunds/voids via the same token. Provide configuration UI and APIs for merchant IDs, certificates, and environment settings, plus health checks and alerting for gateway outages.

Acceptance Criteria
Wallet Merchant Setup and Verification
Given a practice admin with Payments:Admin role submits Apple Pay Merchant ID, merchant certificate, and the domain association file is reachable at /.well-known/apple-developer-merchantid-domain-association When verification is triggered via UI or API Then Apple Pay merchant validation succeeds and the configuration status displays Verified for the selected environment Given Google Pay merchant ID and gateway parameters are entered When readiness validation is executed Then Google Pay returns ready = true and the configuration status displays Verified Given EMV SRC Click to Pay profile ID and keys are configured When a test enrollment lookup is performed for a supported card brand Then SRC returns enrollment status OK and the configuration status displays Verified Rule: Secrets (certs/keys) are encrypted at rest, access is RBAC-controlled, and all configuration changes are audit-logged Rule: Sandbox and Production credentials are isolated; environment selection is explicit and validated per environment
Wallet Checkout Authorization and Tokenization
Given a supported device/browser and a Verified wallet configuration for the practice When the patient completes the wallet sheet (Apple Pay, Google Pay, or Click to Pay) Then a network-tokenized payment method is created and an authorization is sent with a unique Payment Intent ID Rule: P95 authorization latency ≤ 5s and P99 ≤ 8s in sandbox test cases Rule: Authorization outcome is persisted and written back via webhook/API within 2s of gateway response Rule: No PAN, CVV, or sensitive auth data is stored or logged by SmileCue (SAQ A alignment) Rule: On unsupported devices, the corresponding wallet button does not render and a fallback payment option is presented
Idempotent Payment Intent Creation and Safe Retries
Given the client submits Create Payment Intent with Idempotency-Key header When the identical request is retried within 24 hours due to network failure Then no duplicate authorization is created and the original Payment Intent ID and status are returned Rule: Idempotency key scope = (practice_id, amount, currency, MID, wallet type); parameter mismatch returns HTTP 409 with canonical code idempotency_key_conflict Rule: Downstream gateway retries use exponential backoff and are at-most-once per idempotency key Rule: Idempotency keys have a 24h TTL and are present in audit logs with masked payloads
Strong Customer Authentication (3DS) Handling
Given the BIN/processor indicates SCA is required When the patient initiates payment via a supported wallet or tokenized card Then a 3DS 2.x flow is initiated; frictionless applies when eligible; otherwise a challenge is presented and the result is captured Rule: Successful 3DS sets status authorized and liability_shift = true when applicable Rule: Failed, abandoned, or timed-out challenges set status declined with canonical code authentication_failed; no capture occurs Rule: If exemption/whitelisting is indicated by the gateway, proceed without challenge and log sca_exemption
Gateway Response Normalization and Decline Code Mapping
Given an authorization response is received from any supported processor When SmileCue normalizes the response Then it exposes a unified schema: status (authorized|declined|error), canonical_decline_code, processor_trace_id, avs_result, cvv_result, liability_shift Rule: 100% of known processor decline codes map to approved canonical codes; unknown codes map to unknown_error and trigger a mapping alert within 15 minutes Rule: AVS/CVV results are normalized to the standard enum set and included in logs and write-backs Rule: Normalized responses are available via API and webhooks within 2s of gateway receipt
Vault Token Scope, Multi-Location MIDs, and Refunds/Void via Token
Given a successful authorization yields a tokenizable instrument When the token is vaulted Then it is scoped to the practice and bound to the correct location MID; access by other practices is denied Rule: Cross-location usage requires explicit linking; routing selects the correct MID based on invoice/location metadata Rule: Refunds and voids can be initiated via UI/API using the vaulted token or original Payment Intent; normalized outcome is returned within 5s Rule: PCI scope is SAQ A; no PAN/CVV is stored or viewable; quarterly tokenization tests pass without critical findings Rule: Token deletion revokes gateway references and is audit-logged with timestamp, actor, and reason
Gateway Configuration APIs and Health Checks with Alerting
Given authenticated access with Payments:Admin permissions When creating/updating/deleting MIDs, merchant IDs, certificates, and environment settings via API/UI Then input validation, RBAC, encryption-in-transit, versioning, and audit logging are enforced; changes are roll-backable Rule: /health/payment-gateways returns per-gateway status (UP|DEGRADED|DOWN), last success timestamp, and rolling error rate Rule: If error rate > 5% over 5 minutes or health = DOWN, send on-call and in-app alerts within 2 minutes and apply configured failover routing Rule: Secret rotation is supported; expiry within 30 days raises a proactive alert until resolved
Real-Time Authorization & PMS Writeback
"As an office manager, I want payment confirmations to update the appointment and balance instantly so that staff don’t chase payments or double-charge."
Description

Post successful authorizations to SmileCue and the practice management system within seconds, updating patient ledger, appointment status, and outstanding balance. Implement webhooks/event bus with idempotent handlers, guaranteed delivery, and retries with backoff. Generate receipts, send confirmation via SMS/email, and mark reminder threads as completed or updated. Handle edge cases (duplicate taps, timeouts, partial approvals, reversals) and surface clear statuses in the staff portal. Expose an operational dashboard showing event lag, failures, and manual replay controls.

Acceptance Criteria
Instant Writeback on Successful Card Authorization
Given a patient completes a valid card-based Wallet QuickPay payment and the processor returns authorization success When the authorization/capture callback is received by SmileCue Then SmileCue updates the PMS patient ledger, appointment status to "Paid", and outstanding balance within 5 seconds end-to-end (p95), recording authorization_id, amount, and payment method And Then a receipt is generated with receipt_id and accessible link; SMS and email confirmations are queued within 2 seconds; the active reminder thread is marked completed And Then the staff portal reflects "Paid" with timestamp and receipt link within 5 seconds (p95) And Then no duplicate ledger entries are created for the same authorization_id
Idempotent Processing for Duplicate Taps and Retries
Given multiple identical payment submissions share the same idempotency_key and payment_intent_id (e.g., duplicate taps, network retries) When API, webhook, or consumer handlers receive duplicate events within a 10-minute window Then only one charge is captured and only one ledger/writeback occurs; subsequent duplicates return 200 with the original transaction reference And Then no more than one receipt is generated and no duplicate SMS/email confirmations are sent And Then audit logs record a deduplication outcome with idempotency_key and original event_id And Then concurrent consumers do not create duplicates (verified under at-least-once delivery with idempotent handlers)
Timeouts and ACH Pending with Eventual Consistency
Given a payment attempt results in a gateway timeout or an ACH payment enters pending verification When no definitive success or failure is available within 10 seconds Then the payment status is set to "Pending Confirmation"; the reminder thread remains open; the staff portal displays Pending with last_attempt timestamp And Then the system schedules exponential backoff retries (minimum 5 attempts over 15 minutes) and also awaits webhook callbacks; processing remains exactly-once via idempotent handlers And Then upon eventual success, writeback, receipts, and confirmations execute as in the successful flow; upon terminal failure, status becomes "Failed", the reminder thread resumes, and an SMS/email prompts alternative payment And Then all transitions are captured in audit logs with correlation_id and retry_count
Partial Approvals and Remaining Balance Reconciliation
Given a payment is partially approved or the patient pays less than the total due When the processor returns partial_amount < total_due Then SmileCue posts a ledger entry for partial_amount, reduces outstanding balance accordingly, and sets appointment status to "Partially Paid" within 5 seconds (p95) And Then the staff portal shows remaining_balance and a one-tap link to pay the remainder tied to the same invoice_id And Then the receipt clearly indicates a partial payment with amount_paid and remaining_balance And Then a follow-up SMS/email is sent with the remaining balance link within 2 minutes
Reversals, Voids, and Refund Writeback
Given a previously authorized or captured payment is voided, reversed, or refunded (full or partial) When a reversal/refund event is received from the processor or initiated by staff Then SmileCue posts reversing ledger entries to PMS within 10 seconds (p95), updates outstanding balance, and adjusts appointment status appropriately (e.g., "Unpaid" or "Partially Paid") And Then prior confirmation threads are updated with a reversal note, and a reversal notification is sent to the patient if enabled And Then the staff portal shows the updated status with links to original and reversal receipts and includes reason_code And Then audit logs include actor, reason, amounts, and correlation_id
Operational Dashboard: Lag, Failures, and Manual Replay
Given events flow through webhooks and the event bus When an operator opens the operational dashboard Then the dashboard displays event lag p50/p95/max (seconds), and counts of in-flight, succeeded, and failed events for the last 24 hours And Then failed events list error summary, event_id, idempotency_key, retry_count, and practice_id, with filters by type and practice And Then an authorized operator can select failed events and trigger manual replay with confirmation; duplicates are prevented via idempotency on reprocessing And Then all replay actions are audit-logged with operator_id, timestamp, and before/after state
Staff Portal: Clear Real-Time Payment Statuses
Given a staff member views a patient ledger or today's schedule in the portal When a payment is processing, completed, partial, failed, pending, reversed, or refunded Then the portal displays a status badge from [Paid, Partially Paid, Pending, Failed, Reversed, Refunded] with last_update timestamp and correlation_id And Then the portal reflects state changes within 10 seconds of occurrence (p95) and provides links to receipts and event details (if authorized) And Then error states include human-readable guidance for next actions (e.g., retry, call patient) without exposing unnecessary PHI And Then filtering by payment status is available and returns results within 2 seconds (p95)
ACH with Instant Bank Login & NACHA Compliance
"As a patient, I want to pay via my bank account with instant verification so that I can avoid card fees and complete payment easily."
Description

Offer ACH as a first-class method with instant account verification (e.g., Plaid/Open Banking) and a fallback to micro-deposit verification. Display expected settlement timelines, support same-day ACH where configured, and track statuses from initiated to settled or returned (R01–R10, etc.). Enforce NACHA rules, collect and store authorization mandates, and notify staff/patients on returns with automated next steps. Map ACH fees and surcharging rules per practice policy, and write settlement outcomes back to the PMS.

Acceptance Criteria
Instant Bank Login With Micro-Deposit Fallback
- Given a patient opens a Wallet QuickPay link and selects ACH, When they choose Instant Bank Login, Then supported institutions are searchable/selectable via the embedded provider without leaving SmileCue. - Given the patient authenticates successfully, When the provider returns the account, Then SmileCue stores only a tokenized bank reference and masked details (last4, bank name, account type); routing/account numbers are never stored. - Given a supported institution and successful auth, When verification completes, Then account status becomes verified within 60 seconds for supported banks 95% of the time. - Given an unsupported institution, user opt-out, or instant verification failure, When this occurs, Then the flow offers micro-deposit verification without data loss. - Given micro-deposits are initiated, When two small deposits post (<$1 each), Then the patient can enter the two amounts to verify; after 3 failed attempts, verification is locked for 24 hours and staff are notified. - Given micro-deposits are initiated, Then deposits are sent within 1 business day and verification remains available for 10 business days. - Given verification completes (instant or micro-deposit), When the patient confirms payment, Then the payment proceeds only if status is verified and an audit log records provider, timestamps, and actor.
NACHA Authorization Capture and Storage (WEB/TEL)
- Given a patient selects ACH, When proceeding to pay, Then SmileCue displays NACHA-compliant authorization text including merchant DBA, transaction type (single), amount, date, revocation instructions, and contact info. - Given the authorization is displayed, When the patient provides consent, Then consent is captured via required checkbox plus typed full name or e-sign, and stored with timestamp, IP, device, and authorization text version. - Given consent is missing, When the patient attempts to submit, Then submission is blocked with an inline error. - Given consent is captured, When payment is initiated, Then a receipt containing authorization details is sent via SMS/email within 1 minute and is retrievable as a PDF by staff for at least 2 years. - Given stored authorizations, When staff search by patient, date range, or payment ID, Then the authorization record is retrievable with immutable audit history and a checksum for integrity verification.
Settlement Timeline Display and Same-Day ACH
- Given ACH is enabled, When the patient reviews the payment before confirming, Then SmileCue displays an estimated settlement date/time and current status based on processor config and US Federal Reserve holiday calendar. - Given Same-Day ACH is enabled and initiation is before the configured cutoff, When the patient confirms, Then the estimate shows Expected to settle today with the local time window; otherwise it shows the next business day. - Given Same-Day ACH is not enabled or cutoff has passed, Then the estimate shows standard settlement (e.g., T+1/T+2) per processor configuration. - Given processor status updates, When status changes, Then the UI timeline and notifications update within 5 minutes to reflect the latest state. - Given the estimate was shown, When settlement is delayed or returned, Then the timeline updates and staff are notified automatically.
ACH Status Tracking and Return Code Handling
- Given an ACH payment is initiated, When events occur, Then SmileCue records statuses: initiated, submitted, processing, pending_settlement, settled, returned, failed, each with timestamps and ACH trace number. - Given an ACH return is received, When the processor posts an R-code (e.g., R01–R10, R29, R51), Then the payment is marked returned, the R-code and human-readable reason are stored and visible to staff. - Given a re-presentable return (e.g., R01, R09), When policy allows retries, Then the system schedules up to 2 automatic retries respecting NACHA limits and a minimum 2 business days between attempts. - Given a non-representable return (e.g., R02, R03, R29), Then no retries are scheduled and a task with next steps is created for staff. - Given any status transition, Then an immutable audit log entry is created including actor (system/user), timestamp, and source event ID.
Return Notifications With Automated Next Steps
- Given an ACH return event is received, When processed, Then staff are notified in SmileCue and via email within 10 minutes including patient, amount, R-code, suggested actions, and links to retry or request alternate payment. - Given R01 or R09, When retries are scheduled, Then the patient is notified with clear messaging and opt-out; if the patient opts out, all pending retries are canceled automatically. - Given R03 (No Account/Unable to Locate), When received, Then the patient is prompted via secure link to re-verify bank or choose card, and a collections queue task is created for staff. - Given repeat returns meet the practice-defined threshold (e.g., 2), When exceeded, Then automatic retries are disabled and the account is flagged for manual review with a high-priority task.
ACH Fees and Surcharging Rules
- Given practice fee/surcharge configuration, When a patient selects ACH, Then any applicable fee/discount is calculated and itemized before authorization with a required acknowledgment checkbox. - Given the patient’s billing state prohibits surcharges, When a fee would apply, Then SmileCue suppresses the fee and surfaces a configuration warning to staff. - Given a fee is applied, When the payment settles, Then net deposit and fee amounts are recorded separately; if the payment is returned, the patient-assessed fee is reversed or refunded per policy automatically. - Given fee configuration changes over time, When a payment link is generated, Then the applied policy version is stored with the transaction for auditability.
PMS Writeback and Idempotent Reconciliation
- Given a payment settles, When the processor posts settlement, Then SmileCue writes a payment record to the PMS within 5 minutes including patient ID, amount, date, method ACH, trace number, fees, and status settled. - Given a payment is returned, When the return is received, Then SmileCue posts a reversing entry to the PMS and updates the patient balance within 5 minutes. - Given transient PMS API errors, When writeback fails, Then the system retries with exponential backoff up to 24 hours using idempotency keys to prevent duplicates, and creates a staff alert on ultimate failure. - Given duplicate processor notifications, When already written, Then idempotency ensures only one PMS record exists. - Given daily reconciliation, When reports run, Then unmatched items are zero or explicitly listed with details for review and resolution.
Decline Recovery & Smart Retries
"As a practice manager, I want failed payments to automatically prompt alternatives and smart retries so that we reduce declines and collect faster."
Description

Reduce declines by detecting soft vs. hard declines, prompting the next-best available method (e.g., switch from card wallet to ACH), and scheduling intelligent retries that respect issuer guidance. Provide real-time error messaging, card updater/network token refresh, and optional alternative amount offers (e.g., partial payment). Route retries across multiple acquirers where supported, and notify staff only when intervention is needed. Log decline reason taxonomy for analytics and optimize button ordering over time.

Acceptance Criteria
Soft Decline Prompts Next-Best Payment Method
Given a wallet payment attempt returns a soft decline (e.g., do_not_honor, insufficient_funds, issuer_unavailable, network_timeout) When the decline response is received Then the system classifies the decline as soft within 100 ms of gateway response receipt And displays a modal with device-aware next-best methods (e.g., ACH, alternate wallet, card-on-file) within 500 ms And orders methods by predicted success probability learned from the past 30 days for this device type and BIN range And preselects the top method and enables one-tap reattempt without re-entering payment details And the subsequent authorization uses the same invoice ID and idempotency lineage to prevent duplicate capture And button ordering weights are recalculated at most once every 24 hours behind a feature flag And logs event decline_soft_prompt_shown with reason_category, reason_code, issuer_guidance_present, recommendation_shown
Hard Decline Halts Retries and Triggers Needed Staff Notification
Given a payment attempt returns a hard decline (e.g., stolen_card, lost_card, invalid_account_number, restricted_card, hard_fraud, do_not_retry) When the decline is classified Then no automated retry is scheduled And the UI presents a clear message advising alternative payment or contacting the issuer, without exposing raw gateway codes And if the balance remains unpaid after the attempt, a staff task is created with patient_id, invoice_id, last_decline_category, and suggested_action within 5 minutes And no staff notification is sent if a successful alternative payment is completed within 2 minutes of the decline And event decline_hard_task_created is logged exactly once per invoice per 24 hours
Intelligent Retry Scheduling Respects Issuer Guidance
Given a soft decline includes issuer retry guidance (e.g., retry_after seconds) or none When scheduling retries Then a maximum of 3 automated retries are scheduled per invoice over 72 hours And schedule uses issuer-provided retry_after when present; otherwise defaults to 15 minutes, 6 hours, and 24 hours spacing And retries are cancelled immediately upon any hard decline And each retry uses a unique idempotency key and references the prior attempt And events retry_scheduled, retry_skipped, and retry_executed are logged with reason and timestamp
Real-Time Error Messaging Is Clear and Actionable
Given a decline response is received When rendering the patient-facing message Then a mapped, plain-language message specific to the decline category is shown within 300 ms, localized to the patient’s locale And no raw gateway codes or PII/PHI are displayed And an inline action to try the next-best method is presented when available And the message meets WCAG 2.1 AA (screen-reader announced and 4.5:1 contrast) And event decline_message_shown is logged with category and locale
Card Updater and Network Token Refresh Before Prompting Patient
Given the decline is due to expired card, token lifecycle, or updater-eligible reason When the decline is processed Then the system attempts a network token refresh and/or card updater call within 2 seconds And if a new token/PAN is returned, one invisible retry is executed immediately And if that retry succeeds, the patient sees a success state without additional input And if it fails or no update is available, proceed to next-best method prompt And all updater attempts and outcomes are logged with non-PCI metadata (e.g., updater_used, updated_token_present)
Alternative Amount Offer for Partial Payment
Given the practice has enabled partial payment offers for declines When a soft decline occurs on an invoice >= the configured minimum amount Then the UI offers up to three options: predefined percentage (e.g., 25%, 50%), custom amount with minimum threshold, and pay-in-full And selecting a partial amount creates a payment plan for the remaining balance per practice configuration And ledger entries reflect the partial capture and remaining balance accurately And subsequent charges respect the same retry and routing rules And events partial_offer_shown and partial_payment_completed are logged with selected_amount and remaining_balance
Multi-Acquirer Retry Routing with Idempotency
Given a soft decline is eligible for routing per rules (exclude invalid_cvc, invalid_expiry, hard_fraud) When a retry is executed Then the routing engine may select an alternate acquirer/MID based on configured priorities and historical success for the BIN and region And network/customer tokens are preserved across acquirers when supported; otherwise PAN is securely vaulted and tokenized before retry And idempotency and duplicate-prevention are enforced so only one successful capture can post for the invoice And 3DS/SCA data is forwarded or re-challenged per PSD2/region rules when applicable And event routed_retry_executed is logged with selected_acquirer, route_reason, and outcome
Audit Logging & Compliance Controls
"As a compliance officer, I want auditable logs and strong data controls so that Wallet QuickPay remains HIPAA- and PCI-compliant."
Description

Maintain HIPAA and PCI DSS (SAQ A) boundaries by minimizing PHI in payment flows, encrypting data in transit and at rest, and segregating identifiers from clinical data. Implement immutable audit logs for all payment events, admin actions, and data access with RBAC, least-privilege, and SSO support. Capture explicit patient consent where required (wallet terms, ACH authorization), manage retention policies, and provide export for audits. Complete Apple Pay domain verification, Google merchant validation, and ongoing vulnerability and penetration testing.

Acceptance Criteria
Immutable Audit Log for Payment and Admin Events
Given a payment event (create, authorize, capture, refund, fail) occurs When the event is processed Then an immutable audit log entry is appended within 2 seconds including: event_type, timestamp (UTC ISO 8601 ms), actor_id/source, patient_pseudonym, practice_id, correlation_id, ip, device, user_agent, outcome, error_code, request_id Given an administrative action (RBAC change, retention update, export initiation, SSO config change) occurs When the action completes or fails Then an audit log entry is appended with before/after values (safely redacted) and who/when/where Given the audit log store When any user or service attempts to modify or delete an existing entry Then the operation is blocked, the attempt is logged, and an alert is sent within 5 minutes Given daily integrity verification When the job runs Then a hash-chain/WORM verification report shows zero breaks and is retained for 365 days Given retention policies are configured (searchable 90 days, retained 6 years by default) When entries exceed their retention Then they are purged by a daily job, purge actions are logged, and exports/manifests remain intact
RBAC, Least Privilege, and SSO Enforcement
Given role-based access is configured (e.g., Billing, Office Manager, Practice Admin, Compliance Admin) When a non-authorized role requests audit logs or exports Then the request is denied with HTTP 403 and the denial is logged Given SSO is enabled via SAML/OIDC When a user authenticates Then MFA is required by the IdP, session idle timeout is 30 minutes, absolute session lifetime is 12 hours, and local password login is disabled Given a Practice Admin attempts to assign a role higher than their own When the change is submitted Then the operation is rejected with HTTP 403 and logged with before/after role values (redacted where needed) Given least-privilege data access When staff use Wallet QuickPay or review payments Then full PAN/CVV and full bank account numbers are never displayed; only token, brand, and last4 are visible; PHI fields are masked by default Given permission changes When a role’s permissions are edited Then changes take effect within 60 seconds across services and are reflected in authorization decisions
Patient Consent Capture for ACH and Wallet Terms
Given a patient selects ACH in Wallet QuickPay When they proceed to pay Then a NACHA-compliant authorization is displayed with merchant DBA, amount, one-time frequency, revocation instructions, and a required unchecked consent checkbox or e-sign step Given the patient provides ACH consent When payment is submitted Then a consent record is stored with: timestamp, patient contact identifier, masked account last4, routing last4, IP, device, payment_intent_id, and authorization text/version hash, retrievable for 6 years Given a dispute or audit When a Compliance Admin searches by payment_intent_id Then a downloadable consent receipt (PDF or JSON) is available without exposing full account numbers or unnecessary PHI Given wallets (Apple Pay, Google Pay, Click to Pay) When a patient uses a wallet for the first time on a device Then they must accept Wallet QuickPay terms and privacy policy; the acceptance (timestamp, version hash, device fingerprint) is recorded; re-consent is required on version change Given a patient declines required consent When they attempt to submit payment Then submission is blocked with a clear message and only a minimal refusal record (timestamp, channel, reason) is stored
Encryption, Data Minimization, and Data Segregation
Given any client-server connection When a request is made Then TLS 1.2+ with strong ciphers and HSTS is enforced; HTTP is redirected or blocked; SSL Labs grade is A or better Given data at rest (logs, consents, exports, backups) When stored Then it is encrypted with AES-256 using KMS-managed keys rotated at least annually; access is limited to service principals with least privilege Given card payments via Wallet QuickPay When payment details are collected Then SmileCue code never handles PAN/CVV; PSP iFrames/JS or wallet protocols handle entry; only tokens, last4, brand, and expiry (MM-YYYY) are stored Given log ingestion When payloads contain PAN-like or bank-account patterns (Luhn/ABA matches) Then values are masked before persistence and a security alert is raised within 5 minutes Given data domains When payment events are persisted Then payment identifiers reside in a PCI-scoped store isolated from clinical/PHI stores and linked only via a pseudonymous patient_key; cross-store joins require authorized gateway access Given CI/CD enforcement When contract and schema checks run Then any introduction of clinical fields into payment APIs fails the pipeline and notifies the team
Audit Log Export for Compliance Reviews
Given a Compliance Admin requests an export for a date range and practice When the request is submitted Then a tamper-evident ZIP is generated within 15 minutes containing JSONL events, a SHA-256 manifest with counts, and a data dictionary Given the export is ready When a download is initiated Then a signed URL expires in 24 hours, requires MFA, and the download is logged with requester, IP, and checksum Given very large exports (>5,000,000 events) When generated Then the export is chunked, resumable, and completeness is verifiable by manifest totals and per-chunk hashes Given PCI/PHI minimization When exporting Then full PAN, CVV, and full bank accounts are excluded; only last4 is included; patient identifiers are pseudonymized with an export-unique salt Given export lifecycle When an export reaches 30 days since generation Then it is automatically purged and the purge event is logged
Apple Pay and Google Pay Domain/Merchant Validation
Given Apple Pay on the web is configured When merchant validation is performed in sandbox and production Then the validation succeeds, the domain association file is reachable, and an hourly health check verifies presence and validity with alerts at least 14 days before issues Given Google Pay is configured When readiness and end-to-end tests run on supported devices Then readiness returns true and paymentData flows succeed in sandbox and production with correct merchant and gateway IDs Given a wallet validation failure is detected When health checks fail Then the affected wallet button is hidden automatically, ACH/Click to Pay remain available, an advisory banner is shown, and an incident is opened for on-call Given environment isolation When running in non-production Then separate merchant IDs, keys, and domains are used with no cross-environment leakage; checks run daily and results are logged
Continuous Vulnerability Scanning and Penetration Testing
Given dependency and container images When builds occur Then SCA and image scanning run on every build; Critical findings block release; High findings require approval and a remediation plan Given deployed services When weekly scheduled scans run Then authenticated DAST scans complete with reports stored 12 months; Critical issues are remediated within 7 days, High within 30 days, Medium within 90 days Given annual external penetration testing When the test is completed Then a final report and proof-of-fix are stored; all Critical/High findings have documented remediation verified by retest within 30/60 days respectively Given vulnerability alerts are raised When SLAs are breached Then automated escalation pages on-call and creates a ticket with owner, severity, due date, and links to evidence Given configuration drift When CIS benchmark checks run daily Then deviations are reported and tracked to closure within 14 days or formally accepted with risk sign-off

Copay Predictor

Estimate patient responsibility before the visit using procedure, fee schedule, eligibility, and benefits-used data. Show a friendly breakdown in the message, update if coverage changes, and let staff override with notes. Clear expectations reduce day-of disputes and increase deposit completion.

Requirements

Real-time Eligibility & Benefits Sync
"As a front-desk coordinator, I want real-time eligibility and benefits data so that I can provide accurate cost estimates without calling the payer."
Description

Integrate with payers and clearinghouses to retrieve up-to-date eligibility, plan details, remaining deductible, coinsurance, copays, annual maximums, waiting periods, and frequency limitations. Support real-time X12 270/271 or payer APIs, with scheduled refresh and on-demand rechecks prior to appointment. Cache responses with TTL, handle payer timeouts and fallbacks, and normalize data to a standard benefits schema. Ensure HIPAA-compliant transmission and storage, detailed error codes, and retriable queues. Surface data freshness timestamps to staff and downstream components.

Acceptance Criteria
Real-time 270/271 Eligibility Response Retrieval
Given a verified patient, active plan, and reachable payer endpoint, When a real-time eligibility check is initiated via X12 270, Then a 271 response is received within 8 seconds at the 95th percentile and includes member status, plan effective dates, remaining deductible, coinsurance percent, copay amounts, annual maximum remaining, waiting periods, and frequency limitations for requested service codes. Given multiple requested procedures (CDT codes), When the 271 includes service-level benefits, Then each procedure is mapped to benefit type, coverage percent, remaining limitations, and next eligible date where applicable. Given the payer returns partial data, When required fields are missing, Then the system marks the result as partial with code ELEG-PARTIAL and proceeds to normalization using null-safe defaults while flagging missing fields.
Payer API Fallback and Retry with Backoff
Given a real-time 270 request times out after 10 seconds or returns a 5xx, When fallback is enabled for the payer, Then the system enqueues a payer-API eligibility request with exponential backoff starting at 30 seconds, doubling up to 5 minutes, with a maximum of 5 attempts. Given all retries fail, When the queue is exhausted, Then the final status is ELEG-NO-RESPONSE, the staff UI shows a non-blocking banner with timestamp and retry option, and an event is recorded with correlationId. Given any failure occurs, When an error is produced, Then a standardized error object is returned with domain=eligibility, code (e.g., ELEG-TIMEOUT, ELEG-5XX, ELEG-RATE-LIMIT), correlationId, payerId, endpointType, and a human-readable message.
Scheduled Eligibility Refresh Window Before Appointment
Given an appointment scheduled in the future, When the nightly job runs, Then eligibility is refreshed for appointments 1–7 days out and again 2 hours before start time unless a successful check exists within the payer-specific TTL. Given payer refresh window or rate limit constraints, When the scheduler evaluates jobs, Then it throttles requests to remain under configured thresholds and reschedules with jitter if limits are reached. Given a scheduled refresh fails, When a retry is required, Then the request is added to a durable queue with at-least-once delivery and retried per payer profile; success updates the appointment record and triggers downstream Copay Predictor recalculation.
On-Demand Recheck from Staff UI with Locking
Given a staff user with eligibility-recheck permission views an appointment, When they click “Recheck eligibility,” Then the system triggers an immediate check and displays progress; the action is rate-limited to 1 request per patient–payer every 5 minutes. Given a recheck is already in progress, When another recheck is requested, Then the UI disables the button and shows “Check in progress” with correlationId, preventing duplicate requests via an idempotency key. Given the recheck completes, When results are available, Then the UI updates within 2 seconds to show freshness timestamp, success/partial/fail status, and provides a retry link if status is not success.
Benefits Normalization to Standard Schema Across Payers
Given heterogeneous payer responses (271 segments or JSON APIs), When normalization runs, Then outputs conform to the SmileCue Benefits v1 schema with required fields: memberStatus, deductible.remaining, copay.amountByService, coinsurance.percentByService, annualMaximum.remaining, waitingPeriods.byService, frequencyLimits.byService, planEffective.start/end. Given conflicting or duplicated source segments, When merging benefits, Then deterministic precedence rules are applied (service-level > plan-level > default) and the transformation is logged with traceable mappings. Given unsupported or unknown payer codes, When encountered, Then map to standardized enumerations where possible or capture as otherCodes[] with source and description, without blocking downstream consumption.
Cache TTL Enforcement and Freshness Timestamp Display
Given a successful eligibility response, When cached, Then it is stored with a payer-specific TTL (default 24 hours; overrideable per payer) and tagged with source, correlationId, and expiresAt. Given a downstream component requests eligibility, When cached data is valid, Then the cache is served within 100 ms and includes freshness.timestamp and freshness.source; when expired, a recheck is triggered asynchronously and stale-if-error is served up to 2 hours with a warning flag. Given staff views eligibility, When data is displayed, Then the UI shows “Last verified: <timestamp>, Source: <X12|API>, Expires: <timestamp>” and warns if older than TTL.
HIPAA-Compliant Transport, Storage, and Audit Logging
Given PHI is transmitted to/from payers, When requests are sent, Then TLS 1.2+ is enforced, mutual TLS or OAuth2 client credentials are used as required, and no PHI appears in URL query strings. Given eligibility data is stored, When persisted, Then it is encrypted at rest using AES-256, access is restricted by role-based access controls, and all accesses are logged with userId/serviceId, action, timestamp, entityId, and purpose of use. Given any eligibility record is created, viewed, updated, or exported, When audited, Then an immutable audit entry exists and passes integrity verification; logs exclude sensitive values and are retained per policy (minimum 6 years).
Fee Schedule & Plan Rules Mapping
"As an office manager, I want accurate fee schedules and plan coverage mappings so that estimates reflect our contracted rates and plan rules."
Description

Maintain practice-specific fee schedules per location, provider, and payer/plan, including contracted (in-network) rates, UCR, and negotiated discounts. Map CDT procedure codes and modifiers to fees and plan coverage percentages by category (e.g., preventive, basic, major). Support location/provider overrides, effective dates, historical versions, and automated import from CSV or PMS exports. Validate completeness and flag inconsistencies. Provide an admin UI with role-based controls and audit logs for changes.

Acceptance Criteria
Create and Manage Fee Schedules per Location, Provider, and Plan
Given I am signed in as an Admin with the Billing Admin role When I create a fee schedule with required fields: location, provider, payer, plan, fee type (contracted/UCR/discounted), currency, effective start date Then the system saves the schedule and assigns a unique identifier And it enforces uniqueness for active records by [location, provider, plan, fee type, CDT code, modifier, effective date range] with no overlapping effective periods And required fields are validated with inline error messages for missing/invalid values And monetary amounts accept up to 2 decimal places and must be ≥ 0 And retrieving fees by the same [location, provider, plan, CDT code, modifier, service date] returns the stored amount
CDT Code and Modifier Mapping to Coverage Categories and Percentages
Given a payer/plan with coverage categories (e.g., preventive, basic, major) and percentages configured And CDT codes and modifiers are mapped to categories for that plan When I request coverage for a specific CDT code, modifier, and service date Then the returned coverage percentage equals the category percentage effective on the service date And if a code-modifier specific override percentage exists, it takes precedence over category default And if no mapping exists, the system flags the code as Unmapped, returns 0% (or configured default), and records a validation warning
Effective Dates, Overrides, and Historical Versioning
Given a base practice-level fee/rule, a location-level override, and a provider-level override exist When I request the fee and coverage for a given service date Then the precedence applied is: provider override > location override > base And only versions whose effective date range includes the service date are considered And saving a version with overlapping date ranges for the same key combination is blocked with an error And prior versions remain read-only and are accessible by version ID in the history
Automated Import from CSV/PMS with Preview, Validation, and Partial Failure Handling
Given I upload a CSV (or PMS export) using the documented template via the admin UI or schedule an automated import When I run a preview (dry run) Then the system validates schema, required columns, data types, CDT codes/modifiers, date ranges, and non-negative currency values And it displays total rows, valid rows, invalid rows, and a downloadable error report with line numbers and messages When I confirm the import Then valid rows are upserted, invalid rows are skipped, and no existing valid records are overwritten by invalid data And the import is idempotent using a content hash; re-importing the same file does not create duplicates And I can rollback the last import batch within 24 hours, with all changes and rollback recorded in the audit log
Completeness Validation and Inconsistency Flagging
Given plan rules and fee schedules are saved or updated When validation runs on save and nightly Then the system identifies and flags: missing fees for active CDT codes, unmapped codes/modifiers, overlapping effective dates, conflicting percentages for the same key, discounts outside 0–90%, and negative fees And activation/publication is blocked for Severity=Error items until resolved; Severity=Warning items do not block And Admins receive an in-app alert and email summarizing issue counts with a link to the validation report
Admin UI Role-Based Access Controls
Given roles Admin, Editor, and Viewer are configured When a Viewer accesses Fee Schedules & Plan Rules Then all content is read-only and create/edit/delete/import actions are not available When an Editor creates or edits draft changes Then the changes are saved as Draft and require Admin approval to activate; Editors cannot change RBAC or audit settings When an Admin approves, publishes, or deletes fee schedules or plan rules Then changes take effect per effective dates and are recorded in the audit log
Audit Logging of Fee and Rule Changes
Given any create, update, delete, import, or rollback action occurs on fee schedules or plan rules When the action is performed via UI, API, or automated import Then an audit entry records: UTC timestamp, actor user ID and role, entity type and ID, action type, previous values, new values, reason/note (required for overrides and deletes), source, and request ID And audit entries are immutable, retained for 6 years, filterable by practice/location/provider/plan/date range, and exportable to CSV And the admin UI supports paginated viewing and search of audit entries
Copay Estimation Engine with Secondary Insurance
"As a hygienist planning treatment, I want a clear, line-item estimate including secondary insurance so that I can set realistic payment expectations with the patient."
Description

Compute patient responsibility per visit across single or multiple procedures, accounting for remaining deductible, copays, coinsurance, annual maximums, frequency limits, waiting periods, and provider network status. Support coordination of benefits for primary and secondary insurance (including carve-outs and non-duplication), estimate write-offs, and calculate practice-collectible amounts. Produce line-item and total estimates, include a confidence score based on data completeness and payer responsiveness, and generate human-readable reasons and assumptions. Expose results via API for messaging and UI modules.

Acceptance Criteria
COB: Secondary Non-Duplication Across Multiple Procedures
- Given a patient has two billable procedures with active primary and secondary plans whose COB rule is Non-Duplication, When the estimation runs, Then the engine computes primary line-item liability first using plan limits and cost-share. - Given Non-Duplication on the secondary, When computing secondary line items, Then the engine calculates what the secondary would pay as primary and reduces that by the amount paid by primary, yielding secondaryPayment = max(0, secondaryAsPrimaryPayment − primaryPayment) per line. - Given Non-Duplication, When finalizing patient responsibility, Then the engine does not reduce the patient’s liability below the secondary plan’s own patient cost-share for that line, and floors all amounts at $0.00. - Given two procedures, When totals are produced, Then totalPrimaryPaid, totalSecondaryPaid, totalPatientResponsibility, and totalAllowed equal the sum of line items, with no negative totals. - Given rounding rules, When amounts are output, Then monetary values are rounded to two decimals using bankers’ rounding and currency is included.
COB: Carve-Out With Mixed Network Status
- Given primary is in-network and secondary is out-of-network with COB rule Carve-Out, When estimating, Then allowed amounts and write-offs are derived per plan’s network status for each line item. - Given Carve-Out, When computing secondary, Then the engine calculates secondaryAsPrimaryPatientShare and reduces the patient’s post-primary responsibility toward that amount, paying the lesser of (primaryPatientShare − secondaryAsPrimaryPatientShare) and (secondaryAllowed − primaryPaid) per line, floored at $0.00. - Given Carve-Out, When totals are computed, Then no line or total results in negative insurer payment or negative patient responsibility, and write-offs reflect plan contracts. - Given plan annual maximums, When primary or secondary max is exhausted, Then that plan’s payment is capped at remaining max and the remainder shifts to patient or other payer per COB rules.
Primary Plan Cost-Share With Deductible, Copay, Coinsurance, Limits
- Given a single primary plan, When estimating a visit with multiple procedures, Then the engine applies plan rules in the payer-specific order (if provided) or default order: eligibility/waiting-period check → frequency limits → network allowed amount → remaining deductible → fixed copay → coinsurance → annual maximum. - Given a procedure under a waiting period or exceeded frequency, When estimating, Then plan payment is $0.00 for that line and patient owes up to the allowed amount less in-network contractual write-off (if applicable). - Given remaining deductible, When applied, Then deductible reduces plan payment until exhausted and any remainder flows to coinsurance/coplan per plan. - Given annual maximum is reached mid-visit, When subsequent lines are processed, Then plan pays $0.00 on those lines and patient responsibility increases accordingly. - Given rounding and floors, When results are output, Then no negative values occur and all monetary fields are rounded to two decimals with currency.
Line-Item and Total Estimates With Write-Offs and Practice-Collectible
- Given contracted fee schedules and payer allowed amounts, When estimating, Then each line item includes providerFee, allowedAmount, contractualWriteOff = max(0, providerFee − allowedAmount) for in-network, and $0.00 write-off for out-of-network unless plan specifies otherwise. - Given patient cost-share and insurance payments, When summarizing, Then practiceCollectible = max(0, patientResponsibility − unappliedCredits − prepayments) is calculated and returned per line and total. - Given multiple procedures, When totals are produced, Then total fields equal the sum of line items and reconcile: providerFee = contractualWriteOff + primaryPaid + secondaryPaid + patientResponsibility per line and in total, within $0.01 tolerance. - Given deposits configuration, When a deposit policy exists (e.g., min($50, 30% of practiceCollectible)), Then estimatedDeposit is returned and never exceeds practiceCollectible.
Confidence Scoring Based on Data Completeness and Payer Responsiveness
- Given eligibility and benefits data sources, When scoring, Then the engine returns confidenceScore in [0,100] and confidenceLevel in {High, Medium, Low}. - Given last successful real-time eligibility within 7 days and complete cost-share (deductible, copay, coinsurance, max) present, When scoring, Then confidenceLevel is High (score ≥ 80). - Given partial benefits (missing at most one of deductible/copay/coinsurance/max) or stale eligibility (8–30 days), When scoring, Then confidenceLevel is Medium (50 ≤ score < 80). - Given payer unresponsive (no EDI/API response) or material gaps (≥2 missing cost-share fields) or eligibility older than 30 days, When scoring, Then confidenceLevel is Low (score < 50). - Given confidence output, When reasons are returned, Then the response includes confidenceFactors listing data gaps and lastEligibilityCheck timestamps used to derive the score.
Human-Readable Reasons and Assumptions
- Given an estimate is produced, When reasons are generated, Then the response includes a reasons array with at least: deductibleApplied, coinsuranceApplied, copayApplied, waitingPeriodStatus, frequencyLimitStatus, annualMaxStatus, networkStatus, COBRuleUsed, allowedAmountBasis, and dataGaps (if any). - Given assumptions are required due to missing data, When outputting, Then assumptions include explicit fallbacks (e.g., used provider fee as allowedAmount due to missing contract) and their impact on the estimate. - Given reasons and assumptions, When localized output is requested, Then user-facing text is returned in the requested locale while preserving machine-readable codes for each reason/assumption. - Given traceability, When returning reasons, Then each reason is linked to its corresponding line item and to plan identifiers (primary/secondary) where applicable.
Estimation API for Messaging and UI Modules
- Given the need to consume estimates, When calling POST /v1/estimates with procedures, feeScheduleId, and coverageIds, Then the API returns 200 with a payload containing: per-line and total amounts (providerFee, allowedAmount, writeOff, primaryPaid, secondaryPaid, patientResponsibility, practiceCollectible, estimatedDeposit), confidenceScore/Level, reasons, assumptions, and COB details. - Given idempotency, When the same request is retried with the same Idempotency-Key, Then the API returns the same estimateId and payload. - Given performance, When estimating up to 5 procedures with live eligibility cached ≤24h, Then 95th percentile latency is ≤ 2 seconds. - Given validation errors, When inputs are invalid or coverage is missing, Then the API returns 4xx with machine-readable error codes and does not create an estimate. - Given auditability, When an estimate is returned, Then the payload includes estimateId, createdAt, correlationId, and plan metadata (network status, COB rule) for both primary and secondary.
Patient-Friendly Cost Breakdown Messaging
"As a patient, I want a simple breakdown of what I’m expected to pay so that I can budget and avoid surprise bills."
Description

Render a concise, understandable breakdown of estimated costs in SMS and email, showing procedure names, insurance pays, patient pays, and any deposit requested. Include explanations for deductibles, coinsurance, and coverage limits in plain language, with expandable details and a standard disclaimer about estimate variability. Support multi-language templates, accessibility standards, and branded theming. Embed deep links to the patient portal for full details and consent capture.

Acceptance Criteria
SMS Cost Breakdown Rendering
Given a scheduled appointment with at least one planned procedure and an available estimate When an SMS with the cost breakdown is generated for the patient Then the SMS includes for each procedure a human-readable procedure name, the estimated “Insurance pays” amount, and the estimated “You pay” amount And, if a deposit is requested (> $0), the SMS includes “Deposit: $<amount>” And monetary values are formatted in the practice’s locale (e.g., $123.45) And the total estimated patient responsibility is clearly labeled (e.g., “Your est. portion: $<amount>”)
Email Cost Breakdown Rendering with Expandable Details
Given a scheduled appointment with at least one planned procedure and an available estimate When an email with the cost breakdown is generated for the patient Then the email displays a breakdown listing each procedure name with estimated “Insurance pays,” “You pay,” and any “Deposit” requested And the email includes an expandable/collapsible “How this was calculated” section And the expandable section explains deductible, coinsurance, and coverage limits in plain language and presents known values (e.g., deductible remaining, coinsurance percent, coverage cap) when available And the total estimated patient portion is visually emphasized above the fold
Standard Disclaimer Inclusion
Given any cost breakdown message (SMS or email) prepared for a patient When the message content is rendered Then a standard disclaimer indicating estimate variability is included verbatim from the approved template And in SMS the disclaimer length is ≤ 180 characters and placed after the breakdown And in email the disclaimer appears directly below the breakdown section and before any footer And the disclaimer cannot be removed by theme or language settings
Multi-Language Template Selection and Fallback
Given a patient with a recorded language preference When generating the SMS and email cost breakdown Then the system uses the matching language template for all fixed text and explanations And if the selected language template is unavailable, the system falls back to English and records a translation-missing event And numeric and currency values respect locale formatting rules of the selected language
Accessibility Compliance for Email Messages
Given the email cost breakdown template with branding applied When validated against WCAG 2.1 AA criteria Then body text and essential UI elements meet contrast ratio ≥ 4.5:1 And base font size is ≥ 16px and supports 200% zoom without loss of content or functionality And links and buttons have descriptive text (no “click here”) and are keyboard operable And the expandable details control uses semantic button markup with aria-expanded and aria-controls, operable via keyboard and screen readers And images (e.g., logo) include meaningful alt text
Branded Theming Without Compromising Readability
Given a practice with configured branding (logo, colors, display name) When the SMS and email cost breakdown messages are generated Then the practice display name appears in the SMS header text And the email renders the logo and color palette from branding settings And all text remains legible with contrast ratios meeting WCAG 2.1 AA despite applied colors And layout does not truncate or overlap content on common mobile and desktop email clients (e.g., Gmail, Outlook, Apple Mail)
Secure Deep Link to Portal for Full Details and Consent
Given an appointment with a generated cost estimate When the SMS or email is sent Then exactly one deep link to the patient portal cost breakdown and consent page is included And the link contains a secure, single-appointment token that expires within 72 hours or upon successful use And following the link routes the patient to the specific appointment’s cost breakdown and consent capture, requiring authentication if configured And if the token is expired or invalid, the patient sees a friendly message with a path to request a new link
Auto-Recalculation & Change Notifications
"As a scheduler, I want the system to auto-update estimates and notify stakeholders when things change so that we avoid day-of conflicts."
Description

Continuously monitor for changes in eligibility responses, fee schedules, appointment procedures, or plan rules and automatically re-run the estimate. Detect material deltas, version the estimate, and notify both staff and patients with a concise change summary highlighting the difference and rationale. Respect notification preferences and quiet hours, and log all updates with timestamps in the appointment timeline. Provide one-click staff acknowledgment and patient confirmation flows.

Acceptance Criteria
Real-time Monitoring Recalculates on Data Changes
Given an appointment with a saved estimate (v1) and a practice-configured material-delta threshold (default $10 or 2%) And monitoring is enabled for eligibility, fee schedules, procedures, and plan rules When a change is detected in any monitored source Then the estimate is re-calculated within 60 seconds using the latest data And multiple changes detected within a 5-minute window are coalesced into a single recalculation And if a monitored source is unavailable, retries use exponential backoff up to 3 attempts; after final failure a staff warning is logged and sent; no version change is made
Material Delta Detection and Estimate Versioning
Given a recalculation completes When the change in patient responsibility is greater than or equal to the material-delta threshold (absolute dollars OR percent) Then a new estimate version (vN+1) is created with an immutable snapshot of inputs and outputs And the version records prior vs new amounts, change amount and percent, primary reason codes, timestamp, and actor=system And if the delta is below threshold, no new version is created and no notifications are sent And threshold defaults to $10 or 2%, whichever is met first, unless overridden by practice settings
Staff Notification and One-Click Acknowledgment
Given a new estimate version is created due to a material delta And staff notifications are enabled for the location When the version is saved Then staff receive one notification per appointment per version within 2 minutes via their selected channels And the notification includes: previous total, new total, delta amount/percent, primary reason, version number, and an acknowledge link/button And one-click acknowledgment records user, timestamp, and optional note, and updates the appointment timeline And acknowledged versions suppress further staff reminders for that version And if delivery fails on a channel, fallback channels are attempted in the staff member’s configured order
Patient Notification with Preferences and Quiet Hours
Given a new estimate version exists with a material delta And patient notifications are permitted and the patient has opted in to at least one channel When the system evaluates contact preferences and quiet hours Then no messages are sent to the patient between 8:00 PM and 8:00 AM patient local time (configurable) And messages queued during quiet hours are sent at the next allowable time And the channel order respects patient preferences (SMS, email, voice) and opt-outs are honored And the message includes before/after estimate, change amount, brief rationale, appointment date/time, and a confirm link And SMS content excludes unnecessary PHI and fits within 2 segments; longer details are linked to a secure page
Appointment Timeline Logging and Audit Trail
Given any recalculation, version creation, notification (staff or patient), acknowledgment, delivery outcome, or patient confirmation occurs When the event is completed Then an immutable appointment timeline entry is written with timestamp, actor (system/user), event type, source of change, and a structured diff of financials (before/after) And notification delivery status (sent/delivered/failed), channel, and provider message IDs are logged And timeline entries are filterable by event type and exportable by authorized staff And logs are retained for at least 24 months (configurable per practice/legal policy)
Staff Override with Notes and Auto-Update Interaction
Given staff override the system-generated estimate and save with a required note Then the estimate is marked as staff-overridden with author and timestamp And subsequent automatic recalculations do not replace the displayed estimate unless the new system estimate differs from the override by at least the material-delta threshold (or an override-specific threshold if configured) And when such a difference occurs, staff are prompted to approve or reject the auto-update; no patient notification is sent until approved And all override actions, prompts, decisions, and resulting versions are logged to the timeline
Patient Confirmation Flow and Deposit Update
Given a patient receives a change notification with a confirm link When the patient selects Confirm or Requests Callback Then the response is captured with timestamp and recorded on the appointment timeline And confirmation suppresses further patient reminders for that version And the payment/deposit link updates to reflect the new estimate and any prior deposits, showing additional due or credit And if a deposit was already paid and the new estimate decreases, a refundable credit is created and flagged for staff review
Staff Override with Notes & Audit Trail
"As an office manager, I want the ability to override estimates with documented reasons so that we can handle exceptions transparently and maintain compliance."
Description

Allow authorized staff to override the predicted copay or deposit with a new amount, attach structured reasons (e.g., goodwill adjustment, promo, prior authorization pending), and free-text notes. Record user, time, and before/after values with immutable audit logs. Display override indicators in all patient-facing and staff views, and optionally require manager approval above configurable thresholds. Ensure overrides flow into messaging and payment requests while preserving the original estimate for analytics.

Acceptance Criteria
Override Within Threshold by Authorized Staff
Given a predicted copay or deposit exists for an appointment and the user has the Override:Copay permission When the user enters a new amount that is at or below the configured approval threshold, selects a structured reason, and optionally adds a free-text note Then the override is saved and associated to the prediction, the staff view reflects the overridden amount immediately, and a confirmation is displayed And the original estimate remains retained and viewable in the estimate history/details
Role-Based Access Control for Overrides
Given a user without the Override:Copay permission is viewing an estimate When the user loads the UI and calls the override API endpoint Then the override action is hidden in the UI and the API responds 403 Forbidden with no override created And an access denial event is recorded for audit without exposing PHI in logs
Immutable Audit Trail for Override Lifecycle
Given an override is created, approved, or rejected When the audit log for that estimate is retrieved Then an append-only event is present for each action including: event_id, appointment_id, patient_id, original_amount, overridden_amount, currency, reason_code, note, actor_user_id, actor_role, action_type (create|approve|reject), created_at (UTC ISO-8601), approval_threshold, approver_user_id (nullable), correlation_id And any attempt to update or delete an existing audit event is blocked and returns 409 Conflict, leaving the original event unchanged
Manager Approval Above Configurable Thresholds
Given approval_required is enabled and thresholds are configured for the location (by absolute amount and/or delta) When a user submits an override that exceeds the configured threshold Then the override status is set to Pending Approval, a notification is sent to users with Approve:CopayOverrides permission, and the overridden amount is not used in patient communications or payment requests until approval And upon approval the status changes to Approved, the overridden amount becomes active, and an approval audit event is recorded; upon rejection the status changes to Rejected, the original estimate remains active, and a rejection audit event is recorded
Override Indicators in Staff and Patient Views
Given an override exists for an estimate When staff view the schedule, patient timeline, estimate detail, or messaging preview Then an Override badge with the current override status (Pending/Approved/Rejected) is displayed with a tooltip showing before/after amounts, reason code, user, and timestamp And when the patient views messages or portals, an Updated estimate indicator is shown with the updated amount and friendly explanation, without exposing staff names, internal reason codes, or internal notes
Propagation to Messages and Payment Requests
Given an override is Approved or does not require approval based on thresholds When the system generates the next scheduled confirmation/reminder message and any associated payment request Then the message breakdown and payment request reflect the overridden amount and include an updated estimate indicator; payment links request the overridden amount And if the override is Pending, messages and payment requests continue to use the original estimate until approval And all generated artifacts reference the audit event ID for traceability
Analytics Preserve Original and Overridden Values
Given overrides have been applied to estimates When analytics reports and data exports are generated Then both original_predicted_amount and overridden_amount, the delta, reason_code, override_status, and approval_user_id are included without overwriting historical values And metrics can be filtered by override presence, reason_code, and approval status, ensuring the original prediction is preserved for longitudinal analysis
Deposit Request & Payment Link
"As a patient, I want a secure, easy way to pay my deposit ahead of the visit so that check-in is faster and I’m confident my spot is reserved."
Description

Enable practices to request a configurable deposit based on the estimated patient responsibility (flat amount or percentage), with business rules by procedure type, provider, and appointment lead time. Generate secure payment links in SMS/email, support major payment methods, and reflect completion status in the appointment record. Handle partial payments, refunds, and expirations, and provide reminders for unpaid deposits. Expose deposit KPIs and reconciliation exports for the billing team.

Acceptance Criteria
Configurable Deposit Calculation by Rules
Given an appointment with associated procedures, provider, and scheduled date When the system estimates patient responsibility Then it calculates a deposit using the active rule set as either a flat amount or a percentage of the estimate And rules can be conditioned by procedure type, provider, and appointment lead time windows And minimum and maximum deposit caps are enforced when configured And the computed deposit is rounded per practice settings and displayed with currency And authorized staff can override the calculated deposit before sending, must enter a reason note, and the override is audit-logged with user, timestamp, original amount, and new amount
Secure Payment Link Delivery via SMS/Email
Given a deposit request is created When sending via SMS or email Then the system generates a unique, signed, single-use payment URL that expires per practice-defined TTL And the URL contains no PHI; only a random token is present And message content includes deposit amount, due date, practice name, and contact info and renders mobile-friendly And resending regenerates a new token and invalidates all prior links And link clicks are tracked with timestamp, channel, and device metadata for audit And for unpaid deposits, reminders are scheduled per practice-defined cadence, stop upon payment, respect opt-out preferences, and include the current remaining balance and link
Support Major Payment Methods
Given the payment page is loaded from a valid link When the patient pays the deposit Then the system accepts Visa, Mastercard, American Express, Discover, HSA/FSA cards, ACH, Apple Pay, and Google Pay subject to processor availability And payments are processed via a PCI-compliant gateway; card data is not stored on SmileCue servers And wallet buttons are shown only when the device/browser supports them And on payment failure, a clear error is shown and retry is allowed without generating a new link unless the link has expired
Appointment Record Reflects Deposit Status and History
Given an appointment with a deposit request When a payment is completed Then the appointment record shows status Paid with amount, method, transaction ID, and timestamp And partial payments increment collected-to-date and update remaining balance And refunds post negative adjustments and update net collected And all deposit events (requested, sent, clicked, paid, partial, refunded, expired, overridden) are appended to a timeline with actor (user/system), channel, and notes And if estimated responsibility changes before the visit: if deposit unpaid, the system prompts recalculation and allows resend; if paid, staff are alerted to the variance
Partial Payments and Outstanding Balance Management
Given a deposit request allows partial payments per practice settings When a patient pays less than the requested amount Then the system records the partial amount, displays the remaining balance, and keeps the request open until fully paid or canceled And reminder scheduling and due dates are based on the remaining balance And staff can configure a minimum partial amount and due date rules (e.g., must complete N hours before appointment)
Refund Processing and Audit Trail
Given a completed deposit transaction When staff initiate a full or partial refund and provide a reason note Then the system processes the refund via the payment gateway and updates appointment status, remaining balance, and KPIs And refunds default to the original payment method; admin-only override allows alternate method with mandatory note And the refund is audit-logged with user, timestamp, amount, reason, and resulting balances And any active payment links for the refunded request cannot be reused; remaining balance (if any) is recalculated
Deposits KPIs Dashboard and Reconciliation Export
Given deposits activity within a selectable date range When billing views the deposits dashboard Then metrics are displayed: requests sent, conversion rate, total requested, total collected, average time-to-pay, partial vs full mix, refunds count/amount, breakdowns by provider, procedure, location, and channel And filters are available for location, provider, procedure type, and lead time brackets And export generates a CSV with line-level records: patient ID, appointment ID, procedure codes, requested/collected/refunded amounts, fees, processor transaction ID, deposit status, reconciliation status, and GL mapping And the export includes a creation timestamp and checksum; dashboard totals reconcile to export totals within 0.5%

SplitPay Families

Let caregivers split a bill across multiple payers, cards, or children in the same thread. Flexible allocations, per-child receipts, and stored preferences make pediatric and multi-guardian scenarios simple—fewer callbacks, happier families, and fully paid ledgers.

Requirements

Family Linking & Role Management
"As an office manager, I want to link children and multiple guardians into a single family with roles so that I can control who receives bills and who can authorize or pay them."
Description

Introduce a Family entity that links multiple patients (children) and multiple guardians/payers with clearly defined roles (e.g., primary guardian, secondary guardian, payer-only). Support custody constraints, permission scopes (who can view balances, receive statements, or authorize charges), and contact preferences per role. Provide staff UI to create, edit, merge, and search families without duplicating patient records. Enforce minimum necessary PHI exposure in shared threads, and handle lifecycle events (e.g., child aging into self-managed account) with role transition workflows.

Acceptance Criteria
Create Family with Multiple Guardians and Children
Given a staff user with Family Admin permission When they create a Family and add 2 existing patients as children and 2 guardians with roles (Primary Guardian, Payer-Only) Then a Family record with a unique FamilyID is created, links to the 2 existing patientIds without creating new patient records, and persists the 2 guardians with the specified roles Given any attempt to add a child already linked to a Family When the user tries to add that child again Then the system blocks the action with a clear error: "Child is already linked to Family [ID]" and no duplicate patient record is created Given the create form When required fields (at least one child, one guardian with a role) are missing Then Save is disabled and field-level validation messages are displayed Given normal network conditions When Save is clicked Then the Family is created within 2 seconds p95 and an audit entry is written with userId, timestamp, and change summary
Edit Roles, Custody, and Permission Scopes
Given an existing Family When a staff user updates a guardian's role and permission scopes (view balances, receive statements, authorize charges) per child Then changes are saved and immediately enforced in messaging and payments Given custody set to Sole for Child A When any non-custodial guardian tries to enable "authorize charges" for Child A Then the system prevents the change and displays: "Not permitted under sole custody for Child A" Given custody set to Joint for Child B When both guardians have "receive statements" off Then the system requires at least one guardian per child to have "receive statements" on, or staff must provide a documented override reason Given any change to roles, custody, or permissions When Save is clicked Then an audit log captures before/after values, actor, timestamp, and reason
Search Families by Identifiers
Given the Family Search UI When a staff user searches by child full name, guardian name, phone, email, or FamilyID Then matching families are returned with child and guardian counts and primary contacts Given a known family When searched by any linked phone or email Then it appears in the top 5 results with exact-match boosting Given 10,000 families in the tenant When a search is executed Then results render within 1 second p95 and pagination is available Given a selected result When the user opens it Then the Family detail shows linked children and guardians with roles and custody status per child
Minimum Necessary PHI in Shared Threads
Given a family thread includes Primary Guardian and Payer-Only When a statement is sent Then only users with "receive statements" for the relevant child receive a message that includes balance amount and child first name; no diagnosis/procedure codes or DOB are included Given a guardian without "view balances" When they open the thread Then balance amounts and invoice attachments are hidden for them Given any outbound message When recipients include mixed permissions Then the system generates permission-tailored message variants per recipient and logs each dissemination with recipientId, contentClass ("PHI" or "Non-PHI"), and child scope Given an attempt to attach a PHI document to a recipient lacking permission When Send is clicked Then the system blocks the send and identifies the recipient and missing permission
Role-Based Charge Authorization Enforcement
Given a pending charge for Child A When an authorized guardian with "authorize charges" for Child A approves it Then the authorization succeeds, is attributable to that guardian, and the event is logged with childId and guardianId Given a pending charge for Child A under Sole custody When a non-custodial guardian attempts to authorize Then the request is blocked with an error citing custody constraint Given Joint custody for Child B When any one authorized guardian approves the charge Then the charge is authorized without requiring the other guardian Given an unauthorized guardian When they attempt to authorize any charge Then the UI hides the authorize action and any direct API call returns HTTP 403 with an authorization error code
Child Ages Into Self-Managed Account
Given a child will reach the tenant-defined age-of-majority in 30 days When the nightly job runs Then the system queues a role transition workflow and sends notifications to guardians and the child's contact on file Given the workflow is active When the child completes identity verification and accepts responsibility Then the child's role becomes Primary Self, guardian roles transition per tenant policy (e.g., viewer or payer-only), and historical thread visibility is limited to messages they were permitted to see at the time Given the child declines or no response within 30 days When the deadline passes Then staff are alerted to review, and current roles remain until resolved Given any transition When it completes or is canceled Then an immutable audit record with consent artifacts is stored
Per-Role Contact Preferences and Per-Child Receipts
Given guardians have channel preferences (SMS, email, voice) per role and per child When a statement or receipt is generated for Child A Then it is delivered only to guardians permitted for Child A using their preferred channel; opt-outs are honored Given a payment split across Child A and Child B When receipts are sent Then separate per-child receipts are generated and delivered only to guardians with "receive statements" for each child; payer-only guardians receive receipts for allocations they paid Given a delivery failure (bounce or SMS DND) When sending statements or receipts Then the system logs the failure and surfaces an alert on the Family record with next-step recommendations Given a user updates contact preferences When Save is clicked Then changes take effect for the next outbound message and are auditable
Split Allocation Engine
"As a caregiver, I want to split a family bill across two cards and another guardian by percentage so that the costs are shared fairly and transparently."
Description

Enable flexible allocation of a family balance across payers, payment instruments, and children. Support allocation methods by percentage, fixed amount, per-child, or by procedure code, with caps, minimums, and even-split options. Calculate real-time remaining balances, pro-rate and handle rounding, and record allocation metadata for auditability. Apply practice credits and insurance adjustments in the correct order, and support reversals/refunds that preserve original allocation logic. Expose allocation via API/SDK and staff UI with clear previews before charge.

Acceptance Criteria
Multi-Payer Percentage Allocation with Cap and Rounding
Given a family balance of $325.37 And payer A set to 60% with cap $150.00 And payer B set to 40% with no cap And rounding mode = nearest cent with remainder to largest-actual allocation When the allocation is calculated Then payer A amount = $150.00 (cap applied) And payer B amount = $175.37 And total allocated = $325.37 and remaining balance = $0.00 And allocation metadata includes payer_ids, method=percentage, caps, rounding_remainder, actor_id, timestamp, and audit_id And per-payer ledger entries are created with the exact allocated amounts
Fixed Amount + Procedure-Code Allocation with Per-Child Receipts
Given children C1 and C2 with procedures: C1 D1120 $80.00, C1 D1206 $40.00, C2 D2140 $150.00 And family balance = $270.00 And guardian G1 pays fixed $100.00 applied to child C1 And guardian G2 pays remainder allocated by procedure code (100% of C2 D2140, then remaining C1) And two saved cards are selected (G1 Card ...1111, G2 Card ...2222) When the allocation is calculated and payment is authorized Then G1 is charged $100.00 allocated to C1 oldest procedures first (D1120 then D1206) And G2 is charged $170.00 allocated $150.00 to C2 D2140 and $20.00 to C1 D1206 And per-child receipts are generated showing procedures and amounts per child with totals C1=$120.00, C2=$150.00 And the ledger reflects allocations by child and procedure code And allocation metadata captures child_ids, procedure_codes, payer_ids, instrument_ids, and allocation_method
Credits and Insurance Adjustments Order of Operations
Given a family balance of $200.00 And an insurance adjustment of $30.00 and a practice credit of $50.00 available And two payers with even split selected When the allocation is calculated Then the insurance adjustment is applied first (-$30.00), then the practice credit (-$50.00) And the net allocable balance is $120.00 And each payer is allocated $60.00 And audit log records sequence [insurance_adjustment, practice_credit, patient_allocation] with timestamps and actor_id And credits/adjustments never exceed any child/procedure remaining balances
Refund/Reversal Preserves Original Allocation Logic
Given an original payment of $150.00 allocated under percentage method (G1 70% capped at $100.00, G2 30% no cap) And actual paid amounts were G1=$100.00, G2=$50.00 across children C1=$90.00 and C2=$60.00 And a refund of $50.00 is initiated due to cancellation of C2's procedure When the refund allocation is calculated Then the refund is applied first to payers based on their original contribution to C2: G1=$40.00, G2=$10.00 And the original allocation records remain immutable and a linked reversal entry is created with reference to audit_id of the original And remaining balances and receipts reflect the $50.00 refund without reallocating funds from unaffected items
Real-Time Preview and Remaining Balance in Staff UI
Given a staff user opens the SplitPay modal for a family balance of $412.58 And selects three payers with percentages 40/35/25, minimum per payer $20.00, rounding remainder to highest-priority payer When the user edits amounts or toggles even split Then the preview updates within 200 ms with per-payer amounts, per-child allocations, and remaining balance And the Charge button is disabled if total allocated != net balance or if any payer amount < minimum And upon charging, the posted ledger equals the preview values and remaining balance = $0.00
Even Split with Minimums and Pro-Rata When Minimums Exceed Balance
Given a family balance of $75.00 and three payers with even split and minimum $30.00 each When the allocation is calculated Then because sum of minimums ($90.00) exceeds the balance, the engine pro-rates by minimum weights And each payer is allocated $25.00 (rounded to cents with last-cent remainder applied to payer1 if any) And total allocated = $75.00 and remaining balance = $0.00 And the rule evaluation is recorded in allocation metadata: rule=pro_rate_minimums_overflow
API/SDK Allocation Exposure and Stored Preference Override
Given a stored family preference: G1 50% cap $120.00 on Visa ...1234, G2 50% no cap on MC ...7777, per-child receipts enabled And a new net balance of $260.00 When a POST /allocations API request is made without explicit allocation parameters Then the response 201 includes allocation: G1=$120.00, G2=$140.00, with fields audit_id, applied_preference_id, payer_breakdown[], child_breakdown[], rounding_remainder When a staff UI override of 70/30 is submitted for a $200.00 charge Then the resulting allocation matches override logic with cap handling: G1=$120.00 (cap), G2=$100.00 And override_reason is required and captured; applied_preference_id is null; new_preference_saved=false unless Update default is checked
Per-Child Itemized Receipts
"As a parent, I want separate itemized receipts for each child so that I can submit them to different FSAs and keep our records organized."
Description

Generate HIPAA-compliant, itemized receipts per child with clear attribution of procedures, amounts, and payer contributions. Include FSA/HSA-friendly detail (provider, tax ID, CDT/CPT descriptors where applicable), unique receipt IDs, and practice branding. Deliver receipts in-thread via secure links with time-limited access, support multi-language templates, and allow staff to re-send or download. Store receipts with allocation context for future reference and audits while limiting PHI to the minimum necessary.

Acceptance Criteria
Per-Child Itemized Receipt Generation After Split Payment
Given a family payment is posted with allocations across multiple children in one thread When the payment is finalized Then the system generates a separate receipt for each child within 5 seconds And each receipt includes only that child’s procedures and service dates And each line item shows code (CDT/CPT), description, unit price, quantity, discounts/adjustments, payer contribution(s) by source, and line total And the receipt shows child-specific subtotal, total paid, and remaining balance (if any) And totals equal the sum of line items within $0.01 rounding tolerance And if the allocation is partial, the receipt is labeled “Partial Payment” with remaining balance displayed
FSA/HSA-Compliant Receipt Content and Validation
Given a child-specific receipt is generated Then the receipt includes practice legal name, address, phone, provider name, NPI (if applicable), Tax ID/EIN, date(s) of service, CDT/CPT codes with descriptors, charge per code, total charged, amount paid, and payment method label (e.g., FSA/HSA, card last 4) And currency values display with ISO currency code and two decimals And diagnosis codes and clinical notes are excluded And before sending, required FSA/HSA fields are validated; missing fields block send and present a clear error to staff And the receipt is available as a downloadable PDF suitable for FSA/HSA submission
Unique Receipt ID and Practice Branding
Given a child-specific receipt is generated Then it is assigned an immutable Receipt ID unique across SmileCue (e.g., SC-<practiceId>-<YYYYMMDD>-<random>) with uniqueness enforced at the database level And the Receipt ID appears on the PDF, web view, and in all audit events And the header shows practice logo (if configured), practice name, and contact information; if no logo, a text header is used
Secure Time-Limited In-Thread Delivery
Given a receipt is ready to be delivered in the family’s SmileCue thread When the caregiver is sent the link Then the link contains a token valid for 14 days and up to 5 authenticated opens And accessing the link requires SMS OTP to a verified thread participant or DOB verification, as configured by the practice And all traffic uses TLS 1.2+; no PHI is rendered until authentication succeeds And after expiry or revocation, the link shows an expiration notice without PHI and returns HTTP 401/403 And each access attempt is logged with timestamp, user/caregiver identifier, and outcome
Multi-Language Receipt Templates and Selection
Given a caregiver’s preferred language is stored as Spanish and a Spanish template exists When a receipt is generated Then all static labels and headings render in Spanish; procedure descriptors use translated text if available, otherwise default to standard code descriptors And if the preferred language is unsupported, the system defaults to English and records a fallback event And staff can preview and choose the language before sending And template text is externalized for localization without code changes
Staff Re-Send and Download with Audit Trail
Given a staff user with Billing or Admin role opens the family thread When they select a child’s receipt Then they can download the PDF and re-send a secure link to selected thread participants And re-sending generates a new token; existing tokens remain valid until expiry unless explicitly revoked by staff And all actions (view, download, send, revoke) are logged with user ID, timestamp, child, and Receipt ID And users without sufficient role receive an authorization error and no receipt data is exposed
Storage with Allocation Context and Minimum Necessary PHI
Given a receipt is generated Then the system stores an immutable record containing Receipt ID, child identifier, payer sources, per-line allocation breakdown, service dates, codes, descriptors, amounts, and totals And excludes clinical notes, images, and unrelated appointment details to satisfy minimum necessary PHI And adjustments/refunds create a new versioned receipt linked to the original; originals are retained And access to stored receipts is restricted to authorized practice users; all retrievals are audited And receipts are retained per practice policy (minimum 7 years) and exportable for audit without exposing other children’s data
In-Thread Payment Collection
"As a secondary guardian, I want to pay my assigned portion directly from the message thread so that I can complete payment quickly without calling the office."
Description

Collect split payments directly within existing SmileCue SMS/email/voice threads. Generate secure, payer-specific payment links reflecting each party’s allocation and due date. Support tokenized card entry (PCI SAQ-A), Apple Pay/Google Pay, HSA/FSA cards, partial payments, and 3D Secure/SCA where required. Provide real-time status updates to staff, idempotency to avoid duplicate charges, concurrency controls across multiple payers, and fallback voice IVR. Integrate with supported gateways (e.g., Stripe, Authorize.Net) via tokens only; never store raw PANs.

Acceptance Criteria
Split payments across multiple payers and children in SMS thread
Given a family thread with two children and a $600 balance, when staff initiates SplitPay with allocations $200 to Caregiver A for Child 1, $150 to Caregiver A for Child 2, and $250 to Caregiver B for Child 2, then the UI shows per-payer, per-child allocations that sum to $600 with $0 remainder. Given split allocations are sent in-thread, when Caregiver A pays $175 of her $350 total allocation, then the system records a partial payment, shows $175 remaining for Caregiver A, leaves Caregiver B’s $250 unchanged, and updates per-child ledgers accordingly. Given per-child receipts are required, when any payment is captured, then the payer receives an itemized receipt grouped by child with amount, masked payment method (brand + last4), auth/txn ID, and timestamp, and the practice ledger links the receipt to the thread. Given stored split preferences exist for the family, when a new balance is posted, then default allocations auto-fill and are editable prior to sending links.
Payer-specific secure payment links with allocations and due dates
Given split allocations are created, when links are generated, then each payer receives a unique single-use HTTPS URL with an opaque token bound to their allocation amount, due date, currency, and payer ID. Given link expiration is set to 7 days or upon full capture, when a payer clicks an expired or already-used link, then an expiration page is shown with an option to request a new link and payment is blocked. Given staff resends a link, when the resend is triggered, then a new tokenized URL is issued, the prior link is invalidated immediately, and an audit log records both events. Given a payer opens their link, when the page loads, then staff see an “Opened” status with timestamp in real time on the thread.
Tokenized card entry and wallet support (PCI SAQ-A, no PAN storage)
Given a payer opens their link, when they choose card entry, then the card form is gateway-hosted or via tokenization fields and SmileCue never receives or stores raw PAN/CVV. Given the device supports Apple Pay or Google Pay, when the payer selects a wallet, then a payment sheet appears and a tokenized payment method is created and used for the charge. Given the payer uses an HSA/FSA card, when tokenization and authorization are requested, then the transaction is attempted with appropriate healthcare MCC/metadata and succeeds if issuer permits. Given the practice uses Stripe or Authorize.Net, when payment is submitted, then the charge is created using tokens only with descriptors and metadata referencing internal IDs (no PHI) and a success/decline response is returned. Given PCI scope constraints, when production data stores and logs are inspected, then no PAN/CVV/track data exists and only tokens, last4, and non-sensitive metadata are present.
3D Secure/SCA enforcement where required
Given the payer’s card/region requires SCA, when the payer attempts payment, then a 3D Secure authentication flow is initiated and capture only occurs after successful authentication with liability shift recorded. Given a frictionless 3DS result is returned, when capture proceeds, then the payment completes without a challenge and the 3DS result is stored with the transaction. Given the payer cancels or fails 3DS, when returning to the payment page, then no charge is created, a clear “Authentication failed” message is shown, and the link remains usable until expiry. Given the card/region is out of SCA scope, when payment is processed, then no 3DS prompt occurs and the transaction is logged as out-of-scope.
Real-time payment status updates to staff
Given staff has the conversation thread open, when a payer opens a link, starts 3DS, authorizes, captures, or fails payment, then the dashboard updates within 3 seconds via live updates with statuses: Opened, In-Progress, Authorized, Captured, Failed, Refunded, and shows remaining balance per payer. Given multiple captures occur across payers, when the total allocation for the balance reaches $0, then the thread shows a “Fully Paid” badge and further capture attempts are blocked. Given a temporary network disruption occurs, when live updates fail, then the system retries for up to 60 seconds and falls back to polling every 15 seconds while displaying a “Syncing…” indicator. Given audit requirements, when any payment status changes, then an immutable audit log entry is created with user or system actor, event type, timestamp, gateway transaction ID, and payer link token.
Idempotency and concurrency controls across multiple payers
Given a payer double-submits the payment within 10 seconds, when the server receives duplicate requests with the same idempotency key, then only one charge is created and subsequent requests return the original result. Given two payers attempt to pay overlapping amounts simultaneously, when the first capture posts, then the second request atomically validates remaining balance and either adjusts to the new maximum allowed or fails with “Amount exceeds remaining” without creating a charge. Given the same payer has the link open on two devices, when one device completes payment, then the other device reflects the updated remaining balance or link expiry within 5 seconds and prevents duplicate capture. Given a gateway timeout occurs, when a retry is initiated, then the same idempotency key is reused and at most one settled transaction exists in the gateway and ledger.
Fallback voice IVR payment capture
Given a payer replies with a voice prompt keyword or interacts with a voice reminder, when the IVR flow starts, then the call is routed to a PCI-compliant IVR that collects card details via DTMF masking and returns a tokenized payment method. Given the IVR successfully captures a payment, when the transaction settles, then the payer receives SMS/email confirmation, the staff dashboard reflects the capture within 10 seconds, and any call recording excludes DTMF tones. Given the payer abandons the IVR flow, when 2 minutes of inactivity elapse, then a follow-up payment link is sent and the thread logs the abandonment event. Given wallets are unavailable in IVR, when presenting options, then the system offers alternatives including connecting to staff during business hours.
Stored Preferences & Auto-Allocation Rules
"As a busy parent, I want my saved split rules to auto-apply to new visits so that payments happen with minimal coordination."
Description

Allow families to save split preferences (e.g., 60/40 between guardians, card X for child A, cap of $200 per visit) and automatically apply them to new balances. Capture explicit consent per rule, effective dates, and exceptions (e.g., orthodontics not included). Provide UI to review, override, and simulate outcomes before charging. Handle expired cards, re-consent prompts, and notify payers when rules are applied. Support pre-authorization of estimated amounts and automatic top-ups within consented limits.

Acceptance Criteria
Auto-Apply Stored Split Preferences on New Balance
Given a family profile with stored split preferences: 60% Guardian A (Visa ••••1111), 40% Guardian B (MC ••••2222), per-payer cap $200 per visit, exclusion: orthodontics, effective 2025-01-01 to 2025-12-31 And a new balance of $300 is posted for Child A with procedure D1110 (not orthodontics) When the balance is created in the ledger Then the system computes allocations of $180 to Guardian A and $120 to Guardian B And no payer allocation exceeds the $200 per-visit cap And excluded procedures are not considered in allocation (not applicable here) And the allocation is presented in the review UI with rule version, consent ID, and effective date displayed And no charge is executed until a user confirms or a valid pre-authorization exists covering the amounts
Capture and Manage Explicit Consent for Split Rules
Given an office user configures a new split rule for a family When the rule is saved Then the system requires explicit consent from each affected payer with scope (children, procedures), effective start/end dates, and maximum per-visit/top-up limits And captures consent artifacts: timestamp, consenting user identity, device/IP, consent text version, and signature/affirmation And stores a rule version ID and links it to the consent record And prevents rule activation without completed consent for all required payers And prompts for re-consent when any rule term changes or when consent expires And maintains an immutable audit trail retrievable by date range and rule version
Simulation and Override Before Charge
Given an allocation has been computed by stored preferences When a staff user opens the Simulation & Review screen Then the UI displays per-payer allocations, cards on file, caps, exclusions, and consent limits And allows temporary overrides for this visit only: adjust percentages, swap payment method, exclude a procedure, or set manual amounts And validates in real time that overrides do not exceed consented caps or violate exclusions And shows updated payer totals, per-child totals, and fees before charging And requires user confirmation to proceed, with a summary snapshot stored with the transaction And provides Cancel and Revert to Rule actions that restore original allocations
Expired/Declined Card Handling and Re-Consent Prompts
Given a computed allocation targets a stored card that is expired or declines authorization When the system attempts pre-authorization or charge Then the charge for that payer is not executed and the payer is flagged as Action Required And the office is shown remediation options: select alternate stored method (if consent covers it), send secure update link, or reassign amount within consent limits And the system does not reallocate the shortfall to other payers if doing so would exceed their consent caps And if a new payment method is added or payer responsibilities change beyond consent scope, the system prompts for re-consent before proceeding And all failures, retries, and resolution outcomes are logged with reason codes
Notify Payers When Rules Are Applied
Given stored preferences are applied to a new balance When allocations are computed (pre-charge) and/or charges are executed Then payers receive HIPAA-compliant notifications via their preferred channel (SMS/email/voice) within 2 minutes And notifications include child name(s) initial/first name, allocated amount, last4 of payment method, and action link to review/update And exception states (e.g., card expired, consent needed) are clearly indicated with next steps And delivery status is tracked (queued, sent, delivered, failed) and visible in the communication log And duplicate notifications are suppressed within a 24-hour window for the same event
Pre-Authorization and Automatic Top-Ups Within Limits
Given a visit has an estimated balance and payers have consented to pre-authorization and top-ups up to defined caps When the estimate is finalized before or at checkout Then the system places separate pre-authorizations per payer for the estimated amounts And upon final charge, captures against the pre-auths and automatically tops up any shortfall up to the payer’s consented per-visit limit And declines any amount exceeding the limit and flags the remaining balance for manual resolution And releases unused pre-authorization amounts within 24 hours of final capture And records authorization IDs, captures, and top-ups in the audit log and on payer receipts
Per-Child Receipts and Ledger Posting
Given allocations and charges are completed for a multi-child family When receipts are generated Then each payer receives itemized receipts per child with allocated amounts, method last4, authorization/transaction IDs, and date/time And the practice ledger posts payments at the child and procedure level, matching the allocation breakdown And total of per-child receipts equals the total charged amounts across payers And the family thread displays a consolidated summary with links to each per-child receipt And refunds or adjustments later preserve the original allocation proportions unless explicitly overridden with consent
Consent, Authorization & Compliance
"As a practice owner, I want compliant authorizations for split payments and stored rules so that we reduce legal and security risk while protecting patient privacy."
Description

Capture and store payer authorization for split charges, stored preferences, and use of tokenized payment methods via e-sign within the communication thread. Enforce HIPAA minimum necessary access, role-based permissions, and age-of-consent and custody checks. Ensure PCI compliance by using gateway tokenization and never persisting sensitive card data. Provide clear consent language, revocation workflows, and auditable timestamps, IP/device metadata, and signer identity verification steps appropriate for guardians and payers.

Acceptance Criteria
Guardian e‑Sign Authorization for Split Charges and Stored Preferences in Thread
Given a SplitPay invoice requiring authorization is sent within an SMS/email thread When a guardian opens the consent link from the thread Then the system displays the current consent text with version ID and last-updated date And requires explicit agreement via unchecked checkbox and typed full name e‑signature And verifies identity using a 6‑digit OTP (valid 10 minutes, max 5 attempts) sent to a verified channel on file, plus one knowledge factor (patient DOB or ZIP) And captures an authorization record linked to the payer and invoice with: authorizationId, consentVersionId, UTC timestamp (ISO 8601), IP, device metadata, verified channel, verification outcome And prevents token storage or charge execution until authorization status=Signed And returns an on-screen and in-thread confirmation referencing authorizationId
Role-Based Access and HIPAA Minimum Necessary Enforcement in SplitPay Thread
Rule: Only Billing Admin and Office Manager can initiate consent requests and view authorization summaries. Rule: No role may view full PAN or CVV; only token, brand, and last4 are visible; CVV is never collected or stored. Rule: Clinician and Hygienist may see only authorization state (Authorized/Not Authorized) and allocation totals; payer contact details and balances are hidden. Rule: Front Desk may view payer contact details and confirmation status but not token details or per-child clinical PHI. Rule: Access outside the user's assigned practice location is denied (HTTP 403) and logged. Rule: Every access is audit-logged with userId, role, patientId, threadId, action, and UTC timestamp; audit entries are immutable.
PCI Tokenization with Zero PAN Persistence During SplitPay Collection
Given a payer enters card data during SplitPay setup When card fields are displayed Then they are rendered using gateway-hosted fields/iframe, and keystrokes post directly to the gateway domain per CSP And upon submit, the platform receives only a payment token, brand, last4, and expiry; no PAN or CVV transit through or persist in platform servers And database schemas, logs, analytics, and error traces contain no PAN/CVV; automated DLP scans (Luhn + BIN patterns) on logs return 0 matches And stored records include token, brand, last4, expiry, payerId, and tokenCreatedAt UTC; CVV is never stored And recurring or split captures use the token only And the deployment maintains PCI SAQ A scope with current AOC on file.
Age-of-Consent and Custody Validation Prior to Authorization
Given patient DOB, practice location, and custody flags are present in the patient record When initiating authorization for SplitPay and stored preferences Then if patientAge < jurisdictionalAgeOfConsent, the patient cannot self-authorize; at least one verified guardian must authorize per custody rules And if custody=BothRequired, authorization must be signed by all designated guardians before status=Signed And if custody=RestrainedGuardian, that guardian cannot be invited or sign; any attempt is blocked and logged And if patientAge >= jurisdictionalAgeOfConsent, the patient may self-authorize; guardian signatures are optional And the consent screen displays whose authorization is required and remaining signers And all custody and age determinations are recorded in the authorization metadata with the rule rationale.
Consent Revocation and Charge Halt Workflow for SplitPay Payers
Given a payer previously authorized split charges and stored token use When the payer texts STOP in the thread or clicks the Revoke Consent link Then the payer's authorization status transitions to Revoked within 60 seconds And future scheduled or pending captures using that authorization are blocked; staff is alerted in the SplitPay thread and via inbox And stored preferences tied to that authorization are disabled; re-enablement requires fresh e‑sign and re-verification And the payer receives a confirmation message with timestamp and a link to manage preferences And an audit entry is created with revocation method, channel, UTC timestamp, and actor identity.
Auditable Consent Record with Timestamps, IP/Device, and Tamper Evidence
Given an authorized or revoked consent record exists When a Billing Admin or Office Manager views the record Then they can export a read-only PDF/JSON package containing: authorizationId, consentVersionId, full consent text, UTC timestamps, IP, device metadata, verification steps/results, signer role and relationship, and event history And the package includes a SHA-256 hash and sequence number; any modification produces a hash mismatch And records are append-only; corrections are new entries linked by priorHash And retrieval respects role-based access; all views are audit-logged And records are retained for at least 7 years or per practice policy, whichever is longer.
Clear Consent Language and Disclosure Readability Compliance
Rule: Consent text explicitly covers split allocation scope, stored token use, recurring/partial charges, revocation process, responsibility for declined payments, and HIPAA/PCI notices. Rule: Readability score is Flesch-Kincaid Grade Level ≤ 8.0 as measured by an automated check in CI; build fails if higher. Rule: Language is localized to payer's locale from profile or device; fallback to English; legal links to Privacy Policy and Terms are present and functional. Rule: No pre-checked boxes; an explicit checkbox and typed name are required; Cancel option is available and non-destructive. Rule: The displayed consent includes a visible version ID and last-updated date; the exact text and version are stored with the authorization record.
Ledger Sync & Reconciliation
"As a billing coordinator, I want split payments to sync accurately to our PMS per child so that our ledgers and reports remain correct without manual fixes."
Description

Post split payments back to the practice management system per child and procedure with allocation details, mapping to the appropriate providers, CDT/CPT codes, and ledgers. Support bi-directional sync for adjustments, voids, and refunds with robust idempotency to prevent duplicate postings. Provide a reconciliation dashboard and daily reports showing outstanding balances by family and payer, gateway settlement references, and exception handling with retry queues and alerts for failed writes or mismatches.

Acceptance Criteria
Procedure-Level Allocation Posting to PMS
Given a successful payment with split allocations by child and procedure and an idempotency_key unique per allocation, When the sync worker processes the payment within 2 minutes of capture, Then the PMS contains exactly one payment posting per allocation mapped to the correct patient (child), provider_id, CDT/CPT code, and service_date with amount equal to allocation_amount (±$0.01 rounding tolerance). And Then the PMS family and child ledgers decrease by the sum of allocations and SmileCue stores the PMS transaction/reference IDs on each allocation. And Then an audit log entry is written containing payment_id, allocation_id, idempotency_key, provider_id, procedure_code, pms_reference_id, and created_at.
Idempotent Posting and Safe Retries
Given the same allocation (same idempotency_key) is delivered multiple times or retried, When the sync processes it, Then only one PMS posting exists for that idempotency_key and subsequent attempts are no-ops logged as deduped=true. Given a transient PMS failure (HTTP 5xx or timeout), When processing the allocation, Then the job retries up to 5 times with exponential backoff (1m, 5m, 15m, 1h, 6h) and preserves the idempotency_key across attempts. Given a non-retriable validation error (e.g., 4xx mapping/constraints), When encountered, Then the job is not retried, the exception is recorded with error_code and payload snapshot, and the allocation remains Pending Exception.
Bi-Directional Adjustments, Voids, and Refunds
Given a refund, void, or adjustment initiated in SmileCue for a posted allocation, When the sync runs, Then a corresponding PMS transaction is created reversing or adjusting the exact amount and linked to the same child, procedure, and provider, and SmileCue stores the PMS reference IDs. Given a refund, void, or adjustment is created in the PMS, When the next poll/webhook is received, Then SmileCue ingests it within 5 minutes, updates the family/child ledgers, and marks the related allocation with the correct reversal/adjustment status. Then per-family net balances match between systems with $0.00 variance after processing completes.
Code and Provider Mapping Validation
Given an allocation references a CDT/CPT code and provider, When posting to PMS, Then the code and provider_id are validated against the active mapping table version and practice context prior to write. Given an unmapped or inactive code/provider, When detected, Then the posting is blocked, an exception is raised with error_code=MAPPING_MISSING including child_id, procedure_code, provider_id, and a remediation hint, and the item is placed in the exception queue. Given a mapping override is applied by an authorized user, When the item is retried, Then the posting succeeds and the original exception is auto-resolved with a link to the successful posting.
Reconciliation Dashboard Metrics and Drilldown
Given reconciled and unreconciled items exist, When a user opens the Reconciliation Dashboard, Then it loads within 2 seconds for the last 30 days and displays: outstanding balances by family and payer; PMS vs SmileCue ledger deltas; gateway settlement references (batch_id and txn_id) per payment; counts of exceptions and their oldest age. Then selecting a family row shows child- and procedure-level entries with posting status (Posted, Pending, Exception), allocation amounts, PMS reference IDs, and last attempt time. And Then all totals in the UI match exported CSV totals for the same filter criteria.
Daily Reconciliation Report Generation and Delivery
Given activity occurred in the prior day, When the daily job runs at 05:00 in the practice’s configured timezone, Then a CSV and PDF report are generated for 00:00–23:59 containing totals by family and payer, PMS vs SmileCue deltas, exceptions, and gateway settlement references. Then the report is delivered via secure email and/or SFTP to configured recipients by 06:00, and a copy is archived with immutable checksum and retained for 7 years. And Then failures to generate or deliver the report create an exception with retry attempts and alerting per the alerts policy.
Exception Alerts and On-Call Notifications
Given a posting fails after maximum retries or a ledger mismatch > $0.00 is detected, When the event occurs, Then an alert is sent within 5 minutes to the configured Slack/email/on-call channel containing trace_id, family_id, error_code, severity, and recommended next_action. Then the exception appears in the dashboard queue with status=Open and supports actions Retry, Resolve (with reason), and Ignore (with justification) under role-based access control, with all actions timestamped and attributed to the user. And Then closing the exception triggers a reconciliation re-check and removes the item from open alerts if balances are settled.

LineSync Ledger

Map each payment to the right PMS ledger code, provider, and location with automatic transaction IDs, partial/overpayment handling, and end-of-day reconciliation exports. Refunds and voids sync both ways, eliminating double-posting and month-end cleanup.

Requirements

Ledger Code Mapping Engine
"As an office manager, I want payments to auto-map to the correct PMS ledger codes so that I don’t have to manually reclassify transactions and risk month-end discrepancies."
Description

Implement a rule-driven engine that maps each incoming payment, adjustment, and credit to the correct PMS ledger code based on payment method, procedure type, payer, provider, and location. Support versioned mapping rules, fallbacks, and validation against PMS metadata to prevent invalid codes. Provide low-latency lookups for real-time posting and maintain backward compatibility when rules evolve. Integrate with SmileCue payment events and PMS APIs/webhooks to ensure seamless, accurate categorization the moment a transaction is authorized or settled.

Acceptance Criteria
Real-Time Mapping on Authorization and Settlement Events
Given a SmileCue payment, adjustment, or credit event with attributes {event_id, event_type, payment_method, procedure_type(s), payer, provider_id, location_id, amount, effective_timestamp} When the mapping engine evaluates the event Then it selects the ledger_code from the highest-priority active rule that matches all provided attributes as of the event's effective_timestamp And includes provider_id and location_id in the PMS posting payload And returns {mapping_id, ledger_code, rule_version, effective_timestamp} in the mapping response And proceeds to PMS posting only after successful metadata validation
PMS Metadata Validation Before Posting
Given a proposed mapping result with ledger_code X and PMS target {provider_id, location_id} When validating against PMS metadata Then the engine confirms ledger_code exists and is active in PMS, is permitted for the target provider/location, and is compatible with the transaction type (payment/adjustment/credit) And if any check fails, the engine blocks posting, marks the mapping as ValidationFailed with reason codes, emits an error event, and stores an audit record And if a configured validation fallback rule exists, the engine reevaluates and uses the first valid fallback code; otherwise the mapping remains unposted
Fallback Rule Hierarchy for Unmatched Transactions
Given no specific rule matches an incoming event When mapping is attempted Then the engine applies the fallback hierarchy in order: provider+location default -> payment_method default -> global default And if a valid code is found at any level, the engine uses it and records fallback_level used in the audit trail And if no valid code is found, the engine marks the event as Unmapped, does not post to PMS, raises an alert, and emits an UnmappedTransaction event with a correlation_id
Versioned Rules with Backward Compatibility and Auditability
Given rule versions v1 (active until T) and v2 (active from T+1) When evaluating an event with effective_timestamp <= T Then v1 is used to compute the ledger_code And when evaluating an event with effective_timestamp >= T+1, v2 is used And the mapping response includes rule_version_id and rule_hash And reprocessing the same event_id at any future date yields the same ledger_code and rule_version used originally And an admin can roll back to v1 without affecting mappings already produced under v2
Performance and Low-Latency Lookups
Given a production-like load of 200 mixed events per second over 30 minutes with warmed caches When the mapping engine processes events Then end-to-end mapping latency (receive -> mapping response produced, excluding PMS API latency) is <= 50 ms at p95 and <= 150 ms at p99 And error rate for mapping (excluding downstream PMS failures) is < 0.1% And throughput does not drop below 200 events/sec with CPU utilization < 70% on the target deployment profile
Idempotent Mapping and Duplicate Event Handling
Given duplicate delivery of the same SmileCue event (same event_id or idempotency_key) within a 24-hour window When the engine receives duplicates Then only one mapping is executed and at most one PMS posting occurs And subsequent duplicates return HTTP 200 with the same mapping_id and mapping result without side effects And authorization followed by settlement for the same payment results in a single ledger mapping that is reused, not remapped or double-posted
Idempotent Transaction Correlation
"As a billing coordinator, I want guaranteed idempotency for ledger postings so that duplicate webhooks or retries never create double entries in our PMS."
Description

Generate and persist globally unique transaction IDs and correlation keys to guarantee idempotent posting across SmileCue, the payment gateway, and the PMS. Deduplicate replays, retries, and webhook storms; record cross-system references (gateway transaction ID, PMS receipt/entry ID) to prevent double-posting. Expose a reconciliation-safe API and enforce write-once guarantees with optimistic concurrency control for updates such as voids and refunds.

Acceptance Criteria
Global Transaction ID Generation & Persistence
Given a new payment initiation without an existing SmileCue Transaction ID When the Create Payment API is called Then the system generates an RFC 4122 UUID v4 transactionId and persists it atomically before any outbound gateway or PMS call And the API response includes transactionId and correlation/idempotency fields And the transactionId is propagated to gateway metadata/correlation fields And the transactionId is immutable after creation
Client-Supplied Idempotency Key Enforced
Given POST /payments is called with the same X-Idempotency-Key within a 24-hour window When the first request is accepted or in-flight Then subsequent identical requests return 200 with the original result payload and do not create additional ledger, gateway, or PMS entries And if the first request is still processing, subsequent requests return 202 with a polling link and do not trigger new side effects And all deduplicated requests include the original transactionId in the response
Webhook Replay/Storm Deduplication
Given the gateway sends duplicate and out-of-order webhooks for the same gatewayTransactionId (e.g., 10 events within 5 minutes) When SmileCue processes these events Then each gatewayTransactionId is applied at most once per state transition And duplicate events are acknowledged without side effects And final ledger state reflects the last valid transition by gateway timestamp And one append-only ledger entry exists per business event with a processedAt timestamp and idempotency hash
Cross-System Reference Recording & Queryability
Given a transaction is captured and posted to PMS When recording cross-system references Then the tuple {smilecueTransactionId, gatewayTransactionId, pmsEntryId, providerId, locationId} is persisted atomically And these references are immutable and auditable with createdAt and updatedAt in UTC And the Reconciliation API can retrieve the transaction by any of these IDs and return up to 1000 results with p95 latency ≤ 200ms
Reconciliation-Safe Read API
Given transactions exist across statuses (authorized, captured, voided, refunded, failed) When GET /reconciliation?from=...&to=... is called Then results are sorted by transactionId with stable, cursor-based pagination and no duplicates across pages And each record includes cross-system references and parentTransactionId for refunds/voids And repeated GETs with the same cursor and parameters return identical data (idempotent reads) And each record includes a monotonic sequenceNumber to support end-of-day cutoffs
Write-Once Ledger with Optimistic Concurrency for Voids/Refunds
Given a captured transaction exists When two clients submit conflicting void or refund requests concurrently with If-Match version headers Then exactly one request succeeds (200) and increments the version; the other fails with 409 Conflict and no side effects And voids are rejected with 422 if the transaction is already voided or refunded And partial refunds may be applied until the original amount is exhausted; attempts to exceed remaining refundable amount are rejected with 422 And all updates create append-only ledger entries; original entries remain immutable
Retry Safety and Background Reconciliation
Given a gateway timeout occurs after the capture request was sent with the idempotency key When SmileCue retries with exponential backoff up to 5 attempts Then the gateway processes the capture at most once and SmileCue correlates the final outcome to the original transactionId And if retries exhaust without certainty of outcome, status is set to PendingExternalConfirmation and no PMS post occurs And a background reconciler polls the gateway by correlation key every 5 minutes for up to 24 hours and finalizes the ledger exactly once when the outcome is known
Partial & Overpayment Allocation
"As a front-desk receptionist, I want to correctly allocate partial and overpayments across procedures so that patient balances and reports stay accurate without manual spreadsheets."
Description

Support allocation of partial payments, overpayments, and unapplied credits across multiple procedures, providers, and dates of service. Provide configurable allocation strategies (e.g., oldest balance first, by procedure priority, by provider quotas) and allow manual overrides with audit trails. Synchronize allocations and remaining balances with the PMS, including creation of credits or adjustments where supported, and enforce rounding rules consistent with PMS constraints.

Acceptance Criteria
Allocate Partial Payment by Oldest Balance First
Given a patient ledger with at least three unpaid procedures across different dates of service and providers and the allocation strategy is set to "Oldest balance first" When a partial payment of $150.00 with transaction ID T-123 is posted for location L1 Then allocations are applied in ascending date-of-service order until funds are exhausted And no line is allocated more than its remaining balance And the sum of allocations equals $150.00 within a $0.01 rounding tolerance And each allocation is tagged with the correct PMS ledger code, provider, and location And remaining balances are updated locally and synced to the PMS within 60 seconds And re-posting T-123 is ignored to prevent duplicate allocations
Overpayment Creates Unapplied Credit and PMS Sync
Given a patient has a total outstanding balance of $200.00 and no existing unapplied credits When a payment of $260.00 with transaction ID T-456 is posted Then $200.00 is allocated to open items and $60.00 is recorded as an unapplied credit And an unapplied credit record is created in the PMS and the PMS credit ID is stored And no procedure balance becomes negative And local and PMS balances reflect the unapplied credit within 60 seconds And the event is auditable with user, timestamp, and source captured And re-posting T-456 does not create duplicate credits or allocations
Procedure Priority Allocation Strategy
Given a configured allocation priority list of procedure categories exists and is active When a partial payment is posted Then allocations are applied in the order of the configured procedure category priorities And ties within a category are broken by oldest date of service, then by lowest procedure ID And the applied strategy name and version are recorded with the allocation event And changing the active strategy affects subsequent payments without service restart And results are consistent across retries and background replays
Provider Quota-Based Allocation Across Providers
Given provider quota allocation is enabled with quotas totaling 100% and there are open items for at least two providers When a payment of $100.00 is posted Then allocations are split by quota percentages across eligible provider items while respecting each item’s remaining balance And any unallocatable portion for a provider (no eligible items) is redistributed proportionally to remaining providers And rounding is to two decimals with any residual $0.01 assigned to the provider with the largest remaining allocatable balance And each allocation is synced to the PMS with the correct provider and ledger code mapping And the final allocated sum equals $100.00
Manual Override with Audit Trail and EOD Lock
Given a user with the Billing Manager role opens the payment allocation screen with auto-allocation previewed When the user manually adjusts allocations and clicks Save Then a reason note of 5–200 characters is required And the system validates totals, remaining balances, rounding rules, and PMS constraints before commit And an immutable audit record captures before/after allocations, user ID, timestamp, source, and approval (if required) And overrides after end-of-day reconciliation lock are blocked with an explanatory message And if the ledger changes concurrently, the save is rejected and the user is prompted to refresh
Rounding Rules and PMS Constraints Enforcement
Given the PMS supports two-decimal currency and a minimum line amount of $0.01 When allocations are computed for any payment Then all amounts are rounded using round-half-up to two decimals And no allocation line is created below $0.01 and no negative allocation lines are produced And any residual penny is assigned to the allocation line with the largest absolute pre-round amount And if the PMS returns a rounding adjustment, the local ledger is updated to match and the adjustment is logged
Bidirectional Sync and Reconciliation Parity
Given allocations (and credits, if any) are created locally for a posted payment When syncing to the PMS occurs Then the system creates or updates payment distributions and credits/adjustments in the PMS and stores returned PMS IDs And transient sync errors are retried up to 3 times with exponential backoff before surfacing an error And post-sync, local remaining balances match PMS balances for the affected items; discrepancies > $0.01 are flagged and queued for review And the payment and allocations are included in the end-of-day reconciliation export with totals by provider, ledger code, and location And the sync operation is idempotent using the original transaction ID to prevent duplicates
Bidirectional Refund/Void Sync
"As a practice owner, I want refunds and voids to sync both ways so that our books stay consistent regardless of where staff initiates the action."
Description

Enable real-time, two-way synchronization of refunds and voids between SmileCue and the PMS. When initiated in either system, propagate corresponding reversing entries with correct ledger codes, provider/location attribution, and links to the original transaction. Enforce permission checks, capture reasons, and maintain a complete reversal chain for auditability. Handle asynchronous timing and failure recovery to keep both systems consistent.

Acceptance Criteria
SmileCue-Initiated Refund Syncs to PMS
Given an authorized Billing Manager in SmileCue and a settled original payment with transactionId exists When the user initiates a full or partial refund in SmileCue and provides a non-empty reason, selecting provider and location Then within 15 seconds PMS records a corresponding refund that: - references the original via externalId/parentTransactionId - matches the original ledger code, provider, and location - reflects the exact refund amount and correct remaining balance - stores the refund reason and initiating user metadata - writes audit log entries in both systems with action=refund, timestamps, ids, actor, and reason
PMS-Initiated Refund Syncs to SmileCue
Given an authorized user in PMS and a settled original payment with externalId pointing to SmileCue exists When the user creates a full or partial refund in PMS with a required reason Then within 15 seconds SmileCue records a corresponding refund that: - references the original payment via parentTransactionId/originalTransactionId - preserves ledger code, provider, and location attribution from the original - reflects the exact refund amount and updates remaining balance - stores the refund reason and PMS user metadata - writes audit logs in both systems linking PMS refund id to SmileCue refund id
Bidirectional Void Before Settlement
Given an authorized user and an authorized-but-unsettled payment exists in either system When the user issues a void in SmileCue or PMS with a required reason Then the counterpart system marks the original payment as voided within 15 seconds and: - records a void entry linked to the original transaction - makes no additional ledger postings beyond the reversal - preserves original ledger code, provider, and location attribution - logs the reason and actor in audit trails in both systems And if the payment is already settled, the void request is rejected with 409 and guidance to issue a refund instead
Permission and Reason Enforcement
Given a user without refund/void permission attempts a refund or void in either system When the action is submitted Then the request is blocked with HTTP 403 (or platform-equivalent), no changes are persisted, and an audit log captures the denied attempt Given a user with permission omits a reason or provides fewer than 3 characters When the refund/void is submitted Then validation fails with HTTP 422 (or platform-equivalent) and no sync occurs
Reversal Chain Integrity with Partial Refunds
Given an original payment and multiple partial refunds initiated across SmileCue and PMS over time When the refunds are processed and synced Then both systems display an identical reversal chain where: - each reversal links to its parent/original transaction - the sum of refunded amounts never exceeds the original amount - remaining balance is accurate after each reversal - chain order is strictly chronological with monotonic timestamps - querying by any transactionId returns the same chain length and linkage in both systems
Idempotency and Failure Recovery
Given transient network issues or duplicate webhook deliveries during refund/void sync When the same reversal request is retried up to 5 times with exponential backoff Then only a single refund/void is created (idempotent by key composed of sourceSystem+originalTransactionId+reversalType+amount), and eventual consistency is achieved within 5 minutes And if retries exhaust, the event is recorded in a dead-letter queue, an alert is sent to ops, and an automatic replay job restores consistency with no duplicates
End-of-Day Reconciliation Covers Refunds and Voids
Given the end-of-day reconciliation job runs When exports are generated from SmileCue and PMS Then each refund and void appears with matching transaction ids, ledger codes, provider, location, amounts, reasons, and linkage to originals And ledger totals per code and per provider/location match across systems within $0.01 tolerance And any mismatches are reported with itemized differences and auto-remediated within the same run, resulting in zero outstanding mismatches
End-of-Day Reconciliation Exports
"As an accountant, I want daily reconciliation exports with stable IDs so that I can tie out deposits and ledger entries quickly without manual matching."
Description

Produce scheduled, tamper-evident end-of-day exports with both summary and transaction-level detail by location and provider. Support configurable cutoffs by time zone, export formats (CSV, XLSX, JSON), secure delivery (SFTP, secure email, or API), and inclusion of cross-system IDs for easy tie-out. Provide success/failure notifications and a re-run capability that preserves original transaction IDs for audit alignment.

Acceptance Criteria
Scheduled EOD Exports by Configurable Cutoff and Time Zone
Rule 1: For each configured location with an IANA time zone and cutoff time, exports run automatically at the cutoff and include transactions where posted_at >= prior_cutoff and < current_cutoff. Rule 2: Generate both a Summary file and a Transaction Detail file for each location and provider included in the window. Rule 3: Daylight Saving Time transitions are handled without duplication or omission of transactions. Rule 4: File names follow: smilecue_eod_<locationId>_<providerId>_<YYYYMMDD>_<TZ>_<runVersion>.<ext> and include the cutoff date per location time zone. Rule 5: The job produces a machine-readable execution log with job_id, window_start, window_end, location_id(s), provider_id(s), counts, and durations.
Multi-Format Export Generation (CSV, XLSX, JSON) with Cross-System IDs
Rule 1: Users can select one or more formats (CSV, XLSX, JSON) per schedule; all formats contain identical data. Rule 2: Transaction Detail fields (minimum): transaction_id (LineSync), external_transaction_id, pms_ledger_code, provider_id, location_id, transaction_type (payment|refund|void|adjustment), parent_transaction_id (for refunds/voids), amount, currency, posted_at (ISO 8601 with offset), method, cross_system_ids[]. Rule 3: Summary fields (minimum) per location and provider: count_transactions, gross_payments, refunds, voids, net_total, window_start, window_end, location_id, provider_id. Rule 4: CSV is UTF-8 with header row, comma delimiter, RFC4180 quoting; XLSX contains two sheets named "Summary" and "Transactions"; JSON provides two top-level arrays: summary[] and transactions[]. Rule 5: Numeric amounts are fixed to two decimal places; nulls are explicit; no PHI beyond IDs is emitted.
Secure Delivery via SFTP, Encrypted Email, and API
Rule 1: SFTP delivery uses SSH key authentication and host key pinning; files are uploaded to the configured path with permissions 640; up to 3 retries with exponential backoff are attempted upon transient failures. Rule 2: Secure email delivery uses SMTP TLS 1.2+ and sends AES-256 encrypted ZIP attachments with a configurable password delivered out-of-band; max attachment size is enforced and overflow triggers SFTP/API fallback when configured. Rule 3: API delivery provides a token-authenticated download endpoint with time-limited pre-signed URLs (expiry <= 24h); access after expiry returns 403. Rule 4: Delivery outcomes are recorded per channel with timestamps, targets, and success/failure codes; partial-channel failures mark the job as Failed.
Tamper-Evident Files and Signed Manifests
Rule 1: For every export file produced, a SHA-256 checksum is computed. Rule 2: A manifest file (manifest.json) lists each file name, byte size, SHA-256 hash, and job_id. Rule 3: The manifest is signed using the platform private key (PGP or HMAC); the associated public key/secret is documented for verification. Rule 4: Any post-delivery verification that recomputed checksums or signatures do not match causes the job status to be marked Failed and triggers alerting. Rule 5: Checksums and signatures are stored for >= 13 months for audit.
Completion Notifications with Delivery Outcomes
Rule 1: On completion, the system sends a notification (email and/or webhook) within 5 minutes containing job_id, status (Success|Failed|Partial), window_start, window_end, location_id(s), provider_id(s), counts, file names, and checksums. Rule 2: Failure notifications include error category, last error code/message per channel, and next retry (if any). Rule 3: Webhook notifications are signed (HMAC-SHA256) with a configurable secret and include a timestamp and signature header; replay protection with 5-minute tolerance is enforced. Rule 4: Notification recipients and channels are configurable per location; misconfiguration causes validation errors at schedule save time.
Re-run Exports Preserving Original Transaction IDs
Rule 1: Authorized users can re-run an export by specifying job_id or (location, provider, cutoff date); re-runs regenerate files from the original immutable snapshot for that window. Rule 2: Re-runs preserve all original transaction_id and external references; versioning increments runVersion in the file name without overwriting prior artifacts. Rule 3: Re-run outputs are content-identical except for runVersion and regeneration timestamps; downstream systems can idempotently process based on transaction_id. Rule 4: All re-runs are audit-logged with actor, timestamp, parameters, and reason; access restricted to Admin/Office Manager roles.
Reconciliation Totals Tie-Out and Edge Cases
Rule 1: For each location and provider, Summary net_total equals the sum over Transactions of signed amounts (payments positive, refunds/voids negative) with zero tolerance. Rule 2: If any tie-out check fails, the job is marked Failed and no files are delivered; errors identify the first failing group and metric. Rule 3: Zero-activity windows still produce a Summary (all zeros) and an empty Transactions file and are delivered successfully. Rule 4: Refunds and voids in Transactions include parent_transaction_id that references an existing transaction_id within the same or a prior window. Rule 5: Timezone boundaries and DST are validated by testing windows containing DST changes with no duplicated or missing transactions.
Provider & Location Attribution
"As a hygienist, I want payments attributed to the right provider and location so that production and compensation reports reflect the care actually delivered."
Description

Automatically attribute payments to the correct rendering/billing provider and practice location using appointment context, PMS provider mappings, and user-defined overrides. Handle multi-location practices, associate providers, and mid-procedure provider changes. Validate provider/location IDs against PMS directories and apply deterministic fallback rules when context is missing to avoid orphaned entries.

Acceptance Criteria
Auto-Attribution from Appointment Context
Given a payment event references appointment_id=A1 with provider_id=P1 and location_id=L1 When LineSync Ledger ingests the payment Then the stored payment record contains provider_id=P1 and location_id=L1 And the PMS post/export uses the PMS provider code mapped to (P1, L1) And attribution_status = "attributed" And 100% of such payments in test data persist non-null provider_id and location_id and post without manual intervention
User Override of Provider and Location
Given a user applies a per-payment override to provider_id=P2 and location_id=L2 before posting When the payment is posted Then provider_id=P2 and location_id=L2 are used for storage and PMS post, superseding appointment context And an audit entry records user_id, timestamp, previous values, new values, and reason And removing the override reverts attribution to computed values on the next post attempt Given a saved rule-based override matches the payment When the payment is ingested Then the rule is applied consistently and logged with rule_id
Multi-Location Provider Mapping Validation
Given provider P1 practices at locations L1 and L2 with distinct PMS provider codes C1 and C2 When a payment attributed to (P1, L2) is posted Then the PMS post uses provider code C2 And it does not use code C1 And if no PMS mapping exists for (P1, Lx), the payment is moved to attribution_exception with error_code = "MAPPING_MISSING" and is not posted
Mid-Procedure Provider Change Handling
Given appointment A1 has provider P1 at time t0 and is reassigned to provider P2 at time t1 And a payment is received at time tp When tp >= t1 Then attribution uses provider_id = P2 When tp < t1 Then attribution uses provider_id = P1 And an audit record captures the provider change and selection rationale And retries produce the same attributed provider_id for the same timestamps
Deterministic Fallback Rules on Missing Context
Given a payment lacks valid appointment context or provider/location values When attribution runs Then fallback order is applied: (1) billing_provider on payment payload; (2) practice default billing provider; (3) suspense provider/location configured as "Unassigned" And if location is missing, use payment_source default location; else practice default location if still missing And resulting provider_id and location_id are non-null And attribution_status = "fallback" with reason_code set to the rule that assigned values
PMS Directory Validation and Error Handling
Given provider_id and location_id have been attributed When validating against the PMS directories Then both IDs must exist and be active in PMS And if either is invalid or inactive, the payment is not posted and is placed in attribution_exception with error_code in ["PROVIDER_INVALID","LOCATION_INVALID","PROVIDER_INACTIVE","LOCATION_INACTIVE"] And after correcting IDs and revalidation, the payment posts successfully exactly once (no duplicates)
Refund and Void Attribution Consistency
Given a refund or void is initiated for original_payment_id = OP1 attributed to provider_id = P1 and location_id = L1 When the refund/void is posted Then it inherits provider_id = P1 and location_id = L1 for storage and PMS post And the PMS transaction references OP1's external_transaction_id where supported And if OP1 is not found, fallback rules are applied and attribution_status = "fallback" with reason_code = "ORIGINAL_NOT_FOUND"
Ledger Sync Audit, Alerts & Retry Queue
"As a revenue cycle manager, I want clear audit logs and automatic alerts with safe retries so that I can quickly resolve sync issues without risking data integrity."
Description

Create a comprehensive audit trail for every ledger event, capturing before/after states, mapping rules used, external IDs, actor, timestamp, and source system. Implement resilient retry queues with exponential backoff and dead-letter handling for PMS/API failures. Expose a monitoring dashboard with filters, error categories, and one-click replay, plus configurable alerts (email/Slack) for reconciliation-impacting failures. Apply data minimization and encryption-in-transit/at-rest aligned with HIPAA and PCI boundaries.

Acceptance Criteria
Capture Full Ledger Event Audit Record
Given a ledger event (payment, refund, void, adjustment) is processed When the system records the audit entry Then the entry contains: audit_id (UUIDv4), event_type, outcome (success|failure), timestamp_utc (ISO 8601), actor_type (system|user), actor_id (nullable), source_system, target_pms, external_transaction_id, request_id, correlation_id, provider_id, location_id, patient_id (hashed), ledger_code, amount, currency, before_state (JSON), after_state (JSON), mapping_rule_id, mapping_rule_version, error_code (nullable), error_message (nullable), checksum_sha256 And then audit entries are append-only; updates create a new entry linked by parent_audit_id; direct mutation attempts are blocked and logged And then each audit entry is time-ordered and queryable by external_transaction_id, request_id, outcome, error_code, provider_id, location_id, and date range
Exponential Backoff and Dead-Letter Retry Policy
Given a PMS/API call fails with a retryable error (HTTP 5xx, 429, network timeout) When the event is enqueued for retry Then exponential backoff with jitter is applied: delay = min(base*2^attempt + random(0, 0.2*base*2^attempt), maxDelay) with base=5s, maxDelay=30m, maxAttempts=7 And then non-retryable errors (400, 401 after refresh, 403, 404 terminal) are not retried and are sent to the dead-letter queue with reason=non_retryable And then idempotency is enforced via idempotency_key = hash(external_transaction_id + operation + amount + ledger_code); duplicate deliveries do not create duplicate PMS entries And then on exceeding maxAttempts, the message moves to DLQ with final_error_code and final_error_message captured in audit And then retry ordering is preserved per external_transaction_id to avoid out-of-order updates
Monitoring Dashboard Filtering and Error Categorization
Given a Billing Admin opens the ledger sync monitoring dashboard When they apply filters Then they can filter by date range, outcome (success|failure|pending), error category (auth, throttling, validation, mapping, network, pms_unavailable, unknown), operation (create|update|refund|void), provider, location, ledger_code, external_transaction_id, request_id And then the dashboard shows counts, success rate, retry backlog, DLQ size, and top error categories for the current filter And then results are paginated (25/50/100) and exportable to CSV for the applied filter And then the dashboard displays no PHI beyond hashed patient_id or initials
One-Click Replay with Idempotency
Given a failed event is visible in the dashboard or DLQ When a user with Replay permission clicks Replay and provides a reason note (≥10 chars) Then the event is re-enqueued with attempt=0, preserves idempotency_key, and creates a new audit entry linked via parent_audit_id And then if the cause persists, retries follow the standard backoff policy; on success, the latest audit entry reflects outcome=success and the UI status updates to Resolved without duplicate PMS postings And then bulk replay supports selection by filter with confirmation of estimated count and applies rate limiting to honor PMS QPS limits
Email/Slack Alerts for Reconciliation Failures
Given alerting is configured When reconciliation-impacting failures exceed a threshold Then an alert is sent within 5 minutes to configured channels (email, Slack) including environment, error category, failure count/rate, and a deep link to the filtered dashboard And then thresholds can be set by absolute count or failure rate over a rolling window (e.g., >20 or >5% in 15 minutes) per environment And then alerts are de-duplicated within a suppression window (default 30 minutes) and send a resolve notification when metrics drop below threshold And then channel configurations validate via test message; secrets are stored securely and never exposed in UI or logs
HIPAA/PCI Data Minimization and Encryption
Given audit, queues, and dashboards process event data When data is stored or transmitted Then only minimum necessary PHI/PCI data is processed: no full PAN or CVV stored; patient identifiers hashed; last4 only when required and tokenized And then all data in transit uses TLS 1.2+; data at rest is encrypted with AES-256; keys managed in KMS with rotation ≤90 days; access is least-privilege RBAC And then logs, audits, and alerts redact PHI/PCI and secrets; lower environments do not contain real PHI/PCI; audit retention is configurable (default 7 years) with secure purge And then security verification is performed with evidence recorded against HIPAA and PCI scope
Role-Based Access and Access Logging
Given roles (Billing Admin, Office Manager, Support) are assigned When users view, export, or replay from the monitoring dashboard Then permissions are enforced: view audit (Admin, Manager), export (Admin, Manager), replay (Admin), configure alerts (Admin) And then every view, export, and replay action is logged with actor_id, action, timestamp, target identifiers, and outcome; logs are tamper-evident and immutable And then unauthorized actions return 403 and are logged; cross-practice access is blocked And then support access requires explicit time-bound elevation with auto-revocation and full audit

CardVault Consent

Tokenize a card-on-file with explicit, scope-limited consent during checkout or via a separate secure link. Patients control how and when it’s used (deposits, co-pays, balances), with easy revoke and auto-expiry. Faster follow-up collections with PCI scope minimized.

Requirements

PCI-Compliant Card Tokenization & Vaulting
"As an office manager, I want patients’ cards tokenized through a PCI-compliant vault so that we can safely keep a card on file without storing sensitive card data ourselves."
Description

Implement card-on-file storage using a PCI DSS Level 1 tokenization provider. Collect card data only through provider-hosted fields/pages to avoid handling PAN within SmileCue, minimizing PCI scope. Store only tokens and non-sensitive metadata (brand, last 4, expiry, network reference) mapped to the patient profile and practice tenant, with strict multi-tenant isolation. Ensure TLS 1.2+ in transit and strong encryption at rest for all artifacts we persist. Support network tokenization and card updater services where available, without changing consent scope. Provide idempotent token creation, safe retries, and lifecycle management APIs. No PHI is transmitted to the payment provider; SmileCue stores only the minimal linkage needed to associate tokens to patients while keeping PHI and PCI data logically and physically segregated.

Acceptance Criteria
Provider-Hosted Card Entry Avoids PAN Exposure
Given a patient opens the SmileCue payment page, When the card entry form is displayed, Then card fields are rendered exclusively via the PCI provider’s hosted iFrame or hosted page on a provider-controlled domain. Given a patient submits card details, When the browser network requests are observed, Then no request to any SmileCue-controlled domain contains PAN, CVV, full expiry, or sensitive payment data. Given the client code runs, When DOM and console are inspected, Then SmileCue code does not read or serialize PAN/CVV (no event listeners or data bindings on provider inputs). Given server telemetry is enabled, When logs and traces are reviewed, Then no PAN/CVV appears and scrubbing rules redact card patterns. Given CSP is configured, When headers are checked, Then frame-src and connect-src only allow the provider origins for card entry and block posting card data to non-provider origins.
Token Storage with Minimal Metadata and Tenant Isolation
Given the provider returns a tokenization result, When SmileCue persists it, Then only token, brand, last4, expiry month/year, token type, provider/network reference, and timestamps are stored; CVV, full PAN, track data, and billing address are not stored. Given a token is created, When accessed via API using a different tenant than the owner, Then access is denied with 403 and no data leakage occurs. Given data at rest policies, When database encryption settings are inspected, Then token and metadata columns are encrypted with KMS-managed AES-256 and key access is audited. Given a patient profile exists, When the token is linked, Then linkage uses internal IDs only and no PHI is copied into payment schemas.
Idempotent Token Creation and Safe Retries
Given the client calls the create-token endpoint with a unique Idempotency-Key, When the same key is replayed within 24 hours, Then the identical token record and provider reference are returned with HTTP 200 and an idempotency-replay indicator. Given transient provider failures (HTTP 5xx/timeouts), When retries occur, Then exponential backoff with jitter is applied up to 3 attempts without creating duplicate tokens. Given a network partition after provider success, When SmileCue later receives a retry with the same key, Then deduplication prevents multiple stored tokens and the operation is audit logged.
Network Tokenization & Card Updater Without Consent Scope Change
Given a stored card is upgraded by the provider to a network token or refreshed by an account updater, When SmileCue receives update webhooks or poll results, Then the token mapping is updated in place without altering the patient’s consent scopes (deposit, co-pay, balance). Given consent scopes exist, When an updater event arrives for a token tied to expired consent, Then no charging capability is enabled until consent is renewed. Given a scheduled follow-up charge, When the underlying PAN changes via updater, Then the charge uses the updated token successfully without requiring user action and without widening consent scope.
Transport Security and Encryption At Rest
Given any HTTPS connection between client, SmileCue, and provider, When TLS is negotiated, Then TLS 1.2 or 1.3 with approved cipher suites is used and TLS 1.0/1.1 are rejected. Given SmileCue public endpoints, When response headers are inspected, Then HSTS is enabled with includeSubDomains and preload. Given stored artifacts (tokens, metadata, audit logs, backups), When at-rest encryption configuration is reviewed, Then data is encrypted using AES-256 or provider KMS equivalents and replicas inherit encryption.
PHI Exclusion to Payment Provider & Data Segregation
Given tokenization or charge-setup requests to the PCI provider, When request payloads are audited, Then they contain no PHI (e.g., patient name, DOB, treatment info) and only include payment data plus a non-PII internal reference. Given data stores are reviewed, When querying payment schemas, Then they contain no PHI columns and are physically/logically separated from PHI schemas with access controls preventing cross-tenant joins. Given observability/analytics exports, When events are sampled, Then no PHI or PCI secrets are included and data classification rules block export of sensitive fields.
Token Lifecycle: Revoke, Auto-Expiry, and Audit
Given a patient or admin revokes consent, When the token is marked revoked, Then all future charge attempts with that token are blocked with a 409/422 business error and no authorization request is sent to the network. Given a token reaches its configured auto-expiry date, When the date passes, Then the token status becomes expired and it is excluded from charge attempts and batch jobs. Given any lifecycle change (create, update, revoke, expire), When audit logs are queried, Then an immutable record exists with actor, timestamp, IP, tenant, token reference, and reason.
Explicit Scope-Limited Consent Capture
"As a patient, I want to grant explicit, limited consent for how my card can be used so that I stay in control of charges and understand exactly what I’m authorizing."
Description

Enable capture of granular, explicit consent that defines exactly how the card-on-file may be used: allowed categories (appointment deposit, co-pay, post-visit balance, missed-appointment fee, payment plan installments), per-transaction and cumulative caps, frequency limits, validity window, and practice-specific terms. Present clear disclosures and a consent summary with versioning, and record e-signature evidence (checkbox, typed name, timestamp, IP, device fingerprint, user agent, locale). Support capture during checkout or as a separate flow, with ADA-compliant UI and multilingual content (e.g., EN/ES). Store immutable consent records linked to the token and patient, including policy/version references for audit and dispute resolution.

Acceptance Criteria
Scope Selection, Caps, Frequency, and Validity
Given a patient begins CardVault Consent capture When the user selects one or more allowed categories (appointment deposit, co-pay, post-visit balance, missed-appointment fee, payment plan installments) Then the system requires at least one category to be selected before enabling Agree and Save And displays fields for per-transaction cap (currency), cumulative cap (currency), frequency limit (count per period), and validity window (start/end date) with input masks and validation When the user enters caps, frequency, and validity values Then values outside configured limits (e.g., negative, zero, or malformed dates) are rejected with specific field error messages And the consent summary updates in real time to mirror the exact selections and limits When the user attempts to save without accepting practice-specific terms Then the save is blocked and an accessible error identifies the missing terms acceptance When the user saves a valid consent Then the stored record contains categories, per-transaction cap, cumulative cap, frequency limit, validity window, practice terms version ID, and the rendered consent summary text matching the on-screen summary exactly
E-signature Evidence Capture and Integrity
Given the consent summary is displayed When the patient checks the consent checkbox, types their legal name, and submits Then the system captures and stores checkbox=true, typed_name, UTC timestamp (ISO 8601 with timezone), source IP, device fingerprint hash, user agent, and locale code And computes a cryptographic hash (SHA-256 or stronger) of the full consent payload plus evidence And returns a success screen with a human-readable reference ID When any required signature element is missing (checkbox, typed name) Then submission is blocked and field-level errors are announced and visible When a stored consent record is retrieved later Then its hash validates against the stored payload and evidence, proving the record is unaltered
Checkout Flow and Secure Link Capture
Given a patient is in checkout and no active consent exists When payment details are requested Then the CardVault Consent step appears before card tokenization and must be completed successfully to proceed Given the office sends a secure consent link via SMS or email When the patient opens the link Then the user is verified via a one-time code to the same channel before consent content is shown And the link auto-expires after the configured duration and shows an Expired Link screen with a Resend option when expired When the patient completes consent via the link Then the consent record is created and associated to the patient and intended card token, and the link can no longer be reused
ADA/WCAG 2.1 AA Accessible Consent UI
Given a keyboard-only user navigates the consent flow Then all interactive elements are reachable in a logical order with a visible focus indicator and no keyboard traps And modals trap focus and are dismissible via Escape Given a screen reader user navigates the consent flow Then all controls and error messages have programmatic names/roles/states announced correctly And errors are surfaced via an ARIA live region upon validation failures When the page is zoomed to 200% or viewed at 320 CSS pixels width Then content reflows without loss of information or functionality And text and control contrast ratios meet or exceed 4.5:1 And touch targets meet a minimum 44x44 px size
Multilingual Content and Terms Versioning (EN/ES)
Given the patient’s locale is Spanish or selects Español Then all consent UI text, disclosures, and summary are displayed in Spanish with legally equivalent meaning to English And the language toggle allows switching between English and Spanish without losing entered values And dates, numbers, and currency in the summary are formatted per the selected locale When consent is saved Then the record stores the language code, the full text snapshot of disclosures/summary in that language, and the terms policy/version identifiers with a version hash When practice terms are updated to a new version Then new consents reference the new version while existing records continue to reference their original version without modification
Immutable Consent Record and Audit Retrieval
Given a valid consent is submitted Then the system persists an immutable record linked to patient ID and card token, including categories, caps, frequency, validity window, terms version, evidence details, consent summary text, and a content hash And any change requires creating a superseding consent that references the prior record; the prior record remains read-only When an admin searches by patient, token, or consent reference ID Then the consent record is retrievable within 2 seconds for 95% of requests and includes a downloadable PDF and JSON export with all fields and hash When an audit verification is requested Then the system returns the payload and verifies the hash to confirm integrity
Consent-Based Charge Enforcement and Revocation
Given an active consent allowing categories {co-pay, post-visit balance} with a per-transaction cap of $200, a cumulative cap of $500, a limit of 3 charges per 30 days, and a validity window When the system attempts a charge outside allowed categories, exceeding caps, outside frequency limits, or outside the validity window Then the charge is blocked, a precise reason code is returned, and an event is logged referencing the consent ID When a compliant charge is processed Then the authorization succeeds and the event log updates the running cumulative total and charge count atomically When cumulative usage reaches 80% of the cap Then a notification is sent to the practice and the UI flags consent approaching limit When the patient revokes consent Then the consent status is set to Revoked with timestamp and no further charges are allowed under that consent
Patient Self-Service Secure Consent Link
"As a patient, I want a secure link to add my card and choose what it can be used for so that I can complete consent on my own time without calling the office."
Description

Allow practices to send a one-time, expiring secure link via SMS or email for patients to add a card and set consent permissions remotely. Protect the link with short-lived tokens, device binding, and optional OTP verification (SMS/email) or DOB verification. Use payment-provider hosted pages to input card details, then route back to a SmileCue consent review screen to select permitted uses, caps, and expiry before final e-sign. Provide clear success/failure states, error recovery, and accessibility support. Record delivery, open, and completion events to power reminders and follow-ups within SmileCue’s communication workflows.

Acceptance Criteria
One-Time Secure Consent Link Generation and Delivery Tracking
Given a staff user selects a patient and channel (SMS or email) in SmileCue When they generate and send a secure consent link Then the system creates a single-use link with an opaque token (≥128-bit entropy), HTTPS URL, and TTL default 24h (configurable 1–72h) And logs DeliveryQueued with timestamp, patientId, practiceId, channel, and messageId And upon provider callback or internal status, logs DeliverySucceeded or DeliveryFailed with reason And upon first patient access, logs LinkOpened with ip, userAgent, and deviceId hash And the link becomes invalid after successful ConsentSigned or upon expiry, whichever occurs first And the URL contains no PHI/PII and is shorter than 2048 characters
Link Access Security with Token TTL, Device Binding, and Verification
Given a patient opens the secure link within TTL When accessed for the first time Then the device is bound via a signed, HttpOnly, SameSite cookie to the linkId And subsequent access from a different device requires verification per practice setting (None, OTP_SMS, OTP_EMAIL, DOB) And token access is rate-limited to 30 requests/minute per IP Given OTP verification is enabled When the patient requests an OTP Then a 6-digit code is sent via the selected channel, valid for 10 minutes, max 3 sends per 15 minutes And verification fails after 5 incorrect attempts and locks for 15 minutes Given DOB verification is enabled When the patient enters DOB Then access is granted only on exact match with the patient’s record, with max 5 attempts then 15-minute lock When the token is accessed after TTL Then show Expired screen and log LinkExpired; no consent actions are available
Hosted Card Entry and Tokenization Flow
Given the patient has passed link verification When they choose Add Card Then they are redirected to the payment-provider hosted page over HTTPS in the same browser session with CSRF-protected state When valid card details are submitted Then SmileCue receives only a tokenized card identifier, last4, brand, and expiry from the provider, and stores no PAN or CVV And logs CardTokenizationSucceeded with provider reference (no PAN/CVV) When the provider returns an error or the patient cancels Then show a recoverable error with Retry (up to 3 attempts) and Cancel options And no token is stored on failure And all redirects back to SmileCue validate state, origin, and signature before proceeding
Consent Configuration for Permitted Uses, Caps, and Expiry
Given a tokenized card is available When the consent screen loads Then the patient can select permitted uses (Deposits, Co-pays, Balances) and must select at least one to continue And may set a per-transaction cap in USD between 1 and 5000 inclusive and an optional monthly cap between 1 and 10000 inclusive And must set an expiry between 7 and 365 days from e-sign (default 365 days) And a human-readable summary updates in real time reflecting selections, caps, and expiry And inline validation prevents continuation until all fields are valid And the screen meets WCAG 2.1 AA with zero critical axe-core violations; all controls are keyboard accessible, properly labeled, and errors are announced to screen readers And partial progress is preserved on refresh or back navigation within the session
E-Sign Capture and Immutable Consent Record
Given consent selections are valid When the patient affirms consent via required checkbox and provides a typed name or drawn signature Then the system records an immutable consent artifact including patientId, practiceId, card tokenId, permittedUses, caps, expiry, timestamp (UTC), ip, deviceId hash, consent text version hash, and staff initiator (if any) And creates a ConsentSigned event And shows a Success screen with a reference number And sends a confirmation via the original channel containing a consent summary (brand and last4 only; no PAN/CVV) And the consent status becomes Active and visible in the practice portal
Consent Revocation and Auto-Expiry Enforcement
Given an Active consent exists When the patient revokes via self-service link or staff revokes in the portal Then the consent status changes to Revoked within 5 seconds and logs ConsentRevoked with actor and reason And all subsequent payment attempts using the token are blocked with error code CONSENT_INACTIVE before contacting the payment provider When the consent reaches its expiry date Then a scheduled process marks it Expired by 02:00 local time and blocks further use And notifications are sent to the practice (inbox and optional email) and to the patient via their original channel if opted in And all revocations and expiries are audit-logged immutably
Event Tracking and Reminder Automation
Given a secure consent link has been sent When events occur (DeliveryQueued, DeliverySucceeded/Failed, LinkOpened, VerificationPassed/Failed, CardTokenizationSucceeded/Failed, ConsentViewed, ConsentConfigured, ESignStarted, ConsentSigned, ConsentRevoked, ConsentExpired) Then each event is captured with timestamp (UTC), patientId, practiceId, linkId, channel (if applicable), deviceId hash, and actor type Given ConsentSigned has not occurred and the link has not expired When 24 hours elapse since DeliverySucceeded Then send one reminder via the alternate available channel (if any) respecting quiet hours 20:00–08:00 local time And send no more than 2 total reminders per link And cease all reminders immediately upon ConsentSigned, Revoked, Expired, or patient opt-out, logging ReminderSuppressed with reason And the workflow UI displays current state and next reminder schedule
Real-Time Consent Enforcement & Charge Guardrails
"As a billing specialist, I want the system to automatically block any out-of-scope charge and tell me why so that we only run charges patients have approved."
Description

Introduce a centralized decisioning service that validates every attempted card-on-file charge against the patient’s active consent: category match, amount within caps, frequency limits, and consent validity window. Expose a synchronous API and SDK for SmileCue automations and staff-initiated charges to request authorization with idempotency and receive an allow/deny decision plus reason codes. Block out-of-scope charges and surface actionable messages to staff, with options to request updated consent via a one-click link. Tag charges with categories from the practice management/billing context to ensure accurate enforcement without exposing PHI to the payment provider.

Acceptance Criteria
Category Scope Enforcement
Given a patient has an active consent that includes categories ["deposit", "co-pay"] and excludes "balance" When SmileCue requests authorization to charge amount_cents=3000 USD tagged as category="balance" Then decision="DENY" and reason_code="CATEGORY_OUT_OF_SCOPE" are returned with http_status=200 And no authorization is attempted with the payment provider And the response includes consent_id, category="balance", amount_cents=3000, and correlation_id Given the request is tagged category="co-pay" which is present in the active consent and amount/frequency/validity constraints are satisfied When SmileCue requests authorization for amount_cents=3000 USD Then decision="ALLOW" is returned with remaining_limits reflected
Per-Transaction Amount Cap
Given an active consent defines per_transaction_cap_cents=7500 for category="co-pay" When an authorization request is made for category="co-pay" with amount_cents=7501 Then decision="DENY" and reason_code="AMOUNT_EXCEEDS_CAP" are returned and denied_amount_cents=7501 is echoed And no authorization is attempted with the payment provider Given an authorization request for amount_cents<=7500 When the request is evaluated Then decision="ALLOW" is returned and response.remaining_limits.per_transaction_cap_cents=7500 And response includes consent_id and correlation_id
Frequency Limits per Rolling Window
Given an active consent defines for category="balance": max_charges=2 per rolling_window_days=7 And two prior ALLOW decisions for category="balance" exist within the last 7 days When a third authorization request for category="balance" arrives within the same 7-day window Then decision="DENY" and reason_code="FREQUENCY_LIMIT_EXCEEDED" are returned with next_allowed_at set to the earliest timestamp when a new charge becomes permissible Given only one prior ALLOW exists in the rolling window When a second authorization request arrives within the 7-day window and all other constraints are satisfied Then decision="ALLOW" is returned and response.remaining_limits.frequency.remaining=0
Consent Validity & Revocation
Given a consent has start_at and end_at timestamps When an authorization request arrives before start_at Then decision="DENY" and reason_code="CONSENT_NOT_YET_ACTIVE" are returned Given the current time is after end_at When an authorization request arrives Then decision="DENY" and reason_code="CONSENT_EXPIRED" are returned Given a consent has been explicitly revoked at revoked_at When any authorization request arrives after revoked_at Then decision="DENY" and reason_code="CONSENT_REVOKED" are returned Given current time is within [start_at, end_at] and consent is not revoked and other constraints are satisfied When an authorization request arrives Then decision="ALLOW" is returned
Synchronous API, Reason Codes, and Idempotency
Given the client calls POST /v1/consent/authorize with an idempotency_key=K and payload=P When the same request (same K and same P) is retried within 24 hours Then the response is identical (decision, reason_code, body hash) and no counters or side effects are duplicated Given a request is made with idempotency_key=K and payload=P1, and later a request arrives with the same K but payload=P2 (P2 != P1) When the second request is processed Then http_status=409 is returned with error_code="IDEMPOTENCY_PAYLOAD_MISMATCH" and no decision is recorded Given any valid request is processed When the service responds Then the response includes fields: decision in {"ALLOW","DENY"}, reason_code from the documented enum, consent_id, evaluated_rules[], remaining_limits, correlation_id, and processed_at And p95 end-to-end latency for allow/deny decisions is <= 800ms under expected load And official SDKs expose authorizeCharge(...) with typed Decision/ReasonCode enums and idempotent retry helpers
Staff Denial Messaging & One-Click Consent Update
Given a staff-initiated charge is denied with reason_code in {"CATEGORY_OUT_OF_SCOPE","AMOUNT_EXCEEDS_CAP","FREQUENCY_LIMIT_EXCEEDED","CONSENT_EXPIRED","CONSENT_NOT_YET_ACTIVE","CONSENT_REVOKED"} When the SmileCue UI receives the decision response Then a human-readable message is displayed summarizing the denial reason and category/amount And an actionable control "Send consent update" is shown When the user clicks "Send consent update" Then a secure, single-use consent update link is sent via the patient’s preferred channel (SMS/email) and logged with correlation_id And the link expires in <= 7 days or upon completion When the patient completes the consent update Then a webhook marks the new consent active and the UI can retry the charge from the same decision panel
Category Tagging & PHI Minimization
Given SmileCue integrates with the practice management system’s billing context When an authorization request is created Then a required category_code (from a maintained mapping table) is included and validated And if the category_code is unknown or missing, decision="DENY" with reason_code="CATEGORY_UNKNOWN" is returned Given the authorization request is processed Then only non-PHI fields are transmitted to the payment provider (payment_method_token, amount, currency), and category_code/PHI are not sent downstream And raw PAN or un-tokenized card data never passes through the decision service or SmileCue APIs And request/response logs contain no PHI and only last4 + brand for payment method where needed for UX
Easy Revocation & Auto-Expiry Controls
"As a patient, I want to revoke my consent at any time and know it will expire automatically after a set period so that I remain in control without needing to call the office."
Description

Provide simple patient- and staff-initiated revocation mechanisms that take effect immediately across all workflows. Support partial revocation (by category) and global revoke, with optional reasons. Implement configurable auto-expiry for consents (e.g., 6 months), with pre-expiry reminders and easy renewal links. Upon revoke/expiry, disable scheduled or automated charges and notify relevant staff. Maintain a complete history of state changes while ensuring the token itself can remain for future re-consent without re-entering PAN, subject to provider capabilities and policy.

Acceptance Criteria
Patient-Initiated Global Revoke via Self-Service Link
Given a patient has an active payment consent token and a secure self-service link When the patient opens the link, completes 2FA, selects "Revoke all uses," and optionally provides a reason Then the consent scope is changed to revoked:global within 5 seconds and a confirmation receipt is shown And an event "consent.revoked" is emitted with patient_id, token_id, scope=global, actor=patient, reason (nullable), and trace_id And UI badges across patient portal and staff console update to "Consent Revoked" on next view within 5 seconds And relevant staff notification is sent to the Billing queue within 1 minute including actor, reason, and affected workflows
Staff-Initiated Category Revocation in Admin Portal
Given categories {deposits, co-pays, balances} are available for consent scoping When a user with role Billing or Admin opens the patient record and toggles off one or more categories and saves with an optional reason Then only the selected categories transition to revoked:partial immediately and remaining categories stay active And the patient’s record displays which categories are revoked with timestamp and actor=staff And attempts to charge a revoked category are blocked before gateway call with error code CONSENT_REVOKED and a visible explanation And the patient is notified of category changes via their preferred channel within 15 minutes
Immediate Propagation of Revocation Across All Payment Workflows
Given a consent was revoked (global or category) at time T When any manual charge, scheduled charge, or automated retry is evaluated at or after time T Then the system checks the latest consent state and blocks disallowed charges without sending a gateway authorization And the maximum time from revoke to enforcement across services is <= 5 seconds And affected attempts are logged as "Skipped - Consent Revoked" with references to the causative revoke event
Auto-Expiry Enforcement with Configurable Duration
Given tenant-level Consent Auto-Expiry is configurable between 30 and 365 days with a default of 6 months When a consent reaches its configured expiry timestamp Then the consent transitions to expired automatically with actor=system and reason=timeout And the token remains vaulted but marked inactive and unavailable for charging And any attempted charge after expiry is blocked with error code CONSENT_EXPIRED and an audit entry is recorded And relevant staff are notified within 1 minute of the expiry event
Pre-Expiry Reminders with One-Click Renewal
Given a consent is due to expire in 14 days When the reminder scheduler runs Then the patient is sent pre-expiry reminders at T-14 days and T-3 days via their preferred channel containing a unique renewal link When the patient opens the link, completes 2FA, and confirms renewal Then the same vaulted token is re-authorized without re-entering PAN (subject to provider capability), a new expiry is set per tenant config, and a confirmation receipt is shown And if reuse is not supported by the provider, the patient is prompted to securely re-enter card details and the old token is superseded by the new token with an audit link between them
Disable Scheduled and Automated Charges on Revoke/Expiry
Given the patient has scheduled charges or automated retries within the next 30 days When the consent is revoked or expires Then those items are canceled or paused within 10 seconds without attempting network authorization And each item is marked "Skipped - Consent Revoked/Expired" with reason and linked to the revoke/expiry event And staff dashboards display a count and list of skipped items for follow-up
Audit Trail of Consent State Changes and Reasons
Given any consent state change (created, activated, partially revoked, globally revoked, expired, renewed) When a user views the consent audit log in UI or via API Then each entry shows timestamp (UTC), actor (patient|staff|system), actor_id, action, scope (categories), reason (nullable), channel, ip, and trace_id And entries are immutable, ordered, filterable by date/action, and exportable to CSV And the API returns a paginated list of 100 entries within 2 seconds for typical load And audit records are retained per tenant retention policy with the configured retention period displayed
Audit Logging, Evidence Packs & Dispute Reporting
"As a compliance officer, I want complete, exportable evidence of consent and charge decisions so that we can resolve disputes and pass audits with confidence."
Description

Capture an immutable audit trail for consent lifecycle events (create, update, revoke, expire), token lifecycle events, enforcement decisions, and executed charges. Each record includes actor (patient/staff/system), timestamp, IP, device/user agent, request IDs, and consent/version references. Provide exportable, court-ready evidence packs (PDF/JSON) that bundle disclosures, signed terms, event logs, and decision outcomes for chargebacks or compliance reviews. Offer search and filtered reporting for practices, with retention policies aligned to regulatory and contractual requirements. Ensure logs exclude PAN/PHI while preserving necessary context to establish provenance.

Acceptance Criteria
Immutable Audit Trail for Consent Lifecycle Events
Given any consent event (create, update, revoke, expire), when it is committed, then an append-only audit record is written with: event_type, consent_id, consent_version, actor_type, actor_id (nullable for system), occurred_at (UTC ISO 8601), ip_address, user_agent, request_id, practice_id, patient_id, correlation_id. Given a stored audit record, when any modification or deletion is attempted, then the system rejects the operation and logs a tamper_attempt event with actor, occurred_at, and request_id, and the original record remains unchanged. Given the daily integrity verification job, when it runs, then it validates the hash chain/signature of the last 90 days and logs integrity_pass if all verify or integrity_fail with failing_record_id and reason if any verification fails. Given a query by consent_id, when up to 200 lifecycle events exist, then the API returns all events in chronological order within 500 ms p95.
Token Lifecycle and Enforcement Decision Logging
Given a tokenization, refresh, or deletion event, when processed, then a token_event is stored with token_ref, token_provider, event_type, occurred_at, actor_type, request_id, and consent_id/consent_version linkage. Given a payment attempt, when the policy engine evaluates consent scope (use_type, amount_limit, time_window, channel), then a decision record is stored with decision (allow/deny), evaluator_version, policy_id(s), rationale, payment_attempt_id, and consent link. Given a denied payment due to consent scope, when logged, then the decision includes violated_rule_id and a human-readable reason. Given a correlation_id for a payment, when records are fetched, then token_event, decision, and any subsequent charge events are traversable via foreign keys.
Executed Charges Log with Consent Scope Validation
Given a successful or failed charge, when recorded, then the charge_log includes payment_attempt_id, processor_txn_id, amount_minor, currency, outcome, occurred_at (UTC), consent_id/consent_version, decision_id, and contains no PAN digits, no CVV, and no PHI fields. Given a charge exceeding consent amount_limit, when attempted, then the system blocks the charge, records a failed charge_log with reason=exceeds_consent_limit, and no funds are captured. Given a partial capture within consent scope, when processed, then the charge_log reflects the captured amount and links to the parent authorization_id and consent_id. Given 1,000 charge_log records queried by practice_id within a 30-day range, when requested, then the API responds within 1 second p95.
Evidence Pack Export for Chargeback/Compliance
Given a consent_id and payment_attempt_id, when an authorized staff requests an evidence pack, then the system generates a ZIP containing evidence.json (schema v1), evidence.pdf (court-ready), disclosures.pdf, signed_terms.pdf or snapshot.html, and event_logs.csv. Given the generated pack, when validated, then evidence.json includes case_id, practice_id, patient_id_pseudonym, consent_id/version, decision_id, event_timeline, policy_versions, processor_receipts, and SHA-256 hashes of each included file. Given the PDF, when opened, then it displays a timeline with generated_at (UTC) and a digital signature; total pack size <= 25 MB; generation completes within 60 seconds p95. Given an evidence export, when completed, then a secure expiring URL (TTL 72 hours) is issued, RBAC restricts access to permitted roles, and the export action is recorded with requester, purpose, and request_id.
Search and Filtered Reporting for Practices
Given a practice user with Reports role, when searching logs, then they can filter by date range, event_type, actor_type, decision (allow/deny), consent_id, token_ref, processor_txn_id, and patient (by internal id or phone/email hash), and export results as CSV without PAN/PHI. Given a dataset with >=100k events in 90 days, when paginating with limit=100, then the API returns occurred_at desc with cursor-based pagination and p95 latency <= 2 seconds per page. Given a multi-tenant environment, when a user queries, then only records for their practice_id are returned; cross-tenant access is denied and logged. Given a CSV export request, when executed, then the export includes headers, UTC timestamps, a footer with record count and generation hash; request and completion are logged.
Retention Policy Enforcement and Legal Hold
Given default retention policies, when configured, then consent and charge logs are retained for 7 years and token events for 2 years unless superseded by contract; policies are visible in admin UI and included in evidence.json. Given the nightly purge job, when records exceed retention and are not on legal hold, then they are irreversibly purged and a purge_summary record is written with counts by type, date range, and job_run_id; hash chain anchors remain for verification. Given a legal hold on consent_id or case_id, when set, then affected records are exempt from purge until hold release; hold actions are audited with reason and approver. Given a purge dry-run, when executed, then the system reports the count of records eligible for deletion without deleting any and provides a downloadable CSV report.
Sensitive Data Exclusion and Redaction Controls
Given any logging API call, when payload contains PAN digits, CVV, magnetic track, SSN, diagnosis codes, or free-text PHI patterns, then the system rejects the write, redacts offending fields in memory, and logs a pii_blocked event with field names and request_id; no sensitive content is persisted. Given a stored record, when viewed or exported, then fields are restricted to an allowlist; PAN is never present in any form (including last4), CVV is never stored, and clinical data are excluded; automated nightly scans confirm 0 violations. Given role-based access, when a non-compliance-role user exports reports, then patient identifiers are pseudonymized (rotating-salt hash) and IPs are truncated (/24 IPv4, /48 IPv6); compliance role sees full IPs. Given unit and integration tests, when the suite runs, then 100% of logging code paths that handle sensitive fields assert redaction/rejection behavior.
Staff Console & Workflow Integration
"As an office manager, I want an easy console to request, review, and manage card-on-file consent so that our team can reduce manual collections while staying compliant."
Description

Add a CardVault section in the SmileCue admin where staff can request consent, view current token status, permitted uses, caps, and expiry, trigger secure links, revoke or renew consent, and see enforcement decisions with explanations. Provide role-based access controls, activity feeds, and alerts when automations are blocked due to missing or expired consent. Integrate with existing SmileCue appointment and billing communications so staff can include consent requests in reminders, post-visit follow-ups, and balance collection campaigns using templates and merge fields. Ensure the UI surfaces only minimal payment metadata (brand, last 4, expiry) and never exposes sensitive card data.

Acceptance Criteria
Staff Console: CardVault Section Availability and Navigation
Given a staff user with CardVault_View permission When they open the SmileCue admin console Then the CardVault section is visible in the primary navigation and accessible via a unique URL route And the CardVault dashboard loads within 2 seconds on a standard broadband connection And an empty state is shown if no patient consents exist, with a call-to-action to Request Consent
Consent Request: Generate and Send Secure Link
Given a staff user with CardVault_Request permission and a patient record with at least one verified contact method When the user selects Request Consent, chooses permitted uses (e.g., deposit, co-pay, balance), sets caps (amount and frequency), and defines an expiry date Then the system generates a single-use, time-bound secure link with a minimum 30-minute and maximum 14-day validity window And the link can be sent via SMS and/or email using selectable templates And the request event is recorded with user, timestamp, channel(s), scopes, caps, and expiry And the link is invalidated immediately upon successful consent or manual revocation
Token Details: Status, Permitted Uses, Caps, and Expiry Display
Given a patient with an existing CardVault token and active consent When a staff user with CardVault_View opens the patient’s CardVault panel Then the UI displays token status (Active, Expired, Revoked, Pending), permitted uses, amount/frequency caps, consent expiry date, and last consent update timestamp And only minimal payment metadata is shown (brand, last 4, card expiry) And full PAN, CVV, and billing address are never displayed or retrievable And a clear indicator shows time remaining until consent expiry
Consent Lifecycle: Revoke and Renew with Audit Logging
Given a staff user with CardVault_Manage permission and a patient with active consent When the user clicks Revoke Consent and confirms Then the token becomes non-usable for any automation or manual charges And an audit log records user, timestamp, reason, and affected scopes When the user initiates Renew Consent Then the system requires specifying scopes, caps, and expiry and sends a new secure consent link to the patient And consent status remains Pending until the patient re-consents, after which status is Active and audit log is updated
Automation Enforcement and Alerts: Decisions and Block Notifications
Given an upcoming automation (e.g., balance collection SMS) requiring a valid CardVault consent When consent is missing, expired, or revoked at execution time Then the automation step is blocked and no payment action is attempted And the UI surfaces an enforcement decision with a human-readable explanation and the specific failing rule And an alert is created and routed to the assigned location/team inbox with a quick action to Request Consent And the block event is added to the activity feed for the patient and campaign
Role-Based Access: Fine-Grained Permissions for CardVault Actions
Given role definitions that include CardVault_View, CardVault_Request, and CardVault_Manage permissions When a user without CardVault_View attempts to access the CardVault section Then access is denied and the attempt is logged When a user with View but without Request/Manage attempts to send, revoke, or renew consent Then the action controls are disabled and a permissions tooltip is shown And administrators can assign permissions per role and location, with changes taking effect within 1 minute
Communication Integration: Templates and Merge Fields Include Consent Requests
Given existing appointment reminders, post-visit follow-ups, and balance collection campaigns When a staff user edits a template Then merge fields for ConsentRequestLink and ConsentStatus are available and render correctly in preview And sending a message with ConsentRequestLink inserts the active secure link or generates a new one if none is active And campaign analytics attribute consent conversions back to the originating template and campaign

Chairside QR

Generate a one-time QR from the appointment view to hand off payment to the patient’s device or a clinic tablet. The session is device-bound and time-boxed for security, perfect for walk-ins and less tech-savvy patients. Payments complete in seconds, no terminal needed.

Requirements

Appointment-Linked One-Time QR Generation
"As a dental assistant, I want to generate a one-time QR from the appointment screen so that I can hand off payment to the patient’s device or a clinic tablet without using a card terminal."
Description

Enable staff to generate a single-use, time-limited QR code directly from the appointment view that launches a payment session tied to the selected appointment. The QR encodes a short-lived token (not PHI) that resolves to a secure payment URL. Display a visible countdown timer and controls to cancel/regenerate. Ensure high-contrast rendering for print/display, compatibility with common QR scanner apps, and immediate invalidation upon successful payment or cancellation. Regeneration should revoke prior tokens and update the UI so staff can hand off payment within seconds without a terminal.

Acceptance Criteria
Generate One-Time QR from Appointment View
Given a staff user is viewing an appointment with an outstanding balance and payment permissions When the user clicks "Generate QR" Then a single-use token with a TTL of 5 minutes is created server-side and associated to the appointment And the token/QR payload contains no PHI (e.g., no patient name, DOB, phone, email, procedure, or balance amount) And the QR renders in the appointment panel within 2 seconds at p95 And a visible countdown displays starting at 05:00 with tick accuracy within ±1 second per minute And "Cancel" and "Regenerate" controls are visible and enabled
Time-Boxed Session and Expiry Handling
Given a QR is displayed with an active countdown When the countdown reaches 00:00 without the session being claimed Then the token is immediately expired and cannot be used to start payment And scanning the QR or opening its URL returns an "Expired" page and an HTTP 410/401 within 1 second of expiry And the appointment view updates within 1 second to show "Expired" and enables "Regenerate"
Immediate Invalidation on Payment or Cancellation
Given a QR token is active and the payment page is open When the payment is successfully completed Then the token is invalidated within 1 second and any further opens show "Already paid" with HTTP 410/403 And the appointment view updates within 2 seconds to show "Paid", hides the QR, and disables "Regenerate" and "Cancel" Given a QR token is active When a staff user clicks "Cancel" Then the token is invalidated within 1 second and any open payment page shows "Cancelled" And the appointment view shows "Cancelled" and offers "Generate QR" again
Regeneration Revokes Prior Tokens
Given a QR token is active When the staff user clicks "Regenerate" Then a new token is issued and displayed as a new QR within 2 seconds at p95 And the prior token is revoked within 1 second; any scans of the old QR show "Superseded" with HTTP 410/403 And the countdown resets to 05:00 for the new token
Device-Bound Session Enforcement
Given a QR token URL is first opened on Device A When Device B opens the same URL before completion Then Device B sees a "Session in use" page with no PHI and cannot proceed to payment And Device A can complete payment normally Given Device A is inactive on the payment page for 5 minutes When any device opens the token URL thereafter Then the session is expired and further opens show "Expired" until staff regenerates a new QR
High-Contrast QR Rendering for Display and Print
Given the QR is displayed in the appointment view Then the QR includes a quiet zone of at least 4 modules and error correction level M or higher And the luminance contrast ratio between modules and background is at least 7:1 in both light and dark themes And the on-screen size is at least 200x200 px, and exported/printed assets render at ≥300 DPI with a minimum size of 38 mm When tested on common screens and printed on standard office printers Then the QR is scannable with ≥99% success over 100 scans across varied lighting conditions
Compatibility with Common QR Scanners
Given the QR is displayed When scanned using iOS Camera app (iOS 15+), Android default Camera app (Android 11+), and Google Lens (current) Then each opens the HTTPS payment URL without security warnings and begins the session within 2 seconds at p95 network/device And the QR content resolves to a URL that contains only an opaque token (no PHI, no patient identifiers, no appointment details)
Device-Bound, Time-Boxed Payment Session
"As a practice owner, I want each QR payment session to lock to a single device and expire quickly so that payments are secure and cannot be replayed or intercepted."
Description

Bind the payment session to the first device that scans the QR using a server-side association and secure session cookie, enforcing a configurable expiration window (e.g., 5–10 minutes). Prevent replay by invalidating tokens after first bind, applying anti-reuse checks, rate limiting, and signed short-lived tokens (e.g., JWT) with no PHI in URL parameters. Auto-expire and purge state upon completion, timeout, or staff cancellation. Provide staff-side indicators of active/expired status and kiosk safeguards (auto-timeout, data purge) when using clinic tablets.

Acceptance Criteria
Bind Session to First Scanning Device
Given a chairside QR is generated for an appointment and no session is bound When Device A scans the QR and opens the link Then the server binds the session to Device A and issues a secure, HttpOnly, Secure, SameSite=Strict cookie for that session And the QR token is marked as bound and cannot be used to start a new session And the server records the device-bound association with timestamp Given the session is bound to Device A When Device B scans the same QR within the active window Then Device B receives an error indicating the session is already in use on another device (HTTP 409) without revealing patient identity, appointment details, or amount And no session is created for Device B Given the session is bound to Device A When Device A refreshes or reconnects within the active window Then the session continues without requiring a new QR and without rebinding
Time-Boxed Expiration Window Enforced
Given a clinic-level configuration for session expiration between 5 and 10 minutes exists (default 7 minutes) When a chairside QR session is created Then the session inherits the configured expiration and a countdown timer is started server-side Given the configured expiration is reached and payment is not completed When the bound device attempts any action Then the server returns HTTP 410 (Expired) and shows an expiration message without PHI And the session state is set to Expired and cannot be resumed Given a session expires When staff view the appointment Then the status indicator updates to Expired within 2 seconds and the QR is invalidated Given a session is completed before expiration When expiration time elapses Then the session remains Completed and cannot be re-entered
Token Security and Anti-Replay Controls
Given a chairside QR link is generated Then the URL contains only an opaque, signed, short-lived token (e.g., JWT/PASETO) with exp ≤ 10 minutes and jti And no PHI appears in the path or query parameters Given the token has not yet been bound When the first device binds the session Then the server invalidates further use of that token by storing jti as consumed and requires the bound device cookie for all subsequent requests Given multiple scans of the same token occur pre-bind When scan rate exceeds thresholds Then the system enforces rate limiting (e.g., ≥ 429 after 5 scans per minute per IP and 10 per minute globally per token) and logs the event without leaking PHI Given any request uses an invalid signature, expired token, reused jti, or missing bound cookie post-bind When the request is processed Then the server denies with 401/403 and returns a generic error without patient identifiers or appointment details
Session Completion and Data Purge
Given a bound session completes payment successfully When the payment provider confirms success Then the server marks the session Completed, invalidates the bound cookie and QR, and purges transient session state within 2 seconds And the patient device clears session/local storage and cookies for the flow And the browser back button leads to a non-recoverable "Session ended" page with no PHI Given a bound session times out or fails When timeout or failure is detected Then the server marks the session Expired/Failed, invalidates the QR and bound cookie, and purges transient session state within 2 seconds Given any terminal state (Completed/Expired/Cancelled) When staff view the appointment Then the UI reflects the terminal state and removes the active session indicator within 2 seconds And only audit-log metadata remains server-side (no patient financial data in ephemeral session storage)
Staff-Initiated Cancellation
Given an active bound session exists When staff clicks Cancel from the appointment view Then the server immediately sets the session to Cancelled, invalidates the QR and bound cookie, and purges transient state And the patient device receives a cancellation message on the next request or via push within 2 seconds and cannot proceed to payment And the staff UI updates to Cancelled within 2 seconds and logs the staff user and timestamp Given a session is Cancelled When any device attempts to access the link Then the server returns HTTP 410 (Cancelled) with no PHI and does not allow reactivation
Clinic Tablet (Kiosk) Safeguards
Given clinic tablet mode is enabled and a session is active on a clinic-owned device When there is 60 seconds of user inactivity Then the session auto-times out, returns to the start screen, and clears cookies, session/local storage, and in-memory state And the server marks the session Expired and invalidates the QR Given a session ends on the clinic tablet for any reason (Completed/Expired/Cancelled) When the user attempts back navigation or revisits the link Then the app displays a non-recoverable end-state screen and prevents access to prior patient data Given any network response in kiosk mode When HTTP headers are sent Then Cache-Control: no-store, Pragma: no-cache are set and no PHI is written to localStorage/IndexedDB/console logs
Staff-Side Real-Time Status Indicators
Given staff are viewing the appointment with Chairside QR When a session is created Then the UI shows Not started → Active (Bound) with a visible countdown matching the server-side expiration Given the session state changes (Active, In Progress, Completed, Expired, Cancelled) When the change occurs server-side Then all open staff workstations reflect the new state within 2 seconds via realtime updates or ≤5s polling fallback Given a new QR is generated for the same appointment When generation occurs Then any previous active session is immediately invalidated and the UI replaces the old code and countdown with the new session details
Patient-Friendly Payment UI
"As a patient, I want a simple, secure payment screen on my phone or the clinic tablet so that I can pay quickly without dealing with a card terminal."
Description

Deliver a fast, accessible, mobile-first checkout that summarizes the visit and amount due with minimal PHI (e.g., initials, appointment time), supports cards, HSA/FSA cards, and Apple Pay/Google Pay, and completes in one or two screens. Meet WCAG 2.1 AA with large tap targets, plain-language prompts, and error recovery. Provide EN/ES localization initially, optional tips/gratuity (configurable), and clear success/failed states. Offer receipt delivery via SMS/email and optional card-on-file tokenization with explicit consent through the payment processor.

Acceptance Criteria
Two-Screen Mobile Checkout Flow
Given a patient opens a valid Chairside QR checkout link on a mobile device, When the checkout loads, Then the patient can review amount due, initials, and appointment time and select a payment method on one screen, And the entire flow requires no more than two screens before final confirmation. Given tips are enabled for the clinic, When the checkout screen renders, Then tip selection appears inline on the first screen without adding another step, And the default selection is No tip. Given the patient authorizes payment, When the processor returns an approval, Then the confirmation screen appears within 2 seconds and displays success status, amount, and masked payment method (e.g., Visa ••••1234). Given typical mobile conditions, When measured on a mid-tier device over 4G, Then the 95th percentile time from initial view render to authorization complete is ≤ 15 seconds, And the initial view’s Largest Contentful Paint is ≤ 2.5 seconds.
Supported Payment Methods and Smart Availability
Given Safari on iOS with a configured Apple Pay wallet, When the checkout loads, Then an Apple Pay button is visible and functional, And selecting it completes payment via Apple Pay sheet without leaving the flow. Given Chrome on Android with a configured Google Pay wallet, When the checkout loads, Then a Google Pay button is visible and functional, And selecting it completes payment via Google Pay without leaving the flow. Given a device/browser without a supported wallet, When the checkout loads, Then only the card entry form (accepting Visa/Mastercard/Amex/Discover and HSA/FSA cards) is shown. Given an HSA/FSA card is entered, When the payment is processed, Then the transaction is accepted if eligible and tagged in processor metadata as HSA/FSA where available. Given card payments may require SCA/3DS, When the processor requests authentication, Then an embedded challenge is presented and, upon success, the flow returns to confirmation without data loss.
Accessibility: WCAG 2.1 AA Compliance
Given the checkout UI, When evaluated, Then all interactive targets have a minimum hit area of 44x44 dp, And keyboard focus is visible with logical order. Given textual content, When contrast is measured, Then it meets or exceeds 4.5:1 for normal text and 3:1 for large text. Given form fields and controls, When used with screen readers (VoiceOver/TalkBack), Then labels, roles, and states are correctly announced, And error messages are programmatically associated and announced. Given a time-limited session, When time remaining drops below 60 seconds, Then a non-blocking ARIA live announcement warns the user of pending expiry. Given only the keyboard or switch control, When navigating the flow, Then all functionality is operable without touch gestures or device motion.
Minimal PHI Display and Privacy Safeguards
Given the checkout screen, When patient context is shown, Then only initials (e.g., J.D.) and appointment date/time are displayed, And no diagnosis, procedure names, insurance IDs, DOB, address, or full name appear. Given the checkout URL, When inspected, Then it contains no PHI in path or query parameters. Given client storage, When the session is active, Then no PHI is persisted to localStorage, sessionStorage, or cookies beyond what is strictly necessary for session integrity. Given observability/logging, When client and server logs are generated, Then they exclude PHI beyond initials and appointment time.
Error Handling, Session Expiry, and Recovery
Given invalid card input (number, expiry, CVC, ZIP), When the user attempts to submit, Then inline, plain-language errors identify the field and how to fix it without clearing other valid entries. Given a network timeout or processor error, When payment submission fails, Then a clear error state is shown with options to Retry or Choose another method, And no duplicate charge is created upon retry. Given the session expires, When the user attempts to continue, Then an Expired session screen explains what happened and instructs the patient to request a new QR from staff, And the Pay action is disabled. Given a QR session is bound to a device, When the link is opened on a different device, Then the UI displays Session already in use on another device and blocks payment. Given a payment is declined, When the processor returns a decline, Then a failure state shows a human-readable message (no raw codes) and allows switching methods or retrying.
Localization: English/Spanish with Plain Language
Given the browser language is es-*, When the checkout loads, Then Spanish copy is shown by default with an in-flow toggle to switch to English, and vice versa for en-*. Given any UI text (buttons, labels, errors, confirmations), When viewed in Spanish, Then all text is translated with no English fallbacks and uses plain language equivalent. Given dates, times, and currency, When rendered, Then they are formatted for locale while preserving USD (e.g., $123.45) and 12-hour time for US audiences, with Spanish-language month/day strings where applicable. Given copy review, When assessed, Then key instructional and error text targets an 8th-grade reading level (Flesch-Kincaid ≥ 60) in both languages.
Receipts, Optional Card-on-File Consent, and Tips Configuration
Given payment succeeds, When the confirmation screen is shown, Then the patient can choose receipt delivery via SMS or email, Or opt out, And phone/email inputs are validated before sending. Given a receipt is requested, When sent, Then the receipt is delivered within 60 seconds and includes practice name, amount, date/time, and masked payment method; no PHI beyond initials and appointment time is included. Given card-on-file is supported, When the confirmation screen is shown, Then a processor-hosted or approved consent checkbox is present and unchecked by default with clear purpose text and link to terms; tokenization occurs only if the user explicitly checks the box and confirms. Given consent is given, When tokenization completes, Then an audit record stores consent timestamp, consent text version, last4, brand, and processor token ID; if consent is not given, no token is stored. Given tips are configured by the clinic, When the checkout screen renders, Then preset tip options (e.g., 0%, 10%, 15%, 20%) and a custom amount (capped at $500) are available inline, defaulting to No tip, And selecting a tip updates the total instantly; if tips are disabled, no tip UI is shown.
Payment Processor Integration & Webhooks
"As an office manager, I want payments to process securely and automatically update the appointment record so that staff doesn’t have to reconcile manually."
Description

Integrate with a primary PSP (e.g., Stripe) via PaymentIntent-style flows to support SCA/3DS challenges and digital wallets, with an abstraction layer for future processors. Include idempotent creation, metadata linking (appointment ID, patient ID), and secure client confirmation. Implement webhook handlers for succeeded/failed/requires_action events, with retries and signature verification, to update appointment balances, mark confirmations, and issue receipts. Maintain PCI SAQ A scope by never handling raw PAN and storing only PSP tokens and non-sensitive metadata.

Acceptance Criteria
Idempotent PaymentIntent Creation with Appointment/Patient Metadata
- Given an active chairside QR session for appointment A and patient P, When the backend creates a PaymentIntent with idempotency key K, Then the PSP returns a single PaymentIntent with amount equal to A's outstanding balance, currency set to the clinic's currency, and metadata including appointmentId=A, patientId=P, qrSessionId=S, and createdBy. - Given the same request is retried with the same idempotency key K within 24 hours, When the backend calls the PSP again, Then the PSP returns the original PaymentIntent (same id) and no duplicate charge is created. - Then the system persists only PSP identifiers/tokens and non-sensitive metadata; no primary account number or CVV is ever stored or logged.
SCA/3DS Client Confirmation in Chairside QR Flow
- Given a PaymentIntent that requires_action, When the patient proceeds on the bound device, Then a 3DS/SCA challenge is presented via the PSP SDK and, upon completion, the PaymentIntent transitions to succeeded or requires_payment_method within 30 seconds. - Given a PaymentIntent client_secret, When a second, non-bound device attempts to confirm, Then the attempt is rejected with HTTP 403 and the client_secret is invalid for that device. - Then client confirmation is performed using PSP-hosted components only; no card fields are rendered by SmileCue, and no raw PAN is accessible to the SmileCue domain.
Digital Wallet Support in Chairside Payment
- Given a device with Apple Pay or Google Pay capability, When the payment page loads, Then the corresponding wallet button renders within 2 seconds and is enabled. - When the patient pays using a wallet, Then the PaymentIntent succeeds with a wallet payment method type and a receipt token is returned from the PSP. - Given a device without wallet capability, When the payment page loads, Then wallet buttons are not displayed.
Webhook Handling with Signature Verification and Idempotent Processing
- Given a PSP webhook event for payment_intent.succeeded, payment_intent.payment_failed, or payment_intent.requires_action, When it is received, Then the signature is verified using the configured secret and timestamp tolerance of 5 minutes; invalid signatures result in HTTP 400 without side effects. - When a valid event is received, Then processing is idempotent by event id; duplicates or PSP retries do not change state more than once. - Valid events are persisted and enqueued atomically; on success the endpoint responds HTTP 2xx within 2 seconds, and on persistence failure it responds 5xx to trigger PSP retry.
Appointment Balance, Confirmation, and Receipt Updates on Payment Events
- Given a payment_intent.succeeded event with amount X for appointment A, When processed, Then A's balance is reduced by X, A's confirmation status is set to Confirmed if fully paid, and a receipt is generated and sent to the patient's preferred channel (SMS/email) within 60 seconds. - Given a payment_intent.payment_failed event, When processed, Then A's balance remains unchanged, a failure note is attached to the appointment, and the patient is offered a retry link if the QR session is still active. - All changes are audit-logged with PSP event id, timestamp, actor=system, and previous/new values.
Device-Bound, Time-Boxed Chairside QR Session Security
- Given a newly generated QR session S, When first scanned, Then S binds to the first device fingerprint and IP combination and marks all other devices as unauthorized. - Given S has a lifetime of 10 minutes of inactivity, When the window elapses or staff ends the session, Then the client_secret and any pending PaymentIntent are invalidated, the QR code is marked expired, and subsequent requests return HTTP 410 Gone. - Staff can regenerate a new QR from the appointment view; When regenerated, Then the prior session is terminated and cannot be used.
PSP Abstraction Layer Contract and Swappability
- Given the IPaymentProvider interface, When running contract tests against Stripe and a Mock provider, Then all createIntent, confirm, webhookVerify, and parseEvent behaviors pass with identical domain outcomes and event payloads normalized. - Given a configuration switch, When the primary PSP is changed from Stripe to Mock in a staging environment, Then no application code changes are required and all end-to-end payment tests pass with the same acceptance outcomes. - Provider-specific fields are isolated to the adapter layer; no provider-specific types leak into domain models.
Handoff Failover & Recovery Paths
"As front-office staff, I want reliable fallbacks when a patient can’t scan the QR so that we can still complete payment without delays."
Description

Provide robust alternatives when scanning fails: display a short URL and 6–8 character code alongside the QR, allow sending the link via SMS/email from the appointment view, and accept manual code entry on the payment page. Support session cancellation, regeneration, and interrupted-session recovery within the expiration window. Present clear guidance for declined payments with retry options and surface offline/network error messaging with safe recovery steps. Log failures for support diagnostics.

Acceptance Criteria
QR Scan Fails—Short URL and One-Time Code Shown
- Given an appointment view with Chairside QR enabled, When a QR handoff session is generated, Then a short HTTPS URL and a 6–8 character one-time code are displayed adjacent to the QR. - Given the code is displayed, When inspected, Then it is uppercase alphanumeric, excludes ambiguous characters (I, O, 1, 0), and length is between 6 and 8. - Given the session is active, When the appointment view is reloaded, Then the short URL and code remain unchanged until expiration or manual regeneration. - Given the session expires per configured window, When expiration occurs, Then the QR, short URL, and code are invalidated and visually marked as expired in the UI. - Given display occurs, When rendered, Then no PHI beyond patient first name and appointment time is shown alongside the QR/URL/code.
Fallback Link Delivery via SMS/Email from Appointment View
- Given the patient has consented contact channels on file, When staff selects Send Link, Then SMS and Email options are offered with the preferred channel preselected. - Given SMS is selected, When Send is tapped, Then the patient receives an SMS with the short URL and one-time code within 10 seconds, and message content contains no PHI beyond first name and appointment time. - Given Email is selected, When Send is clicked, Then the patient receives an email with the link and code within 60 seconds, with subject/body free of sensitive PHI and including clinic branding. - Given delivery fails (provider error, invalid contact), When the send attempt completes, Then the UI surfaces a clear error with reason, offers immediate retry or alternate channel, and records the failure event with timestamp and error code. - Given a session is regenerated, When staff resends, Then prior links/codes are invalidated and the new URL/code are included in the new message.
Manual Code Entry on Payment Page
- Given a patient opens the short URL, When the page loads, Then a code entry field is present accepting 6–8 characters with client-side validation and paste support. - Given a valid, unexpired code, When submitted, Then the session binds to the current device and navigates to the payment summary within 2 seconds. - Given an invalid or expired code, When submitted, Then an error message explains the code is invalid/expired, provides a non-identifying recovery option to request a new code via staff, and does not leak validity details. - Given a code was successfully redeemed on one device, When the same code is submitted on another device within the window, Then redemption is rejected with guidance to rescan/regenerate via staff.
Session Cancellation and Regeneration
- Given an active handoff session, When staff selects Cancel Session, Then the session is immediately invalidated and all entry points (QR, short URL, code) stop working within 1 second. - Given a canceled or expired session, When staff selects Regenerate, Then a new session with a new QR, short URL, and code is created within 2 seconds. - Given regeneration occurs, When the appointment view updates, Then prior session artifacts are visually marked invalid and an audit log entry records staff ID, timestamp, appointment ID, and action (cancel/regenerate). - Given regeneration is performed within the expiration window, When created, Then the new session inherits appointment context but does not carry over partial payment state.
Interrupted-Session Recovery Within Expiration Window
- Given a patient began payment and lost connectivity or closed the browser, When they reopen the short URL on the same device within the configured expiration window, Then the session restores to the last confirmed step without data loss. - Given recovery to a step with sensitive fields, When the page loads, Then sensitive inputs (e.g., card number, CVV) are not auto-filled and must be re-entered. - Given the patient opens the link on a different device within the window, When a device-bound session exists, Then the page explains the binding and instructs to rescan/regenerate or proceed only via staff-approved transfer flow (if enabled). - Given the expiration window has elapsed, When the URL is opened, Then an expiration notice is shown with option to request a new code via staff and no session data is exposed.
Declined Payments—Guidance and Retry
- Given a payment is declined by the processor, When the response is received, Then the patient sees a user-friendly reason category (e.g., insufficient funds, incorrect info, suspected fraud) without exposing PCI data. - Given a decline is shown, When next steps are presented, Then the UI offers retry with card re-entry, an alternate payment method if enabled (e.g., ACH), or a Save and Pay at Front Desk option. - Given a retry is attempted, When up to 3 attempts occur within 10 minutes, Then no duplicate charges are created and each attempt is correlated under a single session ID. - Given more than 3 declines occur within 10 minutes, When threshold is exceeded, Then the system suggests an alternate channel and notifies staff in the appointment view with the decline summary.
Offline/Network Errors and Safe Recovery
- Given a network disruption on the patient device, When detected, Then an offline banner appears, submit actions are disabled, and lightweight status checks auto-retry every 5 seconds. - Given a server-side error occurs, When the patient attempts an action, Then a friendly error message is shown, no data is lost, and a Back to Start option preserves device binding. - Given connectivity is restored within 2 minutes, When the app auto-detects availability, Then the flow resumes at the last step and re-validates session freshness before payment proceeds. - Given repeated connectivity failures (3 consecutive), When threshold is hit, Then instructions to contact staff are shown and a QR/link regeneration option is presented; all error events are logged with session ID, device fingerprint, timestamp, and error codes.
Audit Trails, Access Control, and HIPAA Safeguards
"As a compliance officer, I want detailed, secure audit logs and minimal PHI exposure so that we meet HIPAA requirements and can investigate incidents."
Description

Record immutable, timestamped audit events for QR generation, scans, device binding, payment attempts, outcomes, cancellations, and expirations with staff/user IDs and originating IPs. Enforce role-based permissions for generating and canceling sessions. Minimize PHI exposure (no PHI in URLs, tokens, or logs) and encrypt data in transit and at rest. Provide configurable retention, exportable audit reports, and alerts for anomalous activity (e.g., repeated token reuse attempts). Ensure BAAs are honored and policies align with HIPAA and organizational compliance.

Acceptance Criteria
Immutable Audit Logging for Chairside QR Lifecycle
Given a staff user generates a Chairside QR session, When the action is executed, Then an immutable audit event is appended with fields: event_id (UUIDv4), occurred_at (UTC ISO-8601 ms), actor_user_id, actor_role, org_id, location_id, appointment_id (if applicable), session_id, action (QR_GENERATED), originating_ip, user_agent_hash (SHA-256), outcome (success), and request_id. Given a QR is scanned and a device is bound, When the first device binds, Then audit events QR_SCANNED and DEVICE_BOUND are appended with the same required fields and device_fingerprint_hash present. Given a payment attempt occurs, When the attempt succeeds or fails, Then audit events PAYMENT_ATTEMPTED and PAYMENT_SUCCEEDED or PAYMENT_FAILED are appended including amount_cents, processor_txn_id (if available), and failure_reason_code (on failure). Given a session is canceled or expires, When the event occurs, Then SESSION_CANCELED or SESSION_EXPIRED is appended with actor_user_id (for cancel) or system as actor (for expire). Given events are written, When persisted, Then they are append-only with a hash_chain_prev_event_id and hash_chain_signature making tampering detectable. Given normal operation, When events are written, Then p95 write latency <= 1s and zero data loss across retries (max 3 with exponential backoff); on final failure, the originating action is aborted and the user is notified. Given a single session, When multiple events occur, Then event ordering is preserved per session_id.
RBAC for Generating and Canceling QR Sessions
Given default roles (Admin, Office Manager, Billing, Front Desk), When permissions are configured so that Admin, Office Manager, and Billing can generate/cancel QR sessions and others cannot, Then those roles receive 200 on allowed actions and others receive 403 RBAC_DENIED. Given a user without location scope, When they attempt to generate/cancel a session for a different location, Then the request is denied with 403 RBAC_DENIED and no session is created/modified. Given permissions are changed by an Admin, When the change is saved, Then enforcement updates within 60 seconds and is applied server-side for all subsequent requests. Given any access decision, When evaluated, Then an ACCESS_GRANTED or ACCESS_DENIED audit event is recorded with actor_user_id, role, resource (location_id, appointment_id), decision, and policy_id. Given a suspended or deactivated user, When they attempt any QR action, Then the request is blocked with 403 USER_INACTIVE and logged.
PHI Minimization in URLs, Tokens, and Logs
Given a generated QR/link, When inspected, Then the URL path and query contain no PHI (no patient name, DOB, phone, email, address, insurance IDs, diagnosis/procedure codes) and only an opaque token. Given a session token is created, When decoded or viewed, Then it contains no PHI claims; it is a 256-bit-entropy opaque or signed token with TTL <= 10 minutes and single-use semantics. Given any server/client log entry, When emitted, Then Authorization headers, cookies, and query parameters are redacted; no PHI values appear in app logs, access logs, or analytics; automated scans over 10k sample events find 0 PHI matches. Given an attempt to log structured fields containing PHI, When processed by the logging pipeline, Then values are redacted/masked per allowlist, and the redaction is verified in log storage. Given a QR is displayed, When rendered, Then the QR payload encodes only the opaque token and does not embed PHI or payment details.
Encryption in Transit and At Rest for Chairside QR
Given any external connection (staff app, patient device, clinic tablet) to SmileCue APIs, When established, Then TLS 1.2+ with modern ciphers is enforced, HSTS is enabled, and SSL Labs grade is A or higher. Given service-to-service communication within the backend, When requests are made, Then mTLS is required and certificates are rotated automatically before expiry. Given sensitive data at rest (audit events, tokens, device fingerprints), When stored, Then it is encrypted with AES-256-GCM using a managed KMS; key access is logged and keys rotate at least every 90 days. Given QR/session tokens, When signed/encrypted, Then signing/encryption keys are rotated at least every 90 days and stored in FIPS 140-2 validated modules. Given a decryption or key access attempt by an unauthorized principal, When evaluated, Then it is denied and an audit event KEY_ACCESS_DENIED is recorded.
Configurable Audit Retention and Exportable Reports
Given an org admin sets audit retention, When updated to a value between 180 and 2555 days, Then the new policy is saved, applied to new and existing records, and logged with actor_user_id and old/new values. Given retention TTLs, When the daily purge job runs, Then expired events are deleted within 24 hours, with purge counts logged; events under legal hold are excluded. Given a compliance user requests an export, When filters (date range, org/location, actor, action types, outcome) are applied, Then a CSV or JSON export is generated asynchronously for up to 1,000,000 events and a download link is provided within 5 minutes for p95. Given exports, When generated, Then they include all required fields, are encrypted at rest, the download link expires in 24 hours, access is RBAC-restricted, and an AUDIT_EXPORT_CREATED event is logged. Given a failed export, When it occurs, Then a clear error is returned, no partial data is exposed, and an AUDIT_EXPORT_FAILED event is logged with failure_reason_code.
Anomalous Activity Detection and Alerting
Given invalid or expired token usage, When >= 5 failed accesses from the same IP or device_fingerprint occur within 10 minutes, Then an alert (severity=medium) is generated, delivered to configured channels within 2 minutes, and logged. Given token reuse across sources, When >= 3 distinct IPs attempt the same token within 5 minutes, Then a high-severity alert is generated and the token is force-invalidated. Given excessive cancellations, When a single user cancels >= 10 QR sessions within 10 minutes, Then a medium-severity alert is generated and the behavior is logged for review. Given alerts are configured, When an org disables a channel (email/webhook), Then remaining channels continue to receive alerts and configuration changes are audited. Given alert noise, When identical events repeat, Then alerts are deduplicated with a 10-minute suppression window while counts are aggregated in the alert payload.
BAA Enforcement and Compliance Controls
Given an organization without an executed BAA on file, When an admin attempts to enable Chairside QR or process a payment, Then the action is blocked with 403 BAA_REQUIRED and an audit event BAA_ENFORCEMENT_TRIGGERED is recorded. Given an organization with an executed BAA, When features are enabled, Then activation proceeds and an audit event BAA_VERIFIED is recorded with BAA document ID and effective dates. Given compliance document updates, When policies or subprocessors change, Then admins are notified, must attest within 30 days, and attestation events are recorded; non-attestation triggers feature suspension warnings. Given a request to view compliance status, When accessed by Admin/Compliance roles, Then the UI/API returns current BAA status, effective dates, subprocessors, and last attestation, without exposing PHI, and access is audited.
Admin Configuration and Kiosk Mode
"As an administrator, I want to configure how Chairside QR operates and enable a secure kiosk mode so that the feature fits our workflow and stays secure."
Description

Add admin settings to control QR expiration, allowed payment methods and wallets, tipping, partial payments, localization, and branding. Implement clinic tablet kiosk mode with guided flow, app/pinned-browser locking guidance, inactivity timeout, automatic session cleanup, and optional device registration. Configure default receipt delivery (SMS/email) and staff permissions for QR features. Provide a lightweight dashboard for monitoring active sessions and recent payments.

Acceptance Criteria
QR Expiration Policy Enforcement
Given an admin sets a QR expiration between 1–30 minutes (default 10) When a staff member generates a QR session Then the countdown timer displays the configured duration and decrements in real time And the QR becomes invalid immediately upon expiry with an "Expired – generate new QR" message And attempting to scan an expired QR returns HTTP 410 and shows an expiry screen in kiosk mode And regenerating a QR invalidates any prior unexpired session for the same appointment And the system logs expiration events with appointment ID, staff ID, device ID, and timestamp
Allowed Payment Methods and Wallets Configuration
Given an admin enables/disables specific payment methods (Card, HSA/FSA Card, ACH) and wallets (Apple Pay, Google Pay) per clinic When a QR session starts on a device with certain capabilities Then only enabled and supported methods are shown and selectable And disabled methods are hidden and cannot be invoked via direct URL or deep link (returns 403) And wallet buttons render only when both the clinic and device/browser support them And selection and authorization of a disabled method are blocked and logged with reason "method_disabled" And changes to allowed methods take effect for new sessions within 60 seconds
Tipping and Partial Payments Controls
Given an admin configures tipping (on/off, presets 0/10/15/20%, custom allowed) and partial payments (on/off, min amount or %) When a payer opens the payment screen Then tipping UI appears only if tipping is enabled and reflects configured presets and custom rules And partial payment option appears only if enabled and enforces the configured minimum And the system prevents payment submissions that violate min/max rules with inline validation And receipts and ledger entries itemize subtotal, tip, partial amount, and remaining balance correctly to the cent And remaining balance updates in the PMS/integration webhook within 30 seconds of settlement
Kiosk Mode Activation, Guided Flow, and Device Registration
Given an admin optionally registers clinic tablets with a device name and location When staff launches Chairside QR in kiosk mode on a registered device Then the app shows a guided, step-by-step flow with large controls and no access to admin settings And the UI displays the device name for staff verification and logs kiosk_start with device ID And an exit requires a staff PIN or biometric and is not accessible via browser back or system gestures (when pinned) And if the device is unregistered and policy requires registration, kiosk mode blocks start and shows a registration prompt And the app provides OS-specific instructions to pin/lock the app with a checklist confirmation
Inactivity Timeout and Automatic Session Cleanup
Given an admin sets a kiosk inactivity timeout between 30–600 seconds (default 120) When there is no user interaction for the configured duration Then the session shows a timeout screen, clears any entered data, and returns to the kiosk home And the associated QR/payment token is invalidated and cannot be reused And the active-session record is removed from the dashboard within 10 seconds and an audit log is created with reason "inactivity_timeout" And if payment authorization was in progress, the flow is cancelled and any holds are voided
Localization, Branding, and Default Receipt Delivery
Given an admin selects a default locale, currency, logo, and brand colors and sets receipt delivery default (SMS or Email) When a QR session starts Then all kiosk text, date/time, number, and currency formats follow the selected locale, with RTL layout where applicable And the clinic logo and colors apply to the kiosk, QR page, and receipts with AA contrast compliance And the default receipt delivery method is preselected, with the ability for staff to override per session And if patient contact info for the default method is missing, the system prompts for an alternative method And receipt delivery status (queued/sent/failed) is recorded and visible in the dashboard and audit log
Role-Based Permissions and Dashboard Monitoring
Given roles (Admin, Staff, Read-Only) have defined permissions for generating QR, configuring settings, viewing dashboard, and refunding When a user accesses QR features or the monitoring dashboard Then capabilities align with role permissions and unauthorized actions return 403 and are logged And the dashboard lists active sessions (appointment, device, staff, start time, time remaining) and the last 50 payments (status, amount, method) And dashboard data auto-refreshes at least every 10 seconds without full page reload And clicking a session allows end/cleanup; clicking a payment shows details without exposing full PAN or PHI And all dashboard views and actions are recorded with user, timestamp, and IP address

Product Ideas

Innovative concepts that could enhance this product's value proposition.

Consent Lockbox

A tamper-proof consent ledger tracking opt-in/out by channel, language, and timestamp; templates auto-check consent before sending, lowering TCPA risk and carrier blocks.

Idea

No-Show Radar

Predicts appointment no-show risk from history and channel response; triggers earlier outreach, voice fallbacks, or deposits for high-risk slots to protect chair time.

Idea

Family Bundle Sync

Automatically groups family members, coordinates sibling appointments, and sends one parent-friendly message to confirm or reschedule everyone in a tap.

Idea

Smart Gap Filler

Monitors cancellations in real time and instantly texts best-fit waitlisted patients; confirms on reply and writes back to the calendar without staff clicks.

Idea

SecureLink OTP

Delivers PHI via expiring magic links gated by one-time passcodes; verifies identity before revealing prep instructions, forms, or X-rays, reducing misdelivery risk.

Idea

BranchLab A/B Studio

Drag-and-drop experiments for message wording, timing, and channel branches; auto-allocates traffic, declares winners by cohort, and publishes improvements in one click.

Idea

Text-to-Pay Chairside

Sends PCI-compliant pay links inside reminders for deposits, co-pays, or balances; auto-posts to PMS and retries failed cards, cutting day-of no-shows.

Idea

Press Coverage

Imagined press coverage for this groundbreaking product concept.

P

SmileCue Launches Consent Suite to Make Compliant Patient Outreach Effortless for Dental Practices

Imagined Press Article

San Francisco, CA — SmileCue today announced its new Consent Suite, a comprehensive set of tools that makes compliant patient communication simple, provable, and scalable for small-to-medium dental practices. Built specifically for HIPAA-governed workflows, Consent Suite removes the guesswork from SMS, email, and voice outreach—so teams can focus on keeping schedules full while staying aligned with TCPA, state, and carrier policies. Summary: SmileCue’s Consent Suite unifies Jurisdiction Rules, Evidence Vault, Consent Pulse, Universal Suppression, Voice Consent, and Guardian Link into a single, automated framework. Practices get the right message, to the right person, at the right time—backed by immutable audit trails and real-time consent health. Who it’s for: Office managers, compliance leads, and multi-location coordinators who need to scale patient reminders, recalls, and two-way messaging without risking deliverability or regulatory missteps. Pediatric and family practices benefit from Guardian Link’s caregiver-aware consent routing. What’s new: - Jurisdiction Rules: Automatically applies state and country TCPA requirements, quiet hours, and consent classes (informational vs. marketing) based on patient location and channel. Staff no longer need to memorize rule variations—SmileCue preflights every send. - Evidence Vault: Generates an immutable, audit-ready record for each consent event, including timestamp, channel, language, template version, user/source, and IP/caller ID where applicable. One-click export speeds responses to audits and carrier inquiries. - Consent Pulse: Real-time dashboards and alerts for opt-ins/opt-outs, consent decay, and carrier feedback. When permissions near expiry, Consent Pulse launches re-permission campaigns with recommended channel and language to recover opt-ins. - Universal Suppression: Propagates opt-outs across connected systems via APIs and webhooks, and blocks outbound sends at preflight. Every platform stays in sync, preventing accidental outreach. - Voice Consent: Captures verbal consent via recorded IVR flows or staff-assisted calls with multi-language prompts. Transcripts and audio are time-stamped and stored in the ledger. - Guardian Link: Links guardian permissions to dependents, honoring family-wide opt-in/out with per-child overrides and channel-level preferences. Why it matters: Inconsistent policies, fragmented tools, and unclear audit histories increase legal exposure and erode carrier trust—hurting deliverability. SmileCue centralizes consent governance and proves compliance automatically, so practices can scale patient communication confidently. How it works: Every outbound touch runs through Consent Suite’s preflight. Jurisdiction Rules determine quiet hours and consent class. Templates are verified against approvals. Universal Suppression checks for opt-outs across systems. If the patient prefers voice or is SMS-averse, Voice Consent enrolls them via a quick call. Guardian Link ensures the correct caregiver receives pediatric communications. Quotes: “Dental teams shouldn’t have to be telecom lawyers to communicate with patients,” said Maya Chen, Chief Compliance Officer at SmileCue. “Consent Suite turns a complex regulatory landscape into a guided, automated workflow—complete with the evidence you need at audit time.” “Guardian Link has been a game-changer for our pediatric practice,” said Priya Patel, Operations Director at Riverbend Kids Dental. “We can honor family preferences, route messages to the right caregiver, and still maintain a clean, provable consent record. Our confirmations are up, and our team spends less time untangling permissions.” “Carriers reward trustworthy senders,” added Alex Romero, VP of Product at SmileCue. “By aligning quiet hours, template approvals, and consent health in one place, practices see better deliverability and fewer blocks—without extra clicks.” Results and benefits: - Less risk: Automated adherence to TCPA and state rules, plus immutable proof via Evidence Vault. - Better deliverability: Cleaner lists and consistent quiet-hour compliance improve carrier trust. - Faster operations: One-click exports, real-time consent dashboards, and automatic re-permission. - Pediatric-ready: Guardian-aware models respect caregiver relationships and per-child preferences. Availability and pricing: Consent Suite is available today to all SmileCue customers in the U.S. and Canada, with global jurisdiction mappings rolling out this fall. Evidence Vault and Consent Pulse are included on Growth and Enterprise plans; Voice Consent and Guardian Link are optional add-ons. Existing customers can activate features in Admin > Compliance. Integration and migration: SmileCue connects to leading practice management systems (PMS) and common email/SMS providers. Universal Suppression synchronizes consent changes across tools via webhook or API. Evidence Vault supports bulk import of historic consent data to consolidate records under a single audit trail. Roadmap: Upcoming capabilities include multi-language consent templates by cohort, advanced carrier feedback loops, and automated quiet-hour exceptions for confirmed day-of emergencies while staying within allowable informational classes. About SmileCue: SmileCue is a HIPAA-compliant patient communication platform that automates SMS, email, and voice reminders with adaptive, response-driven branching. Practices cut manual scheduling by up to 60%, lift confirmations to 85% within three months, and reduce no-shows by as much as 40%. Media contact: Press Relations, SmileCue press@smilecue.com +1 (415) 555-0147 www.smilecue.com/press

P

SmileCue Debuts No‑Show Protection Stack to Safeguard Chair Time and Raise Confirmation Rates

Imagined Press Article

San Francisco, CA — SmileCue today introduced its No-Show Protection Stack, a coordinated set of risk-aware capabilities that helps dental practices anticipate missed appointments and act early to protect schedules. The stack pairs transparent predictions with automated, consent-safe actions—lifting confirmations while reducing staff workload. Summary: The No-Show Protection Stack combines Risk Heatmap, Score Explain, Auto Playbooks, Confidence Tuner, Smart Deposits, and Hold & Release. Practices see at-a-glance risk across providers and locations, understand why each slot is vulnerable, and let SmileCue execute the right escalation—earlier cadence, voice fallback, guardian CC, or deposit request—based on rules they control. The problem: Missed appointments waste premium chair time, frustrate providers, and create last-minute scramble at the front desk. Traditional reminder systems treat all appointments the same, causing outreach fatigue without meaningfully reducing no-shows. Teams need targeted, explainable risk insights with compliant automation. What’s included: - Risk Heatmap: A color-coded schedule view that highlights predicted no-show risk by slot, provider, and location in real time. Filter by appointment type or daypart and apply bulk actions to protect vulnerable blocks. - Score Explain: Human-readable reasons behind each risk score—e.g., prior attendance, booking lead time, channel responsiveness, weather/commute signals, guardian involvement—with a next-best-action tip. - Auto Playbooks: Turns risk thresholds into automated, branching actions, fully integrated with consent rules: earlier cadence, multilingual switch, voice fallback, double-confirm steps, guardian CC, or deposit request for high-value bookings. - Confidence Tuner: A sensitivity slider with a what-if simulator projecting chairs saved, extra outreaches sent, and expected confirmation lift by cohort—so managers can balance aggressiveness with patient experience. - Smart Deposits: For high-risk, high-value appointments, triggers a secure, patient-friendly deposit request via link or staff-assisted call. Eligibility rules, insurance exceptions, and compassionate waivers protect goodwill. - Hold & Release: Places soft holds on adjacent slots or pre-stages backup patients from the waitlist, auto-releasing when confirmations hit a safe threshold. No hard double-booking. How it works: SmileCue updates risk in real time as new signals arrive. The front desk can act manually from the Risk Heatmap or let Auto Playbooks run in the background. All actions respect Jurisdiction Rules and consent class, with decisions logged to Evidence Vault for audit readiness. Confidence Tuner allows per-provider, per-appointment tuning to reduce false alarms and avoid over-messaging. Quotes: “Transparency is table stakes,” said Jordan Alvarez, Head of Data Science at SmileCue. “Score Explain makes the ‘why’ behind each risk crystal clear, and our next-best-action tips give teams the confidence to automate without the black box.” “We used to blast everyone, which annoyed low-risk patients and still didn’t protect our surgical days,” said Sam Rodriguez, Scheduling Lead at Meridian Oral Surgery. “With SmileCue, we see where to focus, request deposits only when warranted, and keep high-value blocks intact. Our surgical no-shows dropped by a third in two months.” “Risk-aware automation needs a dial, not a switch,” added Elena Moore, VP of Product at SmileCue. “Confidence Tuner helps managers right-size intervention by cohort so they maximize saved chairs without creating outreach fatigue.” Benefits: - Fewer no-shows with earlier, targeted outreach. - Stronger provider productivity and revenue predictability. - Patient-friendly automation that avoids over-messaging. - Compliant execution with full audit trails. Availability: The No-Show Protection Stack is available today to all customers on Growth and Enterprise plans. Smart Deposits and Hold & Release are optional modules. Existing customers can enable features from the Schedule Protection settings; onboarding takes hours, not weeks. Integration: The stack works with SmileCue’s adaptive messaging and consent layers out of the box. It syncs with leading PMS calendars and can coordinate with waitlists to pre-stage backups without causing double-booking conflicts. Roadmap: Upcoming enhancements include expanded weather and transit signals, provider-specific learning curves, and A/B-tested intervention pathways using SmileCue’s experimentation toolkit. About SmileCue: SmileCue is a HIPAA-compliant patient communication platform that automates SMS, email, and voice reminders with adaptive, response-driven branching. Practices commonly cut manual scheduling by 60%, lift confirmations to 85% within three months, and reduce no-shows up to 40%. Media contact: Press Relations, SmileCue press@smilecue.com +1 (415) 555-0147 www.smilecue.com/press

P

SmileCue Unveils Family Bundle Platform to Simplify Pediatric and Household Scheduling

Imagined Press Article

San Francisco, CA — SmileCue today announced the Family Bundle Platform, a set of caregiver-aware capabilities that streamlines family scheduling, confirmations, and forms for pediatric and household dental care. By coordinating siblings in one experience and honoring guardian permissions, practices fill more chairs with fewer back-and-forths. Summary: Family Bundle Platform brings together Household Graph, Sibling Stacker, Smart Split, Caregiver Cascade, Bundle Prep, and Bundle Waitlist. Parents receive one friendly message to confirm, reschedule, or complete forms for multiple children—while practices maintain consent integrity and a clean audit trail. Why now: Family dentistry is unique. Parents juggle school runs, work shifts, and caregiver responsibilities; standard reminders rarely fit real life. Manual coordination leads to bottlenecks at the front desk and unnecessary no-shows. SmileCue transforms family logistics into a guided, patient-first flow. What’s included: - Household Graph: Automatically discovers and maintains family relationships from the PMS—shared addresses/guardians, insurance, and custom flags—creating a clean, bundle-ready household record. - Sibling Stacker: Finds optimal back-to-back or concurrent slots across providers and rooms, then offers two or three ready-to-book options in one parent-friendly thread. On tap, SmileCue confirms all selections and writes them back to the calendar. - Smart Split: Lets caregivers confirm the parts of a bundle that work and seamlessly reschedule only the conflicting child. Alternatives preserve as much of the family cluster as possible, minimizing disruption. - Caregiver Cascade: Routes each family message to the right caregiver by child, escalating to a secondary contact if there’s no response—respecting language, channel, and time-of-day preferences. - Bundle Prep: Combines pre-visit instructions, forms, and consents for all children into one secure link with per-child tabs and identity verification. Sign once when allowed; complete per-child details where required. - Bundle Waitlist: Tracks multi-slot openings and recommends families that can fill adjacent times in one move. Offers include friendly expiry timers and immediate calendar write-back on confirmation. How it works: Based on upcoming appointments and waitlist availability, SmileCue proposes smart family bundles and sends a caregiver-aware message that respects Guardian Link permissions. Parents can confirm all children at once, split if needed, and finish forms in minutes. If a conflict arises, Smart Split keeps as much of the bundle intact as possible. Throughout, Consent Suite preflights outreach, logs decisions in Evidence Vault, and syncs opt-outs via Universal Suppression. Quotes: “Pediatric and family practices shouldn’t have to choose between a full schedule and a calm front desk,” said Leila Grant, General Manager for Pediatrics at SmileCue. “Family Bundle Platform gives parents flexibility and gives staff stability—everyone wins.” “Before SmileCue, coordinating three siblings across two providers was a tangle of calls,” said Priya Sharma, Practice Manager at Sunshine Smiles Pediatric Dentistry. “Now parents confirm in one tap, complete all forms on one link, and our team focuses on care instead of calendar juggling.” “Consent integrity remains central,” added Maya Chen, Chief Compliance Officer at SmileCue. “Caregiver Cascade respects guardian permissions and language preferences by child, with an audit trail that stands up to scrutiny.” Benefits: - Fewer no-shows from bundled confirmations and realistic family options. - Higher chair utilization with back-to-back sibling scheduling. - Faster intake via consolidated, secure forms. - Reduced front-desk load and better parent experience. Availability and pricing: Family Bundle Platform is available immediately as an add-on to SmileCue Growth and Enterprise plans in North America, with international availability slated for early next year. Sibling Stacker and Bundle Prep can be enabled independently; Smart Split and Bundle Waitlist are part of the full bundle. Integration: Works with SmileCue’s adaptive reminders, Risk Heatmap, and Instant Fill features. Bundle intelligence reads provider availability, room constraints, and insurance flags to produce viable, parent-friendly options without manual triage. About SmileCue: SmileCue is a HIPAA-compliant patient communication platform that automates SMS, email, and voice reminders with adaptive, response-driven branching. Practices cut manual scheduling by up to 60%, boost confirmations to 85% within three months, and reduce no-shows up to 40%. Media contact: Press Relations, SmileCue press@smilecue.com +1 (415) 555-0147 www.smilecue.com/press

P

SmileCue Introduces Instant Fill to Turn Cancellations into Confirmed Appointments in Minutes

Imagined Press Article

San Francisco, CA — SmileCue today launched Instant Fill, a coordinated waitlist, matching, and offer engine that converts last-minute cancellations into confirmed appointments with zero staff clicks. By combining eligibility checks, real-time arrival feasibility, and fairness rules, Instant Fill helps practices protect revenue while keeping patient experience front and center. Summary: Instant Fill unifies FitRank Match, QuickChain Send, ETA Guard, Waitlist Profiles, Offer Composer, Flex Nudge, and Fill Analytics. When a slot opens, SmileCue automatically identifies the best candidates, sends concise multilingual offers with one-tap confirm, and writes the result back to the calendar—often within minutes. What’s included: - FitRank Match: AI ranks waitlisted patients by appointment length, provider/room constraints, insurance/pre-auth status, patient reliability, language/channel preference, and consent. The best-fit person gets the first offer. - QuickChain Send: Time-boxed cascades escalate to the next candidate if there’s no reply within minutes, with temporary holds and fairness rules to avoid spamming. - ETA Guard: Checks distance, traffic, weather, and known availability before sending an offer, ensuring only patients who can realistically arrive receive a message. - Waitlist Profiles: Patients specify preferred days/times, providers, locations, channels, languages, and deposit willingness via a secure link; pediatric options capture caregiver constraints. - Offer Composer: Auto-builds concise, urgency-aware, multilingual offers with optional secure deposit or form links and a clear expiration timer. Alternates of ±15 minutes can be included where allowed. - Flex Nudge: When no perfect match exists, politely asks nearby confirmed patients to shift earlier/later within a safe window to free the precise gap, respecting consent and caregiver needs. - Fill Analytics: Live metrics for fill rate, time-to-fill, revenue saved, outreach per fill, and fairness distribution by provider/location, plus what-if simulators for thresholds and waitlist size. How it works: When a cancellation hits the calendar, Instant Fill evaluates candidates using FitRank Match and ETA Guard, then triggers a QuickChain of offers. The first patient to confirm within the hold window gets the slot; SmileCue releases other holds and updates the calendar and patient threads automatically. Every outreach is preflighted against Jurisdiction Rules and logged in Evidence Vault. Quotes: “Instant Fill gives practices a second chance at revenue that would otherwise vanish,” said Noah Klein, VP of Product at SmileCue. “Because we factor consent, eligibility, and real-world arrival feasibility, teams fill gaps quickly without creating new no-show risk.” “We used to lose whole afternoons when a family canceled,” said Carmen Alvarez, Access Coordinator at Meadowview Community Dental. “Now offers go out immediately in the right language, and we routinely fill within ten minutes. It’s changed our day-to-day volume.” “Fairness matters,” added Jordan Alvarez, Head of Data Science at SmileCue. “QuickChain ensures no single patient is over-messaged while still moving fast to secure the slot.” Benefits: - Higher revenue retention and improved provider utilization. - Patient-friendly offers that match preferences and actual ability to arrive. - Less manual scramble for front-desk teams. - Transparent analytics to fine-tune thresholds and prove ROI. Availability: Instant Fill is available today for Growth and Enterprise plans as an add-on module. Existing SmileCue customers can enable it from the Waitlist & Fills menu and import existing waitlists via CSV or API. Most practices go live in under a day. Integration: Instant Fill works hand-in-hand with SmileCue’s No-Show Protection Stack and Family Bundle Platform. When used together, practices can stage sibling bundles for cancellations, prioritize reliable patients, and right-size nudges to protect patient trust. About SmileCue: SmileCue is a HIPAA-compliant patient communication platform that automates SMS, email, and voice reminders with adaptive, response-driven branching. Practices routinely cut manual scheduling by 60%, boost confirmations to 85% within three months, and reduce no-shows up to 40%. Media contact: Press Relations, SmileCue press@smilecue.com +1 (415) 555-0147 www.smilecue.com/press

P

SmileCue Rolls Out Secure Access and One‑Tap Payments to Remove Friction Before and After the Visit

Imagined Press Article

San Francisco, CA — SmileCue today announced Secure Access and One‑Tap Payments, a combined set of identity, privacy, and payment tools designed to eliminate friction in pre-visit prep, deposits, and post-visit collections—without compromising security or compliance. Patients complete sensitive tasks in seconds; practices see fewer support calls and faster cash flow. Summary: The release brings together SmartCode Routing, Device Bind, SecureShare, Adaptive Auth, Flex Expiry, Safe Preview, Wallet QuickPay, Copay Predictor, SplitPay Families, LineSync Ledger, CardVault Consent, and Chairside QR. The result: PHI remains protected behind expiring, device-aware links, and payments clear in a tap with automatic posting to the PMS. What’s included: - SmartCode Routing: Delivers one-time passcodes over the best available, consented channel—SMS, email, or voice—and falls back if undelivered. Multilingual prompts reduce lockouts and support calls. - Device Bind: Locks each magic link to the requesting device/browser with a short-lived token, blocking forwarded or intercepted links from opening elsewhere. Optional in-office QR handoff preserves convenience. - SecureShare: Allows patients to delegate access to a caregiver for a single item via a time-boxed OTP link, honoring guardian permissions and logging the relationship. - Adaptive Auth: Streamlines verification for recognized devices and steps up checks when risk signals appear (new device, location shift, multiple failures). - Flex Expiry: Sets smart expiration windows by content sensitivity, shows a clear countdown, and supports self-serve resend/refresh with cooldowns; staff can grant one-click extensions. - Safe Preview: Shows practice name, provider, and date—without PHI—before OTP entry to boost trust and completion rates. - Wallet QuickPay: Offers Apple Pay, Google Pay, Click to Pay, and ACH inside the link with device-aware buttons; confirmations write back instantly. - Copay Predictor: Estimates patient responsibility pre-visit using procedure, fee schedule, eligibility, and benefits-used data; updates if coverage changes and supports staff override with notes. - SplitPay Families: Lets caregivers split a bill across multiple payers, cards, or children in the same thread, with per-child receipts and stored preferences. - LineSync Ledger: Maps each payment to the correct PMS ledger code, provider, and location with automatic transaction IDs, partial/overpayment handling, and end-of-day reconciliation exports. - CardVault Consent: Tokenizes card-on-file with explicit, scope-limited consent during checkout or via a separate secure link; patients can revoke at any time. - Chairside QR: Generates one-time QR codes from the appointment view to hand off payment to the patient’s device or a clinic tablet—no terminal required. How it works: Patients receive a Safe Preview branded message with a secure link. SmartCode Routing delivers the OTP, Device Bind secures the session, and Adaptive Auth selects the right verification strength. From there, patients can complete forms, view prep instructions, or pay with Wallet QuickPay. Copay Predictor sets clear expectations up front, while LineSync Ledger posts results to the PMS in real time. If a caregiver needs temporary access, SecureShare grants limited, auditable permissions. For families, SplitPay Families handles complex allocations in one thread. Quotes: “Security should accelerate patient tasks, not slow them down,” said Rhea Montgomery, Chief Security Officer at SmileCue. “Device-bound links and adaptive verification protect PHI while cutting the steps patients have to take.” “Wallet QuickPay is lifting our same-day collections without adding staff work,” said Owen Park, Practice Administrator at Harbor Ortho & Family Dental. “Patients tap to pay, balances post instantly, and our end-of-day reconciliation is cleaner with LineSync.” “Families need flexibility,” added Priya Patel, Operations Director at Riverbend Kids Dental. “SplitPay lets us collect fairly and transparently across siblings and caregivers, which reduces callbacks and confusion.” Benefits: - Fewer lockouts and support calls with smart OTP delivery and device-aware sessions. - Faster collections through one-tap wallet payments and accurate ledger mapping. - Clear expectations with pre-visit cost estimates, reducing day-of disputes. - Strong privacy posture with scoped sharing, time-boxed links, and step-up verification. Availability and pricing: Secure Access and One‑Tap Payments are available today for Growth and Enterprise plans. Wallet QuickPay, LineSync Ledger, and CardVault Consent are payment add-ons; the security features are included in the core platform. Practices can turn on modules in Settings > Security & Payments and go live in days. Integration: Payments and security layers are fully integrated with SmileCue’s reminders and Instant Fill workflows. Deposits triggered by the No-Show Protection Stack use the same secure flows to keep experiences consistent. About SmileCue: SmileCue is a HIPAA-compliant patient communication platform that automates SMS, email, and voice reminders with adaptive, response-driven branching. Customers typically cut manual scheduling by 60%, lift confirmations to 85% within three months, and reduce no-shows up to 40%. Media contact: Press Relations, SmileCue press@smilecue.com +1 (415) 555-0147 www.smilecue.com/press

Want More Amazing Product Ideas?

Subscribe to receive a fresh, AI-generated product idea in your inbox every day. It's completely free, and you might just discover your next big thing!

Product team collaborating

Transform ideas into products

Full.CX effortlessly brings product visions to life.

This product was entirely generated using our AI and advanced algorithms. When you upgrade, you'll gain access to detailed product requirements, user personas, and feature specifications just like what you see below.