Property Management

FixFlow

Fast Fixes, Clear Accountability

FixFlow is a lightweight tenant portal that automates maintenance intake, performs smart triage, and dispatches vetted vendors for independent landlords and small property managers juggling multiple units, shortening repair resolution by automating coordination, creating annotated photo-timelines as auditable records, and cutting owner admin hours and eliminating responsibility disputes.

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

FixFlow

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 small landlords and tenants to resolve maintenance swiftly and transparently, eliminating disputes and restoring owners' time.
Long Term Goal
Within 5 years, empower 50,000 independent landlords to process 10 million annual maintenance requests and cut average repair resolution time by 50%, restoring owner time and clarity
Impact
FixFlow reduces average repair resolution time by 40% and cuts owner administrative hours by 60% within six months for independent landlords and small property managers, eliminating responsibility disputes and lowering emergency dispatches by 30% while boosting tenant satisfaction.

Problem & Solution

Problem Statement
Independent landlords and small property managers juggling multiple units struggle with slow, opaque maintenance: ad-hoc repair intake, unclear responsibility, and manual vendor coordination; existing portals are clunky or enterprise-focused and do not automate triage or dispatch.
Solution Overview
FixFlow automates maintenance intake and smart triage to route repairs to vetted vendors, and creates annotated photo-timelines with status updates so landlords resolve issues faster and eliminate responsibility disputes and admin overhead.

Details & Audience

Description
FixFlow is a lightweight tenant portal that automates maintenance intake, smart triage, and vendor dispatch. It serves independent landlords and small property managers juggling multiple units and ad-hoc repairs. FixFlow reduces repair resolution time, cuts owner admin hours, and eliminates dispute confusion by centralizing requests and tracking responsibility. Its annotated photo-timelines document work progress and outcomes, creating an auditable visual record.
Target Audience
Independent landlords and small property managers (25–55) needing faster maintenance resolution who juggle multiple units.
Inspiration
At 2 a.m. a tenant sent a shaky video of a burst pipe; I feverishly scrolled contact lists, called plumbers, and juggled frantic texts and blurry receipts. Days later I argued over an invoice with no clear timeline. That chaotic, paper-trail mess sparked FixFlow: a lightweight portal to triage emergencies, assign responsibility, and build annotated photo timelines for clear, auditable repairs.

User Personas

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

S

Speedy Host Sam

- 32–44; operates 8–25 short‑term rentals across two cities. - Gross booking revenue $350k–$1.2M; occupancy 65–85%. - Team: solo operator with 2 cleaning crews, 5–8 vendors. - Mobile‑first; iPhone, Airbnb/Vrbo host dashboards; urban Sunbelt base. - Works from home and car between turnovers; limited office hours.

Background

Scaled from one Airbnb to a multi-unit micro-brand after a breakout listing. A last-minute HVAC failure cost a Superhost badge, pushing adoption of automation and timestamped proof to safeguard ratings.

Needs & Pain Points

Needs

1. Real-time triage aligned to checkout windows. 2. One-tap vendor dispatch with availability. 3. Photo timelines for damage claims.

Pain Points

1. Last-minute failures jeopardizing check-ins. 2. Vendors ghosting during peak turnover. 3. Disputes with guests over damages.

Psychographics

- Obsessed with five-star turnaround speed. - Pragmatic operator, automates every repeatable task. - Data-minded, tracks cancellations and downtime rigorously. - Calm under pressure, hates avoidable chaos.

Channels

1. Airbnb Host app - daily 2. WhatsApp - vendor chats 3. Gmail - booking threads 4. Instagram - hosting tips 5. YouTube - maintenance hacks

C

Compliance Captain Carla

- 35–55; supervises 25–90 scattered-site affordable units. - Midwestern city; mixes HUD vouchers and LIHTC compliance. - Team of three: office admin, field tech, Carla. - Desktop-first at office; Android in field; budget-constrained tools. - Reports to board and grantors; audit cycles quarterly.

Background

Started as a case manager, promoted after repeated inspection failures. A costly citation forced standardized logs; now prioritizes auditable trails and SLA compliance to protect residents and funding.

Needs & Pain Points

Needs

1. Audit-ready timelines matching inspection categories. 2. SLA alerts tied to compliance deadlines. 3. Cost approvals within strict caps.

Pain Points

1. Failed inspections from missing documentation. 2. Communication gaps causing missed access. 3. Vendor delays breaching voucher standards.

Psychographics

- Mission-first, relentlessly protects residents’ stability. - Risk-averse, demands auditable, repeatable processes. - Budget hawk, hates surprise emergency spend.

Channels

1. Outlook - primary email 2. Microsoft Teams - staff coordination 3. LinkedIn Groups - housing ops 4. HUD portals - compliance updates 5. YouTube - training refreshers

R

Remote Asset Alex

- 28–45; manages 150–400 doors across three states. - Finance background; spreadsheet native; dashboard-driven decision maker. - Travels frequently; laptop and mobile access in transit. - Mix of SFR and small multifamily; Class B/C. - Works GMT-5; mornings reserved for portfolio reviews.

Background

Missed CapEx forecasts due to scattered maintenance data across PMs. After a preventable mold claim, sought a single source of truth for owner approvals and SLA compliance.

Needs & Pain Points

Needs

1. Cross-portfolio SLA dashboard with exceptions. 2. Approval workflows by property and threshold. 3. Vendor performance scoring and exports.

Pain Points

1. Inconsistent PM processes and codes. 2. Surprise invoices with no proof. 3. Liability from poor documentation.

Psychographics

- ROI-obsessed, values measurable operational leverage. - Standardization zealot, hates ad-hoc processes. - Risk minimizer, prioritizes downside protection.

Channels

1. Gmail - daily ops 2. Slack - PM coordination 3. Google Sheets - tracking 4. LinkedIn - industry insights 5. Asana - tasks follow-up

V

Virtual Dispatcher Val

- 24–38; remote contractor spanning GMT+5 to GMT-4. - Supports 5–10 landlords, totaling 60–220 units. - Works from home; dual monitors, noise-canceling headset, reliable fiber. - Paid hourly or per ticket; measured on SLA targets.

Background

Came from BPO customer support and learned housing maintenance under pressure. Built personal macros and checklists; needs a system that bakes them in across clients.

Needs & Pain Points

Needs

1. Unified inbox with guided triage scripts. 2. Auto-dispatch by category and zip. 3. Clear approval limits and escalation.

Pain Points

1. Juggling landlord-specific rules. 2. Unreachable vendors after hours. 3. Tenants sending incomplete details.

Psychographics

- Efficiency junkie, chases lower handle time. - Service-first, values clear, empathetic communication. - Process-loyal, loves clear escalation paths.

Channels

1. WhatsApp - vendor pings 2. Gmail - all tickets 3. Trello - status boards 4. Zoom - client check-ins 5. Upwork - new clients

W

Warranty Wrangler Will

- 30–50; oversees 50–150 new homes in suburban communities. - Former superintendent; field-based with tablet and truck. - Mix of GC subs and preferred vendors per trade. - Reports to construction VP; primary KPI: days-to-close.

Background

After repeated rework from undocumented fixes, adopted photo-first habits. Warranty disputes with the builder strained relationships; seeks irrefutable timelines for every trade.

Needs & Pain Points

Needs

1. Warranty categorization distinct from tenant repairs. 2. Photo timelines per trade and lot. 3. Scheduling windows with confirmations.

Pain Points

1. Subs missing scheduled windows. 2. Responsibility disputes between builder and owner. 3. Lost evidence for claims.

Psychographics

- Documentation diehard, proof beats opinions. - Quality-driven, hates costly repeat visits. - Schedule disciplinarian, values firm windows.

Channels

1. SMS - quick confirmations 2. Outlook - work orders 3. LinkedIn - trade sourcing 4. Procore - project references 5. YouTube - product fixes

C

Caregiver Reporter Casey

- 26–60; family member or professional caregiver. - Manages 1–4 households’ needs across city and suburbs. - Smartphone-reliant; prefers large-text, voice prompts, reminders. - Coordinates around medical appointments, work shifts, and transit.

Background

Began managing maintenance after repeated missed communications by loved ones. Frustrated by voicemail loops, moved to structured, accessible reporting with predictable updates.

Needs & Pain Points

Needs

1. Proxy permissions with role-based access. 2. Simple, guided capture with accessibility. 3. Reliable updates and windowed scheduling.

Pain Points

1. Repeating details to multiple parties. 2. Unclear ETAs causing caregiver conflicts. 3. Blame disputes between tenant and owner.

Psychographics

- Empathy-driven, seeks calm and clarity. - Reliability-focused, hates uncertainty and surprises. - Privacy-conscious, values granular, permissioned visibility.

Channels

1. SMS - quick updates 2. WhatsApp - family coordination 3. Gmail - confirmations 4. Facebook - community groups 5. YouTube - how-to basics

Product Features

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

Timeboxed Codes

Generate single-use, auto-expiring entry codes tied to the scheduled visit window and unit. Codes activate only during the approved time, then rotate, with door-open timestamps auto-attached to the work order—reducing lockouts and preventing unauthorized entry.

Requirements

Scheduled Window Code Generation and Activation
"As a property manager, I want entry codes that only work during the scheduled visit window so that vendors can access the unit on time without risking unauthorized entry."
Description

Generate unique, single-use entry codes per unit and work order that activate only within the approved visit window (including configurable early/late buffers) and automatically deactivate outside it. Bind each code to the scheduled appointment, vendor identity, and specific door/lock device. Enforce time zone accuracy (including DST), prevent code creation without a confirmed schedule, and support configurable code length/format and reuse policies. Store codes securely (hashed at rest), reveal them just-in-time, and mask/remove from UI after expiration. Provide UI components that display the active window, countdown, and unit/lock association to reduce lockouts and unauthorized entry.

Acceptance Criteria
Code Generation Requires Confirmed Schedule
Given a work order without a confirmed appointment, When a user or system attempts to generate an entry code, Then the request is rejected with an error indicating "Schedule not confirmed". Given a confirmed appointment with unit, vendor, and lock specified, When a code is generated, Then a unique code is created and associated to the appointment ID, vendor ID, unit ID, and lock ID. Given a code is generated, When it is persisted, Then the code value is stored hashed at rest and only masked values appear in logs and analytics. Given a code is generated, When auditing is checked, Then an audit log includes who generated it, timestamp, and all associations.
Code Activation Within Window and Buffers
Given an appointment window [start, end] in the property timezone and configured early buffer E and late buffer L, When the vendor enters the code at time t, Then the lock accepts the code only if t ∈ [start−E, end+L]. Given the code has been accepted once within the allowed window, When the code is re-entered, Then the attempt is rejected as expired/consumed. Given end+L has passed, When the code is entered, Then the attempt is rejected and the code is marked deactivated; rotation to an inactive state occurs within 60 seconds. Given a code is deactivated, When no new appointment is scheduled, Then the code does not reactivate or become valid again.
Time Zone and DST Accuracy
Given the property timezone is configured and appointment times are stored in that timezone, When the appointment spans a DST transition, Then activation honors wall‑clock start and end times in the property timezone. Given the vendor device is in a different timezone, When viewing the appointment, Then the UI displays window times in the property timezone with an explicit timezone label and countdowns reflect the property timezone window. Given server-side validation for code usage, When a code is presented, Then eligibility is evaluated using the property timezone, not the vendor device timezone.
Single-Use and Binding to Vendor and Lock
Given a code is generated for vendor V and lock L, When the code is entered at lock L for the first time within the active window, Then the door unlocks, the code is marked consumed (single-use), and the door-open timestamp is attached to the work order. Given the same code is entered at any lock other than L, When validation occurs, Then the attempt is rejected and no unlock is performed. Given an authenticated user who is not vendor V, When attempting to view or retrieve the code via UI or API, Then access is denied and the code value is not disclosed.
Just-in-Time Reveal and Post-Expiration Masking
Given current time < (start−E), When the assigned vendor views the appointment, Then the code value is masked and the UI indicates the exact availability time. Given (start−E) ≤ current time ≤ (end+L), When the assigned vendor views the appointment, Then the full code value is revealed. Given current time > (end+L), When any user views the appointment, Then the code value is masked/removed and only a placeholder (e.g., •••• or last-4) is shown; full value is not retrievable via UI or API.
UI Displays Window, Countdown, and Associations
Given an appointment for unit U with lock L, When the vendor views the appointment, Then the UI shows unit identifier, lock name/ID, window start and end times with timezone, and a countdown to start (if inactive) or to expiry (if active). Given the appointment is not confirmed, When the vendor views the appointment, Then the UI shows that code generation is unavailable and no code is visible. Given potential client clock skew up to ±2 minutes, When rendering countdowns, Then the UI syncs to server time and displays countdowns accurate to within ±5 seconds.
Configurable Code Length, Format, and Reuse Policies
Given organization settings define code length N and character set S compatible with the target lock, When generating a code, Then the code conforms to N and S; if incompatible, generation fails with a clear error. Given a no-reuse window of X days on lock L, When generating a new code, Then no code used on L within the past X days is issued again. Given a "disallow-trivial" policy is enabled, When generating numeric codes, Then trivial sequences (e.g., 0000, 1111, 1234, 4321) are excluded from issuance.
Smart Lock Provider Integration Layer
"As a developer, I want a unified integration with multiple smart lock providers so that Timeboxed Codes work consistently regardless of the lock brand installed."
Description

Implement an abstraction layer to integrate with major smart lock ecosystems via API/OAuth, enabling programmatic creation, activation, and revocation of timeboxed codes across different device brands. Map devices to units in FixFlow, detect provider capabilities (e.g., one-time PIN vs. time-bound PIN), and normalize responses/events. Include robust error handling, retries with backoff, webhook ingestion, and health monitoring. Provide sandbox/test mode, credential management with secret rotation, and audit trails for all provider calls to ensure reliable, secure interoperability at scale.

Acceptance Criteria
OAuth Credential Onboarding and Secret Rotation
- Given a provider requiring OAuth 2.0 client credentials When an admin saves credentials in FixFlow Then the credentials are stored encrypted at rest and are not retrievable in plaintext by any user role - Given saved credentials When "Test Connection" is invoked Then a token is obtained and a minimal provider API call succeeds within 5 seconds with HTTP 200 and latency recorded - Given active credentials and a scheduled rotation window When new credentials are provided and activated Then existing tokens continue to work until expiry and no provider calls fail due to credential mismatch during rotation - Given any provider authentication error (e.g., invalid_grant, 401) When detected Then FixFlow marks the integration as Degraded, emits an alert, and blocks new code operations until credentials are remediated
Provider Capability Detection and Normalization
- Given a mapped device and provider account When FixFlow queries provider capabilities Then the response indicates support for time-bound PINs, one-time PINs, max code length, and revocation, and is cached for 24 hours - Given a request to create a timeboxed code for a visit window When the provider supports time-bound PINs Then FixFlow requests a time-bound PIN and returns a normalized payload with fields: code, activation_start_utc, activation_end_utc, one_time=false - Given the provider lacks time-bound PINs but supports one-time PINs When a timeboxed request is made Then FixFlow either returns a 422 capability error or applies a tenant-configured fallback (e.g., single-use on arrival) and sets capability_fallback=true in the response - Given provider-specific errors and payloads When normalized Then error codes and event types conform to the internal schema and incompatible providers are blocked at onboarding with a clear reason
Timeboxed Code Lifecycle (Create, Activate, Expire, Revoke)
- Given a scheduled visit window and a device mapped to the unit When a code is created Then the code is valid only between window_start_utc and window_end_utc; attempts before or after are denied by the provider - Given the visit is canceled before window_start_utc When cancellation is invoked Then the code is revoked within 60 seconds and becomes unusable - Given the activation window has ended When provider supports revocation Then FixFlow revokes the code and confirms revocation within 60 seconds; otherwise marks status=expired - Given a door is opened using the issued code within the window When the event is received Then FixFlow attaches the door-open timestamp and code reference to the related work order timeline entry
Webhook Ingestion and Event Normalization
- Given a configured provider webhook endpoint When a webhook is received Then the request signature is verified per provider spec and invalid signatures are rejected with HTTP 401 - Given duplicate events with the same provider event ID When processed Then FixFlow deduplicates and processes each event exactly once - Given door-open, code-created, code-expired, and code-revoked events When normalized Then events are persisted with unit_id, device_id, work_order_id (if resolvable), event_type, provider, occurred_at_utc, received_at_utc, and payload_hash - Given an event linked to a timeboxed code When processed Then the work order displays an annotated timeline entry within 5 seconds of receipt
Reliability Controls (Retries, Backoff, Idempotency, Circuit Breaker, Health)
- Given a transient provider error (HTTP 429/5xx or network timeout) When creating or revoking a code Then FixFlow retries with exponential backoff and jitter up to 3 attempts and respects provider rate limits - Given a retried request When sent Then an idempotency key ensures no duplicate code is created across retries - Given failures exceed a threshold (e.g., 5 failures in 1 minute) for a provider/device When detected Then a circuit breaker opens for 2 minutes and subsequent calls are short-circuited with a clear error message - Given periodic health checks run per provider every 60 seconds When a provider is unreachable for 3 consecutive checks Then integration status is set to Degraded, alerts are emitted, and status auto-recovers after 2 consecutive successful checks
Sandbox/Test Mode Isolation
- Given an integration configured as Sandbox When creating or revoking codes Then calls are routed to sandbox endpoints/credentials and no actions affect production locks - Given records generated in Sandbox When stored Then all artifacts are labeled environment=sandbox and are excluded from production workflows and analytics by default - Given switching an integration from Sandbox to Production When toggled Then new production credentials must be provided and validated, and no sandbox data is migrated into production
Audit Trails and Redaction
- Given any provider API call (success or failure) When executed Then an immutable audit record is written with timestamp, actor, provider, endpoint, request_id, correlation_id, outcome, and redacted request/response bodies - Given secrets, access tokens, or PIN codes appear in payloads When logged Then sensitive fields are redacted/masked per policy (e.g., codes masked to last 2 digits) - Given an authorized auditor queries audit logs by time range, unit_id, work_order_id, or provider When requested Then results are returned within 2 seconds for the 95th percentile and are exportable as CSV and JSON with proper access controls
Auto-Expiration, Rotation, and Revocation on Schedule Changes
"As a scheduler, I want codes to update automatically when a visit is moved or canceled so that access is always aligned with the latest plan."
Description

Automatically expire codes at window end and revoke them immediately upon cancellation. When appointments are rescheduled, generate a new code tied to the updated window and invalidate the previous one across providers to prevent overlap. Support extend/shorten operations with permission checks and configurable grace periods. Maintain a full change history with timestamps and actors, and synchronize updates to vendor and tenant notifications in real time to minimize access errors and security risks.

Acceptance Criteria
Auto-Expire at Window End with Grace Period
Given a scheduled visit window [start, end] and a configured grace period G minutes When the current time is before end + G Then unlock attempts with the active code succeed and are logged as success events Given the same scheduled visit When the current time reaches or exceeds end + G Then the active code is invalid across all lock providers and unlock attempts are denied And a "code expired" event with ISO 8601 timestamp is attached to the work order And invalidation propagates to all integrated providers within 60 seconds
Immediate Revocation on Cancellation
Given an upcoming appointment with an active entry code When an authorized actor cancels the appointment Then the entry code is revoked across all lock providers within 60 seconds And any subsequent unlock attempts are denied and logged as "denied: canceled" And vendor and tenant receive real-time cancellation notifications including effective revocation time And change history records the cancellation event with actor, timestamp, and prior window
Reschedule Generates New Code; Old Invalidated Without Overlap
Given an appointment with window1 and code1 When the appointment is rescheduled to window2 Then the system generates code2 distinct from code1 and ties it exclusively to window2 And code1 is invalidated across all providers within 60 seconds of reschedule And there is no time window in which code1 and code2 are simultaneously valid And vendor and tenant notifications are updated to show window2 and code2 within 60 seconds And change history records old/new windows, code identifiers, actor, and timestamp
Authorized Extension of Window
Given role-based permissions where only Owner and Property Manager roles may extend windows And an appointment scheduled [start, end] with grace period G When an authorized actor extends end to end′ Then the code validity end shifts to end′ + G and remains invalid outside [start, end′ + G] And updates sync to providers and notifications within 60 seconds When an unauthorized actor attempts the same action Then the system returns a permission error and makes no changes And change history logs actor, old/new end, reason (if provided), and timestamp
Shorten Window With Immediate Enforcement
Given an active appointment [start, end] with grace period G When an authorized actor shortens end to end_s Then the code becomes invalid after end_s + G And if current time is already past end_s + G, revocation completes across providers within 60 seconds And vendor and tenant are notified of the shortened window within 60 seconds And change history records old/new end, actor, timestamp, and reason (if provided)
Door-Open Timestamps Attached and Filtered by Active Window
Given a work order with an associated active code and window [start, end] and grace period G When the door is opened using that code within start..end + G Then a door-open event is appended to the work order with ISO 8601 timestamp, code ID, lock provider, and unit ID When an unlock attempt occurs outside start..end + G Then the attempt is denied and a "denied: outside window" event is logged without opening the door And all events are retrievable via API and UI and show in chronological order
Comprehensive Change History Audit
Given one or more schedule changes (extend, shorten, cancel, reschedule) When a user with permission requests the access change history for the work order Then the system returns an immutable, ordered audit trail including action type, actor identity, old/new windows, old/new code IDs, reasons (if supplied), and timestamps And entries cannot be edited or deleted by any role And the audit trail can be exported as JSON and CSV
Door Event Logging and Work Order Attachment
"As an owner, I want door access events attached to the work order so that I have a clear, auditable record of who entered and when."
Description

Capture door-open/close events from lock providers, correlating each event to the originating code, unit, and work order. Persist timestamped, immutable records and surface them in the work order’s annotated photo-timeline for an auditable chain of custody. Include event metadata (attempted access outside window, failed code entries, manual overrides) and export options (PDF/CSV/API). Provide tamper-evident signatures and retention policies to reduce responsibility disputes and accelerate resolution.

Acceptance Criteria
Event Ingestion and Correlation to Work Order
Given a scheduled visit window exists for unit U and work order WO with a single-use code C issued to vendor V and lock device D When the lock provider emits door_opened and door_closed events for device D using code C Then FixFlow ingests each event within 60 seconds of provider timestamp and records ingestion_latency_ms And each event is correlated to unit U, work order WO, code C, device D, and vendor V And the event record includes: event_id, event_type, provider, device_id, unit_id, work_order_id, code_alias (masked), actor, timestamp_utc (ISO 8601), ingestion_timestamp_utc, outcome And uncorrelated events are flagged with correlation_status="unmatched" and appear in the work order exceptions list
Out-of-Window and Failed Attempt Logging
Given code C is active only during window [Tstart, Tend] for unit U and work order WO When an unlock attempt with code C occurs outside [Tstart, Tend] Then the event is recorded as type=attempt_outside_window with outcome=blocked and no unlock is executed And the attempt is attached to WO and visible in the timeline with a warning badge When an incorrect code is entered N times within 5 minutes Then a failed_code_entry event is recorded with failed_attempts=N and outcome=denied And provider lockout status, if present, is captured as lockout=true When the lock reports a manual override/open by key or thumb-turn Then a manual_override event is recorded with source=mechanical and attached to WO
Immutable, Tamper-Evident Event Storage
Given an event E is persisted Then E is write-once and cannot be updated or deleted via any API or UI And E includes tamper_evident_signature (SHA-256 payload hash and signing certificate fingerprint) And E includes hash_chain_prev linking to the prior event for the same device_id to detect gaps or reordering When any modification attempt is made on E Then the system rejects the operation with 403 and logs a security_audit entry And any administrative correction is stored as a new annotation event linking to E.id without altering E
Work Order Timeline Annotation
Given a work order WO has associated door events When a door_opened or door_closed event is ingested Then a timeline entry is created within 60 seconds in WO’s annotated photo-timeline, ordered chronologically And the entry displays: localized timestamp, event type, unit, device nickname, vendor/visitor label, code_alias (masked), scheduled window correlation (on-time/early/late) And sensitive data (full PIN) is never displayed; only a masked alias is shown And clicking the entry reveals full event metadata and any related photos/notes And exception events (attempt_outside_window, failed_code_entry, manual_override) render with distinct icons and are filterable
Door Event Exports (PDF/CSV/API)
Given a user with role Property Manager or Owner is viewing WO door events When they request an export as PDF or CSV for a chosen date range Then the file is generated within 30 seconds and includes: event_id, timestamp_utc (ISO 8601 with offset), local_time, event_type, outcome, unit_id, work_order_id, device_id, actor, code_alias (masked), provider, tamper_evident_signature, hash_chain_prev And the PDF includes a signature summary page with dataset hash and export certificate fingerprint And the CSV uses UTF-8 encoding, comma delimiter, header row, and CRLF line endings When an API client calls GET /api/v1/work-orders/{id}/door-events with filters (from, to, types[], limit, cursor) Then the API returns 200 with paginated results and an X-Data-Integrity-SHA256 header containing the dataset hash
Retention Policy and Access Control Enforcement
Given the account retention policy is set to 7 years (configurable 1–10 years) for door event records When events reach the retention threshold Then they are purged or archived within 24 hours and a proof_of_deletion manifest (dataset hash, count, period) is stored and exportable And only users with Compliance Admin role can modify the retention policy When the retention policy is updated Then the change is versioned with who/when/why and applies prospectively only And no event can be deleted manually before retention expires; delete attempts return 403 and are audit logged
Just-in-Time Notifications and Visibility
"As a vendor, I want to receive my entry code right before the visit with a clear window countdown so that I can arrive prepared and avoid lockouts."
Description

Deliver secure, role-based notifications that reveal codes to vendors shortly before activation and summarize access windows to tenants and owners. Support configurable channels (in-app, SMS, email), localized content, and masked display after expiration. Include reminders, entry window countdowns, and reschedule alerts. Provide a self-serve view for tenants to see when access is authorized and request presence/permission options as required by policy, improving trust and reducing no-shows.

Acceptance Criteria
Just-in-Time Vendor Code Reveal
Given a scheduled visit with an approved access window and an assigned vendor And an organization-level setting Code Reveal Lead Time = 30 minutes When current time reaches 30 minutes before the window start Then the vendor receives a notification containing the plaintext entry code and access window details via all enabled channels (in-app, SMS, email) And prior to that time the code remains masked everywhere the vendor can view it And the revealed code equals the active timeboxed code tied to the work order and unit And an audit log entry records channel, timestamp, recipient, and reveal event
Role-Based Redaction and Post-Expiration Masking
Given a work order with an active or scheduled timeboxed code When a tenant or owner views any notification or UI related to the visit Then the entry code is never shown in plaintext and is masked for those roles And when a vendor views the code outside the active window it is masked And after the access window ends the code is masked for all roles in UI and message history And no API or export endpoint returns plaintext for non-vendor roles at any time
Multi-Channel Delivery and User Preferences
Given users have per-channel notification preferences (in-app, SMS, email) When notifications are triggered for access window summaries, code reveal, reminders, or reschedules Then messages are sent only on each recipient's enabled channels And no messages are sent on disabled channels And delivery attempts and outcomes are logged per channel per recipient And in-app notifications are always available regardless of SMS/email settings
Localized Content and Correct Time Zones
Given a recipient with locale = es-MX and a property in America/Chicago time zone When an access window summary or reminder is sent Then the message body is localized to Spanish per locale settings And all times are presented in the property's local time zone with clear zone/offset indication And date/time formats match the locale conventions And if a translation key is missing, the message falls back to English while preserving correct times
Reminders and Entry Window Countdown
Given a scheduled visit with reminder offsets configured at 24 hours and 1 hour before window start When the clock reaches each offset Then the system sends reminders to all applicable roles per their channel preferences And the in-app UI shows a live countdown to window start and, once started, to window end with minute-level accuracy And no more than one reminder per configured offset is sent per recipient
Reschedule Alerts and Code Rotation
Given an approved visit is rescheduled to a new access window When the schedule change is saved Then tenants and owners receive localized summaries of the new window per their channel preferences And the vendor is informed that a new code will be revealed at the new reveal time And the prior code is immediately invalidated and masked across all UIs and histories And audit logs capture the reschedule, old/new windows, code rotation, and notifications sent
Tenant Self-Serve Access View and Presence/Permission Options
Given a tenant opens the self-serve access view for an upcoming visit When the page loads Then the tenant sees the authorized access window(s), status, and countdown without any plaintext code And the tenant can select and submit presence/permission options per policy (e.g., Be Present, Enter With Permission, Do Not Enter Without Me) And the submission is stored on the work order with timestamp and tenant identity And if policy requires tenant presence/permission, the vendor does not receive plaintext code until the required option is granted And all affected parties receive notifications of the tenant's selection per their preferences
Offline Provisioning and Sync Reliability
"As a field technician, I want codes to work even if the lock temporarily loses connectivity so that I can complete the job without delays."
Description

Pre-provision timeboxed codes to locks that support offline operation and queue changes for devices currently unreachable. Reconcile state on reconnect, detecting drift (e.g., stale codes) and enforcing authoritative revocations. Implement idempotent operations, monitoring, and alerting for failed syncs, plus fallbacks (e.g., emergency admin code with mandatory incident logging). Validate that door event telemetry is buffered and backfilled to ensure complete audit trails even during connectivity outages.

Acceptance Criteria
Offline Pre-Provisioning to Reachable Lock
Given a scheduled visit window and a reachable offline-capable lock When the visit is scheduled or a work order is created Then a single-use entry code is provisioned to the lock with activation start/end equal to the approved window and the device acknowledges storage Given current time is within the activation window and the code has not yet been used When the code is entered on the lock Then the door unlocks, a door-open event with timestamp is recorded locally, and the code is marked consumed locally Given the activation end time elapses When the code is attempted after the window Then the lock denies entry without requiring connectivity Given the code is revoked before the window starts and the device is reachable When the revocation command is sent Then the device removes the code and denies any future use of it
Queued Provisioning for Unreachable Lock
Given the lock is unreachable at scheduling time When a provisioning operation is issued Then the system enqueues the operation with a unique operation ID, displays device sync status as Pending, and schedules exponential backoff retries Given the device reconnects before the operation TTL When the queue flushes Then only the latest authoritative code set for the visit is applied and superseded operations are dropped; the device state matches the server target Given the operation TTL is exceeded and the visit start is within the alert threshold When the condition is detected Then an alert is sent to the assigned coordinator with device, unit, and work order references and fallback guidance is presented
Drift Detection and Authoritative Reconciliation on Reconnect
Given a previously unreachable lock reconnects When it reports its current code inventory and event counters Then the server computes the diff vs authoritative state and records the comparison Given stale or unauthorized codes are present on the device When reconciliation runs Then removals are issued for non-authorized codes and missing required codes are provisioned; before/after states are logged with timestamps Given conflicts in consumption state exist (e.g., device shows a code consumed that the server shows unconsumed) When reconciliation completes Then the server accepts immutable device event facts while enforcing the authoritative future state and prevents re-provisioning of superseded codes Then a subsequent idempotent replay produces no further changes, confirming convergence
Idempotent Operations and Concurrency Safety
Given each provisioning and revocation carries a unique operation ID and version for the work order and device When the same request is retried or replayed Then the device and server return success without duplicating codes or producing additional side effects Given concurrent schedule updates occur while a device is offline (reschedule, cancel) When the device reconnects Then only the highest-version operation applies and lower versions are ignored with audit entries Given a batch operation partially fails When the operation is retried Then only missing steps are applied and the final device state converges to the server target without duplication
Telemetry Buffering and Backfill During Outages
Given the lock operates offline When a door-open or door-close event occurs Then the device timestamps and buffers the event with a monotonic sequence number Given connectivity is restored When the device syncs Then buffered events are uploaded in order, deduplicated by hash/sequence, and attached to the correct work order using the active code at event time Then the work order timeline displays a complete, gap-free sequence of door events for the visit with origin marked as Backfilled Given the device buffer reaches capacity When additional events occur Then the configured policy (e.g., ring buffer) is applied, an alert is raised, and the count of dropped events is recorded
Emergency Admin Code Fallback with Mandatory Incident Logging
Given a visit is within the emergency threshold and provisioning has not succeeded due to continued device unreachability When an authorized user invokes emergency access Then an admin code is generated that is single-use, limited to a short duration, and does not overlap with visitor/vendor codes Then issuance requires entering reason, approver identity, and work order link; notifications are sent to owner, tenant, and vendor; and all details are audit-logged with timestamps Given the admin code is used or expires When connectivity resumes Then the system auto-revokes the admin code on the device and creates an incident report task that must be completed before the work order can be closed
Monitoring, Metrics, and Alerting for Sync Reliability
Given the system is operating Then metrics are emitted for provisioning success rate, average queue age, retry counts, reconciliation actions, telemetry backfill lag, and emergency code usage, tagged by device and property Given an alert threshold is breached (e.g., >5% failed syncs in 15 minutes or queue age >10 minutes for a critical upcoming visit) When the condition is detected Then alerts are sent to on-call via paging, SMS, and email with affected devices and work orders Given an engineer inspects the reliability dashboard When drilling into an incident Then operation logs show operation IDs, device firmware version, last heartbeat, and reconciliation outcomes Then weekly reports summarize incidents and SLOs are evaluated; acceptance requires ≥99.5% on-time provisioning and ≥99.9% telemetry backfill within 10 minutes

Face Match

Verify the vendor at the door with a quick selfie or ID scan matched to the approved vendor profile, including liveness checks. Unlocks or code reveal only occur on a positive match, protecting tenants and owners from impersonation and fraud.

Requirements

Vendor Face Enrollment & Profile Sync
"As a property manager, I want each vendor’s face enrolled and linked to their profile so that doorstep verification is fast and accurate across all properties."
Description

Establish a verified facial profile for each approved vendor during onboarding. Capture or upload high-resolution face images, perform face detection and quality checks, generate embeddings, and link them to the vendor’s profile, company, and authorized properties/time windows. Support re-enrollment on schedule or trigger (e.g., profile change), human review of low-quality captures, and versioning of face templates. Provide bulk import (CSV/API) and sync updates to the verification service so that doorstep checks are fast and accurate.

Acceptance Criteria
Mobile Selfie Enrollment (Onboarding)
Given an approved vendor is in onboarding and opens the mobile camera capture When the vendor submits a selfie image Then the system detects exactly one face in the frame And the detected face bounding box is at least 200x200 pixels And face pose yaw/pitch/roll are each within ±20 degrees And sharpness score ≥ 0.40 and motion blur score ≤ 0.30 (0–1 scale) And illumination score is between 0.30 and 0.90 (0–1 scale) And occlusion affects ≤ 20% of critical landmarks (eyes, nose, mouth) And the image format is JPEG or PNG and size ≤ 10 MB Then a facial embedding is generated and stored for the vendor And enrollment completes with a success response within 3 seconds at p95 And failures return specific error codes and messages for unmet checks
Headshot File Upload Enrollment
Given an approved vendor uploads a headshot image file during onboarding When the file is validated Then the image shortest side is ≥ 720 pixels and file size is 100 KB–10 MB And the system detects exactly one face with pose within ±20 degrees And quality thresholds for sharpness (≥ 0.40), blur (≤ 0.30), illumination (0.30–0.90), and occlusion (≤ 20%) are met Then a facial embedding is generated and linked to the vendor profile And the system returns a success response including template version = 1 And if any check fails, the system returns actionable guidance (e.g., "too dark", "face not centered") and no template is stored
Profile, Company, Property, and Time-Window Linking
Given a vendor has passed image quality checks and an embedding has been generated When enrollment is finalized Then the face template is linked to the vendor ID, company ID, and selected property IDs And authorization time windows (start/end timestamps and optional weekdays/hours) are recorded And a single template is marked as Active for the vendor And attempting to finalize without at least one authorized property or an open time window returns a validation error And an auditable record is created with actor, timestamp, and linkage details
Scheduled and Triggered Re-enrollment
Given a vendor has an Active face template When the re-enrollment schedule elapses (e.g., 12 months) or a trigger occurs (legal name change, company reassignment, prolonged verification failures) Then the system flags the vendor as "Re-enrollment Required" and notifies via email/SMS/in-app And the previous Active template remains Active until the new template passes checks And upon successful re-enrollment, a new template version is created and set Active And if re-enrollment is not completed within the configurable grace period, the vendor remains with the previous Active template and the status is tracked as Overdue
Human Review Workflow for Low-Quality Captures
Given an enrollment attempt is auto-flagged for low confidence or ambiguous detection When the case is routed to a human reviewer Then the reviewer can Approve, Reject, or Request New Capture with a required reason And approval creates a template and sets status to Complete; rejection provides user-facing guidance and no template is stored And requests for new capture send notifications and reopen the enrollment step And review decisions, reviewer ID, timestamps, and rationales are audit-logged And 90% of review cases are completed within 24 hours
Face Template Versioning and Rollback
Given a vendor has one or more face templates When a new template is created Then the system assigns an incremented version number and metadata (created_at, quality scores, method=capture|upload) And exactly one template is marked Active at any time And an authorized admin can rollback to a prior version, which sets that version Active and deactivates the current one And all version changes are audit-logged and exposed via API/read models
Bulk Import (CSV/API) and Verification Service Sync
Given an admin submits a bulk enrollment via CSV or API with vendor_id, company_id, property_ids, authorization windows, and image URLs/files When the batch is processed Then records are validated; valid rows proceed and invalid rows return row-level errors without blocking others And processing is idempotent using (vendor_id, template_hash) to prevent duplicates And successful templates are created/updated and linked as provided And updates propagate to the verification service within 60 seconds at p95 and 120 seconds max And the verification service acknowledges with 2xx; transient failures are retried with exponential backoff up to 3 attempts before dead-lettering And a completion report summarizes successes, failures, and retry status
Selfie Liveness Verification
"As a vendor, I want a quick, guided selfie check that proves I’m present and real so that I can be verified at the door without delays."
Description

Provide a guided selfie capture flow with passive and active liveness checks (e.g., micro-movements, challenge-response) to detect spoofing attempts such as printed photos, replays, or masks. Perform on-device pre-checks for lighting and face framing, assist with flashlight prompts, and stream to the verification service for final scoring. Return a decision with match and liveness scores, apply configurable thresholds per property, and handle low-connectivity conditions with secure, encrypted retry queues.

Acceptance Criteria
On-Device Pre-Checks: Framing & Lighting
Given a vendor initiates the selfie flow When the camera preview detects a face outside the framing guide or eyes closed Then real-time guidance is shown within 300 ms and the capture button remains disabled And capture is enabled only after the face is centered within ±15% of frame width/height and eyes are detected open for at least 1 continuous second And the preview brightness histogram mean must be ≥ 0.30 for 1 continuous second before capture can start
Selfie Capture and Streaming
Given on-device pre-checks are satisfied When the vendor taps Capture Then the app collects a burst of at least 3 frames over ≤ 2 seconds including one neutral and two micro-movement frames And initial upload/streaming to the verification service begins within 2 seconds of first frame capture using secure transport And if any upload attempt fails, the app retries up to 2 immediate attempts with incremental backoff before deferring to the offline queue
Liveness Verification (Passive + Active)
Given the verification service receives captured frames When passive liveness analysis is performed Then a liveness_score is returned and submissions with liveness_score ≥ property.passive_liveness_threshold (default 0.85) pass passive liveness And if passive liveness is inconclusive, an active challenge is initiated with 2 random prompts (e.g., blink twice, turn head left-right) to be completed within 5 seconds each And active responses produce an active_liveness_score that must be ≥ property.active_liveness_threshold (default 0.80) for a pass And if spoof indicators are detected (e.g., flat surface, repeated frame replay, mask artifacts), the result is Rejected with reason = "spoof_detected"
Match Decision and Property Thresholds
Given the verification service returns match_score, liveness_score(s), and quality flags When property-level thresholds are applied: match_threshold, passive_liveness_threshold, active_liveness_threshold Then the decision is Approved only if match_score ≥ match_threshold and all required liveness thresholds are met and no spoof flags are present And the decision is Retry if image quality is low (e.g., blur, occlusion, low light) or liveness inconclusive, with actionable guidance provided And the decision is Rejected if match_score < match_threshold or spoof flags are present And on Approved, the unlock/code reveal is triggered within 2 seconds; on Retry/Rejected, no unlock occurs
Low Connectivity Handling with Encrypted Retry Queue
Given an upload attempt fails due to timeout or network unavailability When the app defers the submission Then the payload (images/video + metadata) is encrypted at rest using AES-256-GCM with a key stored in the OS hardware-backed keystore and added to a retry queue And the queue retries with exponential backoff starting at 30 seconds up to 10 minutes, for a maximum of 10 attempts And queued items have a 24-hour TTL; upon TTL expiry, the item is securely deleted and marked Failed with reason = "ttl_expired" And upon successful upload, the local encrypted payload is deleted within 5 seconds and the decision flow resumes automatically
Security in Transit and Data Minimization
Given media and metadata are transmitted to the verification service When establishing a connection Then TLS 1.2+ with certificate pinning to the verification host is required; connections failing pinning are aborted and logged And EXIF/location metadata is stripped from all images prior to upload And captured media is stored only in the app sandbox and is not discoverable by the device gallery And access to the selfie flow requires an authenticated session tied to the assigned work order and approved vendor profile
Audit Log and Timeline Entry with Unlock Gating
Given a decision (Approved, Retry, Rejected) is produced When persisting the result Then an audit record is created with vendor_id, property_id, work_order_id, decision, match_score, liveness_scores, thresholds applied, reason codes, attempt_id, timestamps (start/end), device model, and network state And the tenant/owner photo timeline records a watermarked, redacted key frame with annotations (decision + scores) unless policy disables media retention And code reveal/door unlock is strictly contingent on decision = Approved; any other decision must not expose codes or trigger unlock
ID Scan Match Fallback
"As a dispatcher, I want an ID scan fallback that compares to the vendor’s profile so that jobs can continue when selfie verification encounters issues."
Description

Enable scanning of a government ID or company badge as a fallback or secondary factor when selfie verification fails or is unavailable. Extract text via OCR/MRZ/barcode, crop the document portrait, and perform a compliant 1:1 match against the enrolled vendor profile. Redact and watermark stored images, mask sensitive fields (e.g., ID numbers), validate document authenticity signals, and minimize retention. Surface clear pass/fail feedback and route failed attempts to manual review.

Acceptance Criteria
Fallback Trigger and Access Gating at Door
Given a vendor with an active work order within the scheduled window and within the property geofence When selfie verification fails, times out, or the device lacks a usable front camera Then the system offers ID/badge scan as a fallback and suppresses unlock/code reveal until a positive match is achieved Given a vendor initiates ID fallback When the attempt count exceeds 3 within 10 minutes Then further attempts are blocked for 10 minutes and no unlock/code is revealed Given an ID fallback attempt completes with a positive match and the work order is valid When door access is requested Then the app reveals the access code/unlocks within 2 seconds and records the decision in the audit trail Given an ID fallback attempt results in negative, inconclusive, or authenticity-failed outcome When door access is requested Then the app withholds the code/lock, shows "Not verified", and automatically routes the attempt to manual review
ID/Badge Data Capture and Field Extraction
Given a supported government ID (MRZ TD1/TD3) or company badge (PDF417/Code 39/Code 128) When the document is scanned under typical indoor lighting Then front/back images (as applicable) are captured and MRZ/barcodes decode successfully on at least 98% of QA test samples Given a successful scan When OCR/MRZ/barcode parsing completes Then the system extracts full name, document number or employee ID, expiration date (if present), and portrait region, and flags missing required fields Given field extraction occurs When confidence for any required field is below 0.90 Then the attempt is marked inconclusive, access is withheld, and the attempt is routed to manual review
Portrait Crop and 1:1 Face Match Against Enrolled Profile
Given a cropped portrait from the scanned document and the enrolled vendor face template When face quality checks pass (face detected, brightness/blur within acceptable range) Then a 1:1 face match is performed and a similarity score is produced Given a similarity score and quality metrics When the score is greater than or equal to the configured decision threshold (default 0.80) and quality thresholds are met Then the outcome is Positive Match; otherwise the outcome is Negative Match or Inconclusive based on quality Given the default decision threshold When evaluated on the release validation set Then the operating point achieves FAR ≤ 0.1% at TAR ≥ 98%, documented in the model card/release notes
Document Authenticity and Expiry Validation
Given a government ID with MRZ When MRZ lines are parsed Then all MRZ check digits validate and DOB/expiry consistency checks pass; otherwise authenticity fails Given a driver license or badge with PDF417 or other barcode When decoded Then key fields (name, document number) match printed text with Levenshtein distance ≤ 1 and barcode format/signature checks pass if applicable Given a document includes an expiration date When the expiration date is in the past Then the attempt fails authenticity and is routed to manual review Given tampering indicators are detected (e.g., portrait crop mismatch, duplicate barcode across attempts, excessive glare over security zones) When the authenticity score falls below threshold Then the outcome is Authenticity Failed and access is withheld
Redaction, Masking, and Watermarking of Stored Artifacts
Given processing completes When storing any image of the ID/badge Then only a redacted, watermarked copy is stored and all raw images are discarded Given redaction rules When applied to stored artifacts Then the document number is masked except last 4 characters, MRZ is fully redacted, address lines are fully redacted, barcode payloads are not stored, and all EXIF metadata is stripped Given a stored artifact is viewed by an authorized user When zoomed to 200% Then masked fields remain unreadable and the watermark displays attemptId, timestamp (UTC), and vendorId
Data Minimization and Retention Controls
Given an ID scan attempt completes (any outcome) When post-processing finishes Then all raw images and intermediate files are deleted within 5 minutes of the decision Given redacted artifacts and minimal metadata are retained When the default retention policy is active Then artifacts are automatically deleted after 90 days; the retention period is configurable between 7 and 365 days Given the scheduled retention job runs daily When a deletion occurs Then an immutable audit log entry records attemptId, deletion timestamp, retention policy used, and outcome
User Feedback, Unlock Behavior, and Manual Review Routing
Given a positive match and authenticity pass When the attempt completes Then the UI displays "Verified", reveals the access code/unlocks, and an annotated photo-timeline entry is added with redacted images and decision Given a negative, inconclusive, or authenticity-failed outcome When the attempt completes Then the UI displays a clear failure reason, access remains withheld, and a "Request assistance" action is available Given an attempt is routed to manual review When the route is created Then a review task is generated within 30 seconds containing redacted images, extracted fields, match score, authenticity checks, and reasons; notifications are sent to the configured reviewer group Given a manual reviewer selects Approve When the decision is submitted Then a one-time access code is issued, logged, and time-bounded; if Reject, access remains blocked and the work order is flagged for follow-up
Doorstep Verification Flow
"As a tenant, I want to see and confirm who is at my door with real-time verification results so that I feel safe before granting entry."
Description

Deliver a two-sided, at-the-door workflow connecting the scheduled work order, unit, tenant, and vendor. When the vendor marks ‘Arrived,’ trigger the verification sequence and notify the tenant with real-time status. Display vendor name, company, and profile photo to the tenant alongside verification outcome, with clear actions for approve, deny, or request help. Provide edge-case handling for no-answer, timeouts, or mismatches with escalation to support, SMS fallback links for non-app users, and localized UI.

Acceptance Criteria
Vendor Arrival Triggers Verification and Tenant Notification
Given a scheduled work order has an assigned vendor and tenant contact When the vendor taps "Arrived" in the vendor app Then the system starts face-match and liveness checks within 5 seconds And a real-time notification is sent to the tenant within 10 seconds And the tenant view displays vendor name, company, and profile photo with status "Verifying vendor"
Positive Match With Tenant Approval Grants Access
Given the vendor selfie/ID scan passes liveness and matches the approved profile with confidence >= 0.92 And the tenant sees the verification outcome "Verified" When the tenant taps "Approve" Then the one-time access code is revealed or the smart lock is unlocked within 5 seconds And the code remains visible for no more than 60 seconds and is masked on screen exit And an audit entry (timestamp, approver, selfie thumbnail, match score) is appended to the work order timeline
Mismatch or Liveness Failure Blocks Access and Escalates
Given the match confidence is below 0.92 or the liveness check fails When verification completes Then the tenant sees status "Not Verified" And the Approve action is disabled And no access code is revealed and no lock command is issued And the vendor may retry up to 2 times within 10 minutes And on final failure or tenant "Request Help", a support ticket is created with work order, unit, vendor, and failure details and notifications are sent to support and owner within 2 minutes
No-Answer and Timeout Handling
Given a verification is in progress and a tenant notification was sent When the tenant does not act within 3 minutes Then an SMS fallback link is sent to the tenant's verified phone number And if no action is taken within 7 minutes total, the verification session expires And no access is granted And the vendor is notified of the timeout with guidance to contact support And an escalation event is logged to the work order and routed to support
SMS Fallback Web Flow for Non-App Tenants
Given the tenant receives an SMS fallback link When the link is opened Then a secure mobile web page loads over HTTPS within 3 seconds on a 4G connection And the page displays vendor name, company, profile photo, and actions Approve, Deny, Request Help And the link is single-use and expires after 15 minutes or upon completion And the tenant's decision updates the work order in real time and triggers the same access and audit behaviors as in-app
Localized UI for Verification Flow
Given the tenant's preferred language is supported (e.g., English, Spanish) When verification screens and notifications are presented Then all UI strings, CTAs, and system messages are shown in the selected language And date/time and number formats follow locale norms And if the preferred language is unsupported, the UI falls back to English And localization keys are externalized and covered by snapshot tests for supported languages
Real-Time Status Updates and Timeline Audit
Given any verification state change occurs (started, verified, failed, expired, approved, denied) When the state change is emitted by the system Then the tenant view updates within 2 seconds to reflect the new status And the work order timeline appends an immutable entry with state, actor (vendor/tenant/system), ISO 8601 timestamp, and artifacts (selfie thumbnail, match score, reason code) And entries are visible to owner, tenant, and support based on role permissions
Access Control Gatekeeper
"As an owner, I want door unlocks and code reveals to require a successful Face Match so that unauthorized individuals cannot access my properties."
Description

Gate smart lock commands and code reveals on a positive verification result within a configurable time window and geofence. Integrate with supported smart locks and code providers to issue ephemeral, per-visit codes and log all unlock events against the work order. Enforce risk-based rules (e.g., elevate thresholds at night), block repeated failed attempts, and provide an auditable chain linking verification decision to the access event for dispute prevention.

Acceptance Criteria
Unlock Gated by Face Match, Time, Geofence
Given a scheduled visit with a configured start/end time window and geofence radius for the work order And the vendor is assigned to the work order When the vendor completes liveness and face match with score >= the configured threshold And the vendor device location is within the configured geofence And the attempt time is within the scheduled time window Then the system authorizes smart lock commands and access code reveal for this visit And authorization automatically expires after the first successful unlock or at window end, whichever occurs first And attempts outside the time window or geofence are denied with explicit reason codes
Ephemeral Per-Visit Access Code Issuance
Given a successful verification event for a supported lock or code provider When access is authorized for the visit Then generate a unique, single-use access code tied to the work order and vendor And set the code TTL to the configured duration and automatically revoke it after first use or TTL expiry, whichever occurs first And do not reveal the code until verification succeeds; reveal only within the verified vendor session And revoke the code immediately on visit cancellation, access revocation, or lockout
Audit Trail Linking Verification to Access
Given any unlock command is issued or an access code is used When the event is recorded Then persist an append-only log entry containing work order ID, verification event ID, face match score, liveness result, geofence distance, decision outcome, device ID, lock ID, timestamp (UTC), requester identity, and reason code And include a cryptographic hash chain reference to the prior log entry for tamper-evidence And expose read-only queries to retrieve logs by work order, vendor, lock, and time range And include the log entry reference on the work order timeline
Risk-Based Access Elevation at Night
Given the current local time falls within the configured high-risk hours for the property When a vendor attempts verification for access Then increase the required face match threshold to the configured high-risk value And reduce the allowed geofence radius to the configured high-risk radius And require a second factor when the high-risk policy is enabled And deny access if any elevated requirement fails or times out within the configured limit And record the applied risk policy version and parameters in the audit log
Block and Notify on Repeated Failures
Given failed verification attempts are tracked per vendor, device, phone number, and work order When the system detects >= the configured consecutive failures within the configured window Then place the subject into lockout for the configured cooldown duration And deny further verification attempts during lockout with reason "LOCKOUT" And send notifications to the tenant and owner/manager per notification settings And create an alert on the work order with failure count and last attempt metadata
Smart Lock/Provider Integration and Safeguards
Given the target device is on the supported integrations list When sending unlock commands or requesting code issuance Then send idempotent requests signed or authenticated with a unique command ID and enforce configured retries and timeouts And do not execute unlock or reveal codes if the integration returns an error or times out; surface a clear error to the user And queue a retry only within the authorization TTL; expire pending commands after TTL And record the integration request/response IDs and statuses in the audit log
Audit Trail & Photo Timeline
"As a property manager, I want tamper-evident verification records attached to each job so that I can resolve disputes quickly and prove compliance."
Description

Automatically append verification artifacts to the work order’s annotated photo-timeline, including timestamped selfie thumbnails, redacted ID crops, match/liveness scores, decision, actor, and location metadata. Hash and sign records for tamper-evidence, enforce role-based visibility, and enable export for insurance, compliance, or dispute resolution. Provide searchable filters (property, vendor, outcome) and retention hooks aligned with privacy policies.

Acceptance Criteria
Append Verification Artifacts to Photo Timeline
Given a vendor verification (selfie or ID scan) is completed for a work order When the verification decision is produced Then an audit-timeline entry is created within 3 seconds and associated to the correct work order And the entry includes: ISO-8601 UTC timestamp, verification method (Selfie|ID), decision (Approved|Rejected|Manual Review), matchScore (0–100), livenessScore (0–100 or null if method=ID), actorId, actorName, deviceId, geo.lat/geo.lon with accuracyMeters <= 50, and propertyId And the entry includes a 256x256 max selfie thumbnail or a redacted ID crop with ID number, address, MRZ, and barcode redacted And the entry is immutable once written and is assigned a unique monotonic sequence number within the work order timeline
Metadata Validation and Error Handling
Given an audit-timeline entry is created When the system validates the entry Then required fields are present and conform to types and ranges: timestamp valid ISO-8601 UTC not more than 5 minutes in the future; scores within 0–100; latitude -90..90; longitude -180..180; accuracyMeters > 0 And if any required field is missing or out-of-range, the write is rejected, no partial media is stored, and an error telemetry event with reason code is emitted And the timeline for the work order remains consistent with no gaps or duplicates in sequence numbers
Tamper-Evident Hashing and Signing
Given an audit-timeline entry is persisted When the system computes a SHA-256 content hash over the immutable fields and attached media Then the entry stores the hash, the previousEntryHash (for the same work order), and a detached signature produced with the platform signing key And a public verification endpoint returns Valid for the entry and chain when no alteration has occurred And any post-write mutation attempt results in signature verification failure, the write is blocked, and a security alert is logged with entryId and actorId
Role-Based Visibility Enforcement
Given users with roles Tenant, Owner, PropertyManager, Vendor, and Support access the timeline When a user views an audit entry Then field-level visibility is enforced: Tenants and Owners see decision, timestamp, vendor name, selfie thumbnail, and propertyId; they do not see matchScore, livenessScore, deviceId, or precise geo (rounded to 2 decimals) And Vendors see their own entries with scores but never other vendors’ PII; Support sees full fields including deviceId and precise geo; ID crops are always redacted for all roles And unauthorized access attempts are denied with HTTP 403 and are audit-logged with userId, role, and entryId
Export for Insurance/Compliance/Dispute
Given a user with ExportAudit permission selects one or more work orders When the user requests an export Then the system produces within 60 seconds a ZIP package containing: JSONL of audit entries, attached media, a manifest with hashes and signatures, and a human-readable PDF summary And all ID images remain redacted; a verification report includes decision counts and timestamps And the package includes a verification script or instructions that validate signatures offline; the download link expires in 24 hours and is scoped to the requesting org
Search and Filter Audit Records
Given an authorized user opens the audit browser When the user filters by propertyId, vendorId, decision outcome, method, and date range Then results reflect the filters accurately and return the first page within 2 seconds for up to 50,000 matching entries And results are sortable by timestamp and decision; clearing filters returns the unfiltered default view; empty results show a no-data state
Retention and Legal Hold Hooks
Given an organization retention policy (e.g., 24 months) and optional legal holds by work order or property When an audit entry exceeds retention and is not under legal hold Then the system purges media and personal identifiers, retains minimal tombstone metadata (entryId, timestamp, hash), and updates the chain with a purge marker And purged entries are excluded from search and export; a retention audit log records the purge with reason and policyId; legal holds prevent purge until released And the retention job runs daily and reports success/failure metrics
Privacy, Consent & Data Retention
"As a compliance officer, I want explicit consent, retention controls, and auditability for biometric data so that our use of Face Match meets legal and contractual obligations."
Description

Present clear, localized consent for biometric processing, with policy links and just-in-time explanations. Apply region-specific rules (e.g., GDPR, BIPA), data minimization, encryption in transit/at rest, and configurable retention/auto-deletion schedules for biometrics and ID images. Provide admin controls for subject access requests and deletion, audit logs of data actions, and DPA templates to support landlord compliance.

Acceptance Criteria
Localized Biometric Consent Before Capture
Given a vendor initiates Face Match at a property, When the system resolves the applicable jurisdiction and locale (via property address, account settings, and IP as fallback), Then a consent dialog is presented in the user’s language with jurisdiction-specific disclosures (purpose, retention period, rights, and policy links) before any image or biometric is captured. And the dialog requires explicit opt-in (unchecked checkbox plus Confirm) and blocks progression until granted; Decline aborts the flow and prevents unlock/code reveal. And the system records a consent receipt (subject ID, org ID, jurisdiction, consent text hash, policy version, timestamp, IP, device) tied to the session. And accessibility conformance is met (WCAG 2.1 AA) and the text meets a readability threshold (≤ 9th grade). And if consent is withdrawn later, subsequent biometric processing is blocked and a non-biometric verification alternative is offered.
Region-Specific Compliance Enforcement (GDPR, BIPA)
Given the jurisdiction is GDPR, When processing biometric data, Then explicit consent is required and recorded; data minimization is enforced (store face template; transient images automatically purged within 15 minutes unless retention is separately consented); purpose limitation is applied; withdrawal of consent immediately halts processing; and cross-border transfers use approved safeguards (e.g., SCCs) with records. Given the jurisdiction is Illinois (BIPA), When collecting biometrics, Then written consent includes purpose and retention terms; a publicly accessible retention/destruction policy link is displayed; no sale or profit from biometric data occurs; disclosure only with consent or legal requirement; and deletion occurs at the earlier of purpose completion or 3 years after last interaction. And Face Match processing is blocked if required consent artifacts or policies are missing for the detected jurisdiction, with an actionable error surfaced to the user/admin.
Configurable Retention and Auto-Deletion
Given an org admin opens Data Retention settings, When configuring, Then they can set separate retention periods (in days) for biometric templates, selfie images, ID scans, consent receipts, and audit logs, within region-defined min/max bounds. And defaults auto-populate per jurisdiction; the UI displays the effective retention policy and the next scheduled deletion date per data type. And a scheduled job runs daily and deletes eligible records from primary storage within 24 hours of expiration, updates audit logs with counts by type, and marks tombstones for backup purge within 30 days. And deleted biometric/ID data are irrecoverable from search indices and media caches immediately after deletion, and linked workflow records retain only non-biometric metadata. And an exportable deletion report is available for each run, including successes, failures, and retry status.
Subject Access Request (SAR) and Erasure Workflow
Given an authorized org admin submits a SAR for a specific subject, When identity and authorization are verified, Then an export is generated within 7 calendar days containing the subject’s consent receipts, stored biometric templates, ID images, and related audit events, provided in a secure downloadable package (JSON/CSV plus media files) with checksum. When a deletion (erasure) request is submitted and validated, Then all biometric and ID data for the subject are removed from primary stores within 72 hours and scheduled for backup purge within 30 days; completion is confirmed with a deletion receipt and audit entry. And SAR status is trackable (Received, In Progress, Ready, Completed/Denied) with timestamps and reasons for denial if applicable; processing of biometrics halts immediately upon validated erasure/withdrawal requests.
Encryption and Key Management for Biometrics and ID Images
Given biometric or ID data are transmitted, Then TLS 1.2+ with PFS is enforced; plaintext or downgraded connections are rejected; HSTS is enabled. Given biometric or ID data are stored, Then AES-256-GCM encryption at rest is applied; keys are managed in a FIPS-validated KMS with envelope encryption; key rotation occurs at least every 90 days; and access is restricted via service identities with least privilege. And encryption/TLS posture is continuously verified by automated checks; uploads or reads fail closed if cryptographic prerequisites are not met; encryption status is reportable for audits.
Comprehensive Audit Logging of Data Actions
Given any CREATE, READ, UPDATE, EXPORT, DELETE, or CONFIG action on biometric/ID data or retention settings, When the action occurs, Then an append-only, tamper-evident log entry is written capturing actor ID, role, subject ID, action type, resource type, legal basis/consent ID, timestamps, IP/device, and outcome. And audit logs are stored separately from primary data, chained with hashes for integrity, and retained for at least 2 years or per jurisdictional requirement, whichever is longer. And authorized auditors can filter/search/export logs by subject, actor, date range, and action; suspicious patterns (e.g., bulk export or mass deletion) trigger real-time alerts to org owners and are logged.
DPA Templates, Execution, and Enforcement
Given a landlord org without an executed DPA, When attempting to enable Face Match or collect biometrics, Then the system blocks activation and presents jurisdiction-tailored DPA templates with e-sign or upload flows. And upon execution, the signed DPA record (org, signer identity, version, timestamp, file artifact) is stored, versioned, downloadable, and tied to processing records; renewal reminders are sent 30 days before expiry or template update. And DPA status is exposed via UI and API; biometric processing is prevented if DPA is missing or lapsed; all DPA-related events are audit-logged.

NFC Door Tap

Enable tap-to-verify at the entrance using a low-cost NFC tag or smart lock integration. Vendors prove presence with a tap, triggering instant access or code reveal while logging precise arrival time—eliminating keypad misreads and speeding entry.

Requirements

NFC Tag Enrollment & Door Linking
"As a property manager, I want to enroll and link NFC tags to each unit’s door so that vendor taps are accurately tied to the right property and work order."
Description

Provide an admin flow to register and assign NFC tags to specific properties, buildings, units, and doors within FixFlow. Support scanning a tag (UID and NDEF), naming the door, and binding it to active work orders and approved vendor companies. Include bulk enrollment, replacement flow for lost/damaged tags, and tamper-state tracking. Validate uniqueness of tag-door mappings and enforce access policies per unit. Surface enrollment status in the unit profile and allow QR backup for emergency access. This enables reliable, low-cost deployment and ensures that taps are unambiguously tied to the correct entry point and job context.

Acceptance Criteria
Single NFC Tag Enrollment With UID/NDEF Capture and Door Linking
Given an admin is on the NFC Tag Enrollment screen for a selected property, building, unit, and door When the admin taps an unregistered NFC tag and inputs a door name Then the system captures and stores the tag UID and any NDEF payload And validates the tag UID is not already linked to any door in the system; if duplicate, blocks save with an error identifying the existing door And validates the selected door has no active tag; if it does, blocks save with guidance to use the Replacement flow And saves the tag-to-door mapping and door name And updates the Unit Profile to display the door with Active tag and masked UID (last 4 chars) And creates an audit log entry with user, timestamp, door ID, and tag UID
Bulk NFC Tag Enrollment and Conflict Handling
Given an admin starts Bulk Enrollment for a selected property/building When the admin scans multiple NFC tags sequentially and assigns each to a unit/door Then each valid scan is saved with tag UID, NDEF (if present), and door mapping within 2 seconds per tag And the bulk UI displays running counts of Saved, Duplicates, and Conflicts And duplicate tags (already linked elsewhere) and doors with existing active tags are flagged inline and skipped with actionable error messages And the admin can undo the last saved mapping within the current session And upon completion, a summary report (CSV downloadable) lists each tag, door, status, and error (if any)
Lost/Damaged Tag Replacement With History Preservation
Given a door currently has an active NFC tag When an admin selects Replace Tag, chooses a reason (Lost or Damaged), and scans a new NFC tag Then the system deactivates the old tag and prevents it from granting access And transfers the door linkage, access policies, and any active work-order bindings from the old tag to the new tag And preserves a historical record linking old and new tag UIDs with reason and timestamp And updates the Unit Profile to show the new Active tag and the old tag as Replaced And writes an audit log entry for the replacement event
Vendor Access Policy Enforcement During Work-Order Binding
Given a door has an enrolled tag When an admin binds the door/tag to one or more active work orders and selects vendor companies Then only vendors approved for the unit can be selected; unapproved vendors are blocked with a clear message And saving is blocked if any selected work order is not Active And the saved binding persists the list of allowed vendor companies for the door/tag And if a bound work order closes, its binding to the door/tag is automatically removed and logged
Unit Profile Enrollment Status Visibility
Given a unit profile is opened When the unit has one or more doors Then each door row displays: door name, masked tag UID (last 4), tag status (Active/Deactivated/Replaced), tamper state, last updated timestamp, bound work orders count, approved vendors count, and QR backup status And each row includes a Manage action that navigates to enrollment details And data shown matches the latest enrollment records and audit logs
QR Backup Code Generation and Revocation
Given a door has an active NFC tag When an admin generates a QR backup code and sets an expiry window (e.g., 1–72 hours) Then a unique, single-door QR token is created, inherits the door’s access policies, and is displayed for download/print And the QR token can be revoked at any time, after which it is unusable And the Unit Profile shows the QR status (Active/Revoked/Expired) and expiry time And an audit log entry records QR generation and revocation events
Tamper-State Tracking and Alerting
Given a door’s tag supports tamper indication or tamper status is tracked administratively When the tamper state is set to Triggered via scan read or admin update Then the tag’s tamper_state updates to Triggered and is visible in the Unit Profile within 1 minute And an alert is sent to property admins/owners with door, unit, and timestamp details And replacing the tag resets tamper state for the new tag while preserving history for the old tag And tamper state can be cleared only with a required reason and is audit logged
Vendor Tap Verification & Geofenced Presence
"As a vendor, I want to verify my arrival with a quick tap so that FixFlow records my presence and lets me proceed without keypad errors."
Description

Enable vendors to verify on-site arrival by tapping their NFC-capable device to the assigned tag. Capture timestamp, vendor identity, job ID, tag ID, device fingerprint, and approximate location. Validate presence with a tight geofence and door-level mapping, showing immediate confirmation or actionable error. Support offline mode with short-lived, signed challenges cached client-side, auto-syncing upon connection. Prevent duplicate/multiple taps unless configured; allow grace windows relative to appointment time. Write minimal NDEF payloads to support tap-to-open on iOS/Android without requiring app foreground where possible, falling back to deep link if needed. This creates a precise, auditable arrival signal that reduces keypad misreads and disputes.

Acceptance Criteria
On-site NFC Tap with Geofence Confirmation
Given a vendor assigned to a job and within the configured grace window (default -15/+30 minutes), When the vendor taps the assigned NFC tag while within the configured geofence radius (default 10 meters) of the mapped door, Then the system marks arrival, displays a success confirmation within 2 seconds, and logs eventId, timestamp (UTC), jobId, vendorId, tagId, doorId, deviceFingerprint, and location with accuracy. Given a vendor taps a tag mapped to a different door or is outside the geofence radius, When validation runs, Then the system does not mark arrival, shows an actionable error (“Wrong door tag” or “Too far from door”) within 2 seconds, and presents a map link to the correct door. Given a tagId not associated with the job’s property or door, When tapped, Then the system rejects the event with “Tag not assigned” and no arrival logged. Given a vendor not assigned to the job, When they tap a valid tag, Then the system rejects with “Not assigned to job” and logs a security alert. Given the appointment is outside the grace window, When a valid tap occurs, Then the system rejects with “Outside check-in window” unless an override flag is enabled for the job.
Complete, Immutable Arrival Event Logging
Given a successful tap validation, When the event is recorded, Then the system persists non-null fields: eventId (UUID), jobId, vendorId, tagId, doorId, timestamp (ISO-8601 UTC), deviceFingerprint (hashed), location.lat, location.lng, location.accuracyMeters, appPlatform, appVersion, and challengeNonce. Given an arrival event is stored, When the audit log is queried by jobId or vendorId, Then the event is retrievable within 300 ms and is immutable (append-only), with cryptographic signature verification status recorded. Given GPS is unavailable, When the tap occurs, Then the system attempts network/Wi‑Fi location and only accepts if accuracy ≤ 25 meters within 10 seconds of tap; otherwise the event is rejected with “Location unavailable.” Given API export is requested, When exporting events for a date range, Then the exported CSV/JSON includes all above fields and signature verification outcome for each event.
Offline Mode with Short-Lived Signed Challenges
Given the app has pre-fetched a signed challenge for the job/tag (expires in ≤ 15 minutes) and the device is offline, When the vendor taps the tag, Then the app validates locally, records the event with the challengeNonce, shows “Recorded offline” within 2 seconds, and queues for sync. Given the device regains connectivity, When a queued offline event exists, Then the app auto-syncs within 10 seconds, the server verifies signature and geofence, and marks arrival if valid. Given a signed challenge has expired or is missing, When offline tap occurs, Then the app blocks check-in and shows “Offline token expired—connect to proceed.” Given an offline event was already synced, When a replay attempt occurs, Then the server rejects as duplicate (HTTP 409) using idempotency key derived from challengeNonce+vendorId+jobId.
Duplicate Tap Prevention and Configurable Multiple Taps
Given a vendor has already recorded an arrival for a job, When the same vendor taps again within the cooldown window (default 2 minutes), Then the system suppresses a new arrival and displays “Already checked in.” Given job settings allowMultipleTaps=true, When subsequent taps occur after cooldown, Then the system records additional events marked type=“re-tap” without altering the initial arrival timestamp. Given multiple vendors are assigned to the same job, When each vendor taps, Then the system records distinct arrivals per vendor and prevents cross-vendor duplication. Given network retries or user double-taps, When identical payloads are received, Then the system remains idempotent and only one arrival event is stored.
iOS/Android NDEF Tap-to-Open With Fallback Deep Link
Given an NFC tag provisioned with a minimal NDEF payload (≤ 120 bytes) containing a universal/deep link and tokenized tagId, When a vendor taps on iOS with the app not in foreground, Then iOS invokes the universal link to open the app (or Safari fallback) and passes tagId and challenge parameters without requiring the app to be open. Given Android devices with NFC enabled, When the vendor taps, Then the OS routes the NDEF to the app via intent and passes tagId and challenge parameters; if the app is not installed, a web fallback opens with secure authentication. Given universal link association fails, When a tap occurs, Then the system falls back to a custom URL scheme or secure web page that enables check-in after authentication. Given a device/security policy blocks NFC reading, When a tap is attempted, Then the user is guided to open the in-app scanner/deep link manually, preserving the same validation flow.
Access Gating and Code Reveal on Successful Tap
Given a successful arrival validation for the assigned vendor, When the confirmation screen is shown, Then the door access code is revealed (or smart lock integration triggers unlock) within 2 seconds and is masked after 60 seconds of inactivity. Given validation fails, When the vendor attempts to view the access code, Then the code is not revealed and an actionable message explains how to resolve (re-tap at correct door, move closer, or contact support). Given the appointment is outside the configured access window, When a valid tap occurs, Then the system records the tap but withholds the code and displays “Access window closed” unless an override is set.
Security, Anti-Spoofing, and Tag Integrity
Given a tap event, When server-side verification runs, Then the signed challenge must include vendorId, jobId, tagId, issuedAt, and expiresAt and verify against the server’s public key; otherwise the event is rejected. Given a tag clone or mismatched tagId is used, When a tap occurs, Then the system rejects with “Tag mismatch,” records a security alert, and notifies the property manager. Given location data is captured, When evaluating geofence, Then the location must be obtained within 10 seconds of tap and have horizontal accuracy ≤ 25 meters to be considered valid. Given all communications occur, When data is transmitted, Then TLS 1.2+ is enforced, and the NDEF payload contains no PII besides an opaque tokenized link.
Conditional Smart Lock Access Reveal
"As a landlord, I want door access to trigger automatically after a verified tap so that vendors can enter quickly without sharing permanent codes."
Description

Upon successful tap verification and schedule compliance, automatically unlock the door via smart lock APIs or reveal a time-bound, single-use code in-app. Support integrations with common brands (e.g., August, Yale, Schlage, Kwikset, Level) through OAuth/API keys, with per-unit configuration of access mode: auto-unlock, code reveal, or tenant-approval gate. Enforce access conditions (time window, vendor authorization, work order status), and revoke/expire codes automatically post-entry or at window end. Provide fallback guidance if integration fails and log all access actions for audit. This reduces entry friction and eliminates code misreads while maintaining fine-grained control.

Acceptance Criteria
Auto-Unlock on Valid Tap Within Scheduled Window
Given unit A has access mode set to Auto-Unlock and a healthy smart lock integration And work order W is in status Dispatched or In Progress with a scheduled window [start, end] And vendor V assigned to W is authorized When vendor V performs a verified NFC tap at unit A within [start - grace, end + grace] Then the platform sends a single unlock command to the provider API within 1 second And the door unlocks within 5 seconds of tap verification And no access code is revealed to the vendor And an access event is logged with fields: eventType=unlock_success, timestamp (ISO-8601 with ms), unitId, workOrderId, vendorId, provider, method=auto-unlock, arrivalSource=nfc
Single-Use Time-Bound Code Reveal on Valid Tap
Given unit A has access mode set to Code Reveal with a connected keypad-capable provider And a code policy is configured with TTL=30 minutes by default and single-use=true When vendor V performs a verified NFC tap within the scheduled window Then the platform generates or fetches a unique single-use code for unit A And the code is displayed in-app within 3 seconds, masked by default with an explicit Show action And the code expires immediately after first successful use or at window end, whichever occurs first And any subsequent attempts using the expired or used code are rejected by the provider And an access event is logged with fields: eventType=code_revealed, timestamp, unitId, workOrderId, vendorId, provider, codeRef (masked), ttl, method=code
Tenant-Approval Gate Prior to Access
Given unit A has access mode set to Tenant-Approval Gate with a reachable tenant T And work order W has a scheduled window [start, end] When vendor V performs a verified NFC tap within the scheduled window Then tenant T receives an approval request via push or SMS within 5 seconds containing vendor name, unit, and Approve or Deny actions And if tenant T approves within the configurable decision window (default 2 minutes), the configured access action executes immediately (auto-unlock or code reveal) And if tenant T denies or the decision window elapses without response, access is not granted and the vendor is shown a denial or timeout message with next steps And the outcome is logged with fields: eventType=tenant_approval_{approved|denied|timeout}, timestamp, unitId, workOrderId, vendorId, tenantId
Access Conditions Enforcement and Denial Reasons
Given unit A has a scheduled window [start, end], assigned vendor V, and allowed work order statuses {Dispatched, In Progress} And a grace period is configured (default ±10 minutes) When any vendor performs an NFC tap Then access is granted only if the tapping vendor matches V AND current time is within [start - grace, end + grace] AND the work order status is in the allowed set And if any condition fails, no unlock command is sent and no code is revealed And the vendor is shown a specific denial reason code: {outside_window, unauthorized_vendor, invalid_status} And the attempt is logged with fields: eventType=access_denied, reason, timestamp, unitId, workOrderId, vendorId
Automatic Code Revocation and UI Cleanup
Given a single-use code C was revealed for unit A with TTL T When code C is used successfully at the lock OR the scheduled window ends OR TTL T elapses, whichever occurs first Then code C is revoked via the provider API within 30 seconds and marked expired And code C is removed from the vendor’s app view and cannot be copied or reused And any further attempts with code C fail with an explicit expired or invalid response And a revocation event is logged with fields: eventType=code_revoked, reason, timestamp, unitId, workOrderId, vendorId, provider, codeRef (masked)
Provider Connection and Per-Unit Access Mode Configuration
Given an admin connects a supported provider (August, Yale, Schlage, Kwikset, Level) via OAuth or API key Then the connection is validated by retrieving at least one lock resource and its status within 10 seconds And access tokens or keys are stored securely with auto-refresh where applicable And the admin can set per-unit access mode to one of {Auto-Unlock, Code Reveal, Tenant-Approval Gate} and save successfully And invalid credentials or expired tokens produce a visible error and the integration remains disabled And a configuration event is logged with fields: eventType=lock_integration_{connected|failed} or access_mode_updated, timestamp, unitId (if applicable), provider, adminId
Integration Failure Fallback and Retry Controls
Given a vendor performs a verified NFC tap and the access mode requires a provider API call And the initial provider API call fails or times out Then the system retries up to 2 times with exponential backoff not exceeding 10 seconds total And if all retries fail, the vendor is shown clear fallback guidance including: verify schedule, contact tenant or property manager, and request manual entry And no duplicate unlock or code generation occurs beyond the retry limit And the failure and guidance display are logged with fields: eventType=access_failure, errorClass, attempts, timestamp, unitId, workOrderId, vendorId, provider
Audit Log & Entry Photo Prompt
"As an owner, I want a timestamped tap event and entry photo logged automatically so that I have a defensible record of when and how access occurred."
Description

Automatically create an immutable event entry upon tap including timestamps, identity, geofence result, and access outcome, appended to the work order’s timeline. Prompt the vendor to capture an entryway photo immediately after access to confirm condition-at-entry. Store media with unit, door, and job metadata, and generate a concise, exportable photo-timeline for owners and tenants. Expose APIs and UI components to filter by event type (tap, unlock, code reveal) and support compliance downloads for disputes and insurance. This delivers verifiable, annotated records that reduce responsibility disputes and improve transparency.

Acceptance Criteria
Create Immutable Audit Event on NFC Tap
- Given a verified vendor taps a registered NFC tag linked to a work order and door within the geofence radius, When the tap is processed, Then the system creates a single audit event with fields: eventId, workOrderId, unitId, doorId, vendorId, nfcTagId or lockId, tapTimestamp (ISO 8601 with timezone), geofenceResult (inside|outside|unknown), accessOutcome (unlocked|code_revealed|denied), and appVersion. - And the audit event is appended to the work order timeline in chronological order and is visible in the UI within 2 seconds. - And the event is immutable: any update or delete attempt returns 403 and is logged to a security audit trail with actor and reason. - And repeated taps from the same vendor within 10 seconds against the same door are deduplicated into a single event with a duplicateTapCount incremented.
Geofence Validation and Access Control
- Given device location accuracy ≤ 50 meters is available, When a tap occurs inside a configurable geofence radius (default 50m) of the door, Then geofenceResult=inside and access can proceed. - When a tap occurs outside the radius or location is unavailable, Then geofenceResult is set to outside or unknown respectively, accessOutcome=denied, and code/unlock is not revealed. - Then the calculated distance (in meters) and GPS accuracy are stored in the event metadata. - And all deny decisions produce an audit event visible on the timeline with a clear user-facing reason.
Immediate Entry Photo Prompt After Access
- Given accessOutcome is unlocked or code_revealed, When the vendor proceeds past entry, Then a blocking prompt requires capturing at least one entryway photo within 60 seconds before "Start Work" can be confirmed. - When the vendor attempts to skip, Then a mandatory reason is required and logged; skip is permitted only if the user has the required role permission. - Then the captured photo is time-stamped, geotagged when available, and associated with workOrderId, unitId, doorId, vendorId, and the originating accessEventId. - And uploads succeed within 10 seconds on stable connectivity; if offline, the photo is queued, shows "pending upload" in the timeline, and auto-uploads within 5 minutes of connectivity without creating duplicates.
Metadata Association and Storage Integrity
- Given an entry photo is captured, When it is uploaded, Then the system stores it with metadata: workOrderId, unitId, doorId, vendorId, captureTimestamp, fileSize, mimeType, checksumSha256, deviceId, and accessEventId. - Then media access URLs are short-lived (≤15 minutes), role-gated, and do not expose PII in the path. - When checksum verification fails, Then the upload is retried up to 3 times and on final failure an error event is added to the timeline with remediation guidance. - And vendor-initiated deletes are blocked; owner/admin soft-deletes retain the timeline entry with media redacted and a removedByRole flag.
Annotated, Exportable Photo-Timeline
- Given a work order has tap/access events and photos, When an owner or tenant requests an export, Then the system generates a timeline sorted by timestamp with annotations: event type, timestamp (local and UTC), identity, geofenceResult, accessOutcome, and photo captions. - Then exports are available as PDF and JSON within 10 seconds for timelines ≤100 events and ≤50 photos; larger exports stream with visible progress. - And each export includes a summary page (workOrderId, property/unit, date range) and a manifest containing SHA-256 checksums of included media. - When the export is downloaded, Then an access log event is recorded and the package remains retrievable for 30 days.
API and UI Filtering by Event Type and Date
- Given timeline data exists, When a user filters by event type (tap, unlock, code_reveal, photo, error) and date range, Then the UI returns only matching entries within 500ms for ≤200 events. - When calling GET /work-orders/{id}/timeline with eventTypes, from, to, page, and pageSize, Then the API returns results sorted ascending by timestamp with totalCount and stable pagination. - Then unsupported parameters yield 400 with structured error details; empty results return 200 with an empty array. - And permissions enforce: vendors see only their events/media; owners/managers see all; tenants see redacted fields per policy.
Access Outcome Consistency with Smart Lock and Code Reveal
- Given an eligible tap inside geofence from a verified vendor, When the smart lock confirms unlock, Then accessOutcome=unlocked and the lock response timestamp is recorded. - When a code is required instead, Then the code is revealed within 2 seconds, accessOutcome=code_revealed, and the reveal is masked in logs except to authorized roles. - When the lock times out or errors, Then accessOutcome=denied with errorCode, user-facing guidance is shown, and the event is recorded. - Then all access outcomes appear consistently on mobile and web within 5 seconds and include a correlationId linking to the lock transaction; manual owner overrides are recorded as distinct events linked via parentEventId.
Security & Anti-Fraud Controls
"As a property manager, I want strong anti-fraud measures on tap verification so that only authorized vendors gain access and audit trails are trustworthy."
Description

Implement safeguards to prevent spoofing and misuse: cryptographic challenge-response embedded in deep links, server-side verification of tag IDs, rate-limiting for taps per device, and detection of impossible travel or repeated off-geo attempts. Support optional encrypted NDEF records and tag tamper seals, with admin alerts when tags are moved or repeatedly fail geofence. Mask sensitive door codes, restrict screenshot, and auto-expire tokens. Maintain least-privilege scopes for lock integrations and rotate credentials. Log security events to a dedicated stream with alerting policies. These controls preserve trust while enabling frictionless entry.

Acceptance Criteria
Challenge-Response Tap Validation
Given a registered NFC tag (tagId) assigned to a unit and a vendor authenticated in FixFlow When the vendor taps and opens the signed deep link within 30 seconds Then the server verifies tagId ownership, validates the cryptographic signature and nonce freshness, and records arrival with an RFC3339 timestamp to the second Given any replay of a previously used or expired nonce When the deep link is invoked Then the server returns 401 Unauthorized, no access code is revealed, and a security event is logged with reason=replay Given a tagId not registered to the property/unit When a tap is attempted Then the server returns 403 Forbidden and no arrival is recorded
Tap Rate Limiting and Abuse Prevention
Given a device has made 3 or more tap attempts within 60 seconds for the same property When an additional tap occurs Then the server responds 429 Too Many Requests with Retry-After=60s and logs reason=rate_limit_device Given a tag has 10 successful validations in a rolling 60-minute window When an 11th validation is requested Then validation is blocked, the server responds 403, and an alert event is created with reason=rate_limit_tag Given throttled requests occur When the cooling period elapses Then normal validation resumes and subsequent taps are processed successfully
Geofence Compliance and Impossible Travel Detection
Given the device location at tap time is unavailable or more than 50 meters from the property's geofence centroid When a tap validation is requested Then validation is denied with 403, outcome=off_geo, and the attempt is logged Given the last verified tap and the current tap imply a speed greater than 200 km/h between locations When the current tap is attempted Then validation is denied with 403, outcome=impossible_travel, and the attempt is logged Given 3 off-geo attempts from the same device within 10 minutes When the next off-geo attempt occurs within that window Then an admin alert is sent and further validations from that device for the property are suspended for 15 minutes
Encrypted NDEF and Tamper-Seal Enforcement
Given a tag is configured for encrypted NDEF When it is scanned Then the NDEF payload is ciphertext with no plaintext secrets, the server successfully decrypts and validates integrity, and altered ciphertext fails validation Given a tamper-seal capable tag reports state=Open When a tap occurs Then validation is blocked, a tamper alert is issued to admins, and the tag is flagged for replacement Given a tag is not configured for encryption When it is scanned Then no secret tokens are present in plaintext NDEF, and authorization still requires online challenge-response
Sensitive Code Protection and Token Expiry
Given a vendor passes validation When the door code is displayed Then it is masked by default and requires press-and-hold to reveal for up to 15 seconds before auto-hide, with copy/share/paste disabled Given the mobile app code screen is visible When a screenshot or screen recording is attempted Then the app prevents capture using OS secure flags and no image is saved Given an access token or code reveal link is issued When 5 minutes elapse or it is used once (whichever comes first) Then the token expires and subsequent requests return 401 Unauthorized
Least-Privilege Lock Integration and Credential Rotation
Given a smart lock integration is enabled When scopes are granted Then they are limited to the specific lock's read_status and unlock actions only, with access tokens expiring in 10 minutes or less Given stored integration credentials reach 90 days of age When the rotation job runs Then credentials are rotated automatically, old credentials are revoked, and no unlocks can be performed with revoked credentials Given a vendor is removed from a job When they attempt to unlock via the integration Then the server denies the request with 403 and logs reason=permission_revoked
Security Event Logging and Admin Alerting
Given any security-relevant action (challenge pass/fail, rate-limit, off-geo, tamper, code reveal, lock API call) When it occurs Then a structured event with tenantId, propertyId, tagId, deviceId, reason, outcome, and timestamp is emitted to the security stream within 2 seconds 99% of the time and retained for 365 days Given more than 5 off-geo attempts from the same device within 10 minutes or a tamper state=Open When detected Then an admin alert is sent via email and push within 60 seconds including property, tagId, deviceId, and last known location Given a tag is scanned at locations over 100 meters apart within 1 hour When detected Then an alert with reason=possible_tag_move is generated and the tag is marked under review
Admin Configuration & Notifications
"As a small property manager, I want configurable policies and notifications so that access aligns with my workflows and stakeholders stay informed."
Description

Provide configuration screens to set per-unit access policies (NFC-only, NFC+auto-unlock, NFC+code reveal, approval required), schedule windows, vendor eligibility, and notification preferences. Send real-time alerts to tenants, owners, and managers on key events: vendor arrived (tap), access granted/denied, code revealed, and missed arrival within a defined window. Support SMS, push, and email channels with rate control and quiet hours. Include reporting widgets for arrival SLA, tap-to-entry time, and failed access reasons. This ensures the feature aligns with stakeholder preferences and operational SLAs.

Acceptance Criteria
Configure Per-Unit Access Policies
Given an admin opens Unit A's Access Policy settings When they select "NFC-only" and save Then the system disables auto-unlock and code reveal for Unit A and persists the setting Given an admin selects "NFC + auto-unlock" and saves When an eligible vendor taps within the active schedule Then the door unlock command is issued within 2 seconds and the access event is logged with vendor, unit, and timestamp Given an admin selects "NFC + code reveal" with code TTL set to 10 minutes and saves When an eligible vendor taps within the active schedule Then a one-time code is revealed to the vendor within 2 seconds and expires exactly 10 minutes after reveal Given an admin selects "Approval required" and sets fallback policy "auto-unlock" upon approval When a vendor taps Then an approval request is sent to the designated approver and no access is granted until approval is recorded And upon approval within 15 minutes, the door auto-unlocks on next tap and the approval is audit logged And upon rejection, access is denied and a denial notification is sent Given the admin revisits Unit A settings When the page is reloaded Then the last saved policy values are displayed accurately
Schedule Windows Enforcement
Given Unit A has schedule windows Mon–Fri 08:00–18:00 in America/New_York When a vendor taps at 19:05 local time Then access is denied and the event reason "outside schedule window" is logged and notified per preferences Given the manager creates a one-time override 17:30–20:00 for today When the vendor taps at 19:05 local time Then access follows the unit's policy and the override is recorded with creator, scope, and TTL Given a daylight saving time transition occurs When a vendor taps during the configured 08:00–18:00 window Then enforcement uses local wall time correctly and no false denials occur Given an admin edits the schedule window and saves When the vendor taps after the change Then the updated schedule is enforced immediately without service restart
Vendor Eligibility Validation on Tap
Given Unit A eligibility is restricted to VendorCo X and role "Plumber" with an active work order When a technician from VendorCo Y taps Then access is denied and the reason "ineligible vendor" is logged and notified Given a technician from VendorCo X with role "Plumber" taps without an active work order for Unit A Then access is denied and the reason "no active work order" is logged and notified Given the admin adds VendorCo X to eligibility and saves When the same technician taps again within 1 minute Then the new rule is applied immediately and access proceeds per unit policy Given the admin removes a technician's eligibility When that technician taps thereafter Then access is denied and the reason "revoked eligibility" is logged
Real-Time Multi-Channel Notifications with Quiet Hours and Rate Control
Given tenant, owner, and manager have notification preferences configured for "vendor arrived", "access granted", "access denied", "code revealed", and "missed arrival" When the corresponding event occurs Then recipients receive notifications via their selected channels (SMS, push, email) within 5 seconds of the event timestamp Given a recipient has quiet hours set 22:00–07:00 local time When an event occurs during quiet hours Then notifications for that recipient are suppressed and queued and a single summary is sent within 5 minutes after quiet hours end Given rate limit is set to 3 notifications per 10 minutes per recipient per channel When 5 events occur for the same recipient and channel within 10 minutes outside quiet hours Then only the first 3 are delivered immediately and the remaining 2 are suppressed with a "rate-limited" log entry Given a push notification fails due to device unreachable When fallback to SMS is enabled for that recipient Then an SMS is sent within 10 seconds and the failure/fallback is audit logged
Missed Arrival Detection and Alerts
Given a job for Unit A has an arrival window 14:00–15:00 When no vendor NFC tap is recorded by 15:00 Then a "missed arrival" event is generated at 15:01 and notifications are sent to the manager and owner per preferences Given a grace period of 10 minutes is configured When the vendor taps at 15:07 Then the job is marked "late arrival" instead of "missed", notifications are updated accordingly, and tap-to-arrival delay is recorded Given the vendor taps at 15:20 (outside grace) Then the job remains "missed arrival" and the late tap is logged without granting access unless manually overridden Given the arrival window is updated during an active job When the window ends Then missed/late evaluation uses the latest saved window configuration
Secure Code Reveal Workflow
Given Unit A policy is "NFC + code reveal" and the vendor is eligible and within schedule When the vendor taps and authenticates with their FixFlow account Then the code screen displays only the last 2 digits masked until the vendor taps "Reveal", after which the full code is shown for up to 10 minutes Given the code TTL is 10 minutes When 10 minutes elapse after reveal Then the code is hidden and unusable and any further attempts require a new NFC tap Given a code has been revealed When notifications are enabled for "code revealed" Then the manager receives a notification containing unit and vendor identifiers but not the full code Given an unauthorized user attempts to access the code URL without a successful NFC tap within the last 2 minutes Then access is denied and the attempt is audit logged
Reporting Widgets for SLA, Tap-to-Entry, and Failed Access Reasons
Given there are access and notification events across the last 30 days When the "Arrival SLA" widget is viewed with SLA threshold 60 minutes Then it displays the percentage of jobs with first tap within 60 minutes of scheduled start matching raw event calculations within ±1% Given the "Tap-to-Entry Time" widget is viewed When filtering by property, unit, vendor, and date range Then median and 90th percentile times match underlying event data within ±1% and update within 5 seconds of filter change Given the "Failed Access Reasons" widget is viewed When selecting a date range Then the top 5 reasons (e.g., outside window, ineligible vendor, approval pending, code expired, lock offline) are shown with counts matching event logs within ±1% Given the user clicks "Export CSV" on any widget When the download completes Then the file includes all data points visible under current filters with timestamps in ISO 8601 and correct timezone

Geofence Window

Activate access only when the vendor’s device is within a defined radius and scheduled time window. Blocks early/late entry, prompts rescheduling on missed windows, and reduces disputes over unannounced access.

Requirements

Geofence Radius & Location Setup
"As a property manager, I want to define and save a precise geofence for each work order so that access control and audit events are tied to the exact location of service."
Description

Allow owners/managers to configure a precise geofence per work order using the unit’s verified address and an adjustable map pin with radius (e.g., 50–200 meters). Support multi-unit properties by saving building/entrance-specific geofences and snapping to parcel boundaries when available. Validate address to coordinates, prevent overly small or excessively large radii, and store a read-only snapshot of the geofence with the job to preserve audit integrity if the property record changes later. Integrate with FixFlow’s job creation flow, exposing a simple map UI and API to read/write geofence settings, and defaulting from property templates. Expected outcome: accurate, repeatable location boundaries that anchor access control and downstream logging.

Acceptance Criteria
Radius Limits and Map Pin Adjustment
Given a job is being created and the geofence map is shown When the user drags the map pin Then the pin coordinates update and the circular geofence rerenders centered on the new position in real time And when the user sets the radius below 50 m or above 200 m Then an inline validation error displays "Radius must be 50–200 m" and Save is disabled And when the radius is within 50–200 m inclusive Then the error clears and Save is enabled
Address Geocoding Validation and Manual Override
Given a unit with a verified address is selected When geocoding succeeds with confidence ≥ 0.8 Then the pin auto-centers on the returned coordinates and the address is marked "Validated" When geocoding fails or confidence < 0.8 Then an error displays and Save is disabled until the user places the pin manually and checks "Use manual pin" confirmation Then the system stores validation_method as "geocoded" or "manual" accordingly
Parcel Boundary Snap Option
Given parcel boundary data exists for the property When the user toggles "Snap to parcel" Then the geofence shape changes to the parcel polygon, radius control is hidden, and shape_type is set to "parcel" When parcel boundary data is unavailable Then the toggle is hidden and the geofence remains a circle Then saving stores polygon vertices (≥ 3 points) and parcel_id for parcel shape; for circle, store center and radius only
Multi-Unit Entrance-Specific Geofences
Given a property with multiple entrances has saved entrance-specific geofences When a unit tied to Entrance B is selected Then the geofence defaults to the Entrance B template values (shape, center/polygon, radius) And the user can select a different entrance template from a dropdown and the map updates accordingly When the user selects "Save as entrance template" on save Then the entrance template is created/updated and will default for future jobs for that entrance
API Read/Write Contract and Validation
Given the API client requests GET /jobs/{id}/geofence Then the response returns 200 with fields: shape_type ("circle"|"parcel"), center {lat,lng} when circle, radius_m when circle, polygon [{lat,lng}] when parcel, parcel_id (optional), validation_method, created_at, updated_at When the client PUTs invalid data (e.g., radius_m < 50 or > 200 for circle, missing polygon for parcel) Then the API responds 400 with a machine-readable error code and field-level messages When the client PUTs valid data Then the API responds 200 and persists the geofence, which is retrievable via GET with identical values
Read-Only Geofence Snapshot on Job
Given a job geofence is set and the job is saved Then a snapshot record is stored with all geofence parameters and a hash, and is immutable (read-only) When a user attempts to modify the job geofence after snapshot creation Then the UI prevents changes and the API returns 403 unless a new job version is created When the property-level geofence/template is later modified Then the existing job’s snapshot remains unchanged
Job Creation Flow Defaulting and Gating
Given geofence is enabled for the account and a new job is created When the geofence step loads Then it defaults to the unit’s entrance template if present, else geocoded center with a default radius of 100 m And the Continue/Save button is disabled until address is validated or manual override is confirmed and the radius/shape is valid When the user saves the geofence Then the job creation flow proceeds and the saved geofence is available via API and UI on the job detail
Schedule-Bound Access Enforcement
"As a vendor, I want access instructions to unlock only when I’m at the property during my scheduled window so that I can enter compliantly and avoid disputes."
Description

Gate the release of access instructions (e.g., lockbox code, contact details, entry notes) behind simultaneous geofence presence and scheduled time window checks. Enforce early/late entry blocks with configurable grace periods, and display in-app prompts for "on my way" and "arrived" events that confirm location and time. Trigger real-time notifications to tenants/owners when a vendor arrives within the allowed window, and block viewing of sensitive details when outside it. Integrate with existing scheduling and notifications services, support webhooks for third-party access providers, and log all allow/deny decisions for auditability. Expected outcome: access occurs only at the right place and time, reducing unannounced entry and disputes.

Acceptance Criteria
Release Access Instructions Within Geofence and Allowed Window
Given a scheduled job with startTime, endTime, earlyGraceMinutes, lateGraceMinutes, geofenceRadiusMeters, and an assigned vendor And the vendor’s device reports GPS with horizontalAccuracy <= 50 meters When current time is >= (startTime - earlyGraceMinutes) and <= (endTime + lateGraceMinutes) And the device location is within geofenceRadiusMeters of the job location Then the app un-masks access instructions (lockbox code, contacts, entry notes) for the vendor And an ALLOW decision is recorded with timestamp (UTC), lat/long, accuracy, deviceId, jobId, windowId, and ruleVersion
Block Early Entry and Display Countdown
Given a scheduled job with startTime, earlyGraceMinutes, and geofenceRadiusMeters And the vendor’s device location is within geofenceRadiusMeters When current time < (startTime - earlyGraceMinutes) Then the app keeps sensitive details masked and displays a "Too early" message with a countdown to (startTime - earlyGraceMinutes) And a DENY decision with reason EARLY_TIME is logged with timestamp (UTC), lat/long, accuracy, jobId, windowId And no tenant/owner notifications are sent
Handle Late Arrival with Reschedule Prompt
Given a scheduled job with endTime and lateGraceMinutes When current time > (endTime + lateGraceMinutes) And the vendor attempts to view access instructions Then the app blocks sensitive details and displays a reschedule prompt with next available slots from the scheduling service And a DENY decision with reason LATE_TIME is logged with timestamp (UTC), vendorId, jobId, windowId And upon vendor submission of a new time, a reschedule request is sent to the scheduling service and the UI reflects pending confirmation
On My Way and Arrived Event Confirmation
Given a scheduled job with a defined location, geofenceRadiusMeters, and time window When the vendor taps "On My Way" Then the app records an ON_MY_WAY event with timestamp (UTC), current coarse location (lat/long), and estimated travel time And when the vendor taps "Arrived" Then the app verifies the device is within geofenceRadiusMeters and records an ARRIVED event with timestamp (UTC) and precise location And if the device is outside the geofence, the ARRIVED action is rejected with an error message and access instructions remain masked
Real-time Arrival Notifications Within Allowed Window
Given an ARRIVED event is recorded and both time-window and geofence checks have passed When the ARRIVED event is saved Then tenant and owner receive notifications via the existing notification service within 10 seconds containing vendor name, job address, and arrival timestamp And notification delivery failures trigger up to 3 retries with exponential backoff and are logged in the job timeline And duplicate notifications for the same ARRIVED event are suppressed using an idempotency key
Third-Party Access Provider Webhook on Allow
Given a third-party access provider webhook endpoint is configured for the job/property When an ALLOW decision is made to release access instructions Then the system sends an HTTP POST to the endpoint with a signed JSON payload including decisionId, jobId, vendorId, eventType=ACCESS_ALLOWED, timestamp (UTC), lat/long, window details, and ruleVersion And the request includes HMAC-SHA256 signature and Idempotency-Key headers And HTTP 5xx responses are retried with exponential backoff up to 5 times; HTTP 4xx responses are not retried And all attempts and outcomes (success/failure) are logged in the audit trail
Comprehensive Allow/Deny Audit Trail
Given any access decision (allow or deny) is evaluated When the decision is finalized Then an immutable audit entry is created with decisionType, reasonCode, timestamp (UTC), evaluator inputs (startTime, endTime, earlyGraceMinutes, lateGraceMinutes, geofenceRadiusMeters), device location and accuracy, user/device identifiers, jobId, windowId, correlationId, and ruleVersion And audit entries are visible in the job timeline to authorized roles and exportable as CSV and JSON And all timestamps are stored in UTC and presented in the property’s timezone in the UI
Device Verification & Consent Binding
"As a vendor, I want to securely link my device to a work order so that location checks are permitted only for that job and my access is recognized as legitimate."
Description

Require vendors to bind a specific mobile device to the work order prior to the visit using a secure sign-in plus second factor, and capture explicit consent for job-scoped location checks. Generate a short-lived device token tied to the job, rotating as needed, and prevent access from unbound devices. Provide clear disclosures about location usage limited to the scheduled window. Integrate with FixFlow’s vendor app authentication, MDM-compatible device IDs where available, and fraud safeguards against emulator/VM use. Expected outcome: trusted device identity and compliant location permissions that underpin geofence enforcement.

Acceptance Criteria
Device Binding with SSO + Second Factor
Given a vendor is signed in to the FixFlow Vendor App and has an assigned work order, When the vendor opens the work order prior to the visit, Then the app requires device binding that completes only after a successful second factor challenge (OTP/SMS/push or authenticator) and platform attestation completes, And a device-binding record is created containing jobId, vendorId, deviceId, attestationResult=pass, timestamp, and bindingStatus=bound, And the device cannot access job-scoped resources until bindingStatus=bound.
Explicit, Job-Scoped Location Consent
Given a vendor is completing device binding for a specific work order, When the consent screen is displayed, Then the disclosure states purposes (geofence enforcement), data collected (coarse/fine location), and temporal scope (scheduled window start to end plus 10-minute grace), and provides a privacy policy link, And the vendor must select Agree to proceed or Decline to exit binding, And on Agree the system stores consent with jobId, vendorId, deviceId, timestamp, scopeWindow, and a hash of the consent text shown, And on Decline, access to job-scoped resources remains blocked and rescheduling is offered, And automated tests verify no location APIs are invoked by the app for this job outside the consented window.
Block Access from Unbound Devices
Given a device is not bound to the job or consent is not recorded, When the device requests job-scoped actions (view exact address, reveal lock code, start job check-in, upload timeline photos, or mark arrival), Then the API responds 403 with reason=device_not_bound (or consent_missing), And the app displays a binding/consent prompt with a direct CTA to complete binding, And the event is logged with device fingerprint and IP, And no secret material (e.g., lock codes) is returned in the response body or logs.
Short-Lived, Device-Bound Job Token Rotation
Given a device is bound and consented for a job within its scheduled window, When the device requests a job access token, Then the server issues a device-bound token with TTL=20 minutes that is cryptographically bound to the device key and includes jobId, vendorId, deviceId, and window bounds, And the app rotates the token no later than 5 minutes before expiry, And tokens are rejected if presented from a different device (replay test fails), after consent revocation, or after window end plus 10-minute grace, And all job APIs require a valid device-bound token and return 401 token_invalid on failure.
Fraud/Tamper Safeguards (Emulator/VM/Root/Jailbreak)
Given the vendor app is running in an untrusted environment (emulator/VM/root/jailbreak/debugger detected or Play Integrity/App Attest verdict fails), When device binding is attempted, Then binding is blocked with error=env_untrusted and guidance to use a compliant device, And the event is logged with reason codes and signal details, And only an admin with explicit, time-bound waiver can override to allow a single visit, with the override recorded and visible on the job audit trail.
MDM-Compatible Device Identification
Given the vendor device may be MDM-enrolled, When collecting a device identifier for binding, Then the system prefers MDM-exposed device identifiers where available, else uses platform-appropriate attested IDs (e.g., iOS App Attest key ID + DeviceCheck token; Android Play Integrity + app-scoped key), And the app generates a persistent, app-scoped DeviceKey stored in Secure Enclave/StrongBox; IMEI/MAC are not collected, And identifiers are salted and hashed server-side and linked to the jobId, And uninstall/reinstall resets the app-scoped ID (unless MDM provides a stable ID), which forces re-binding before access.
Missed Window Handling and Reschedule Prompt
Given the scheduled start time has passed and the vendor has not completed device binding and/or consent, When 5 minutes elapse past the scheduled start, Then access to job-scoped resources remains disabled, And the system sends notifications to the vendor (push/in-app) and the resident/owner (per notification preferences) prompting rescheduling, And the job timeline records status=missed_window with reason=binding_incomplete, And future attempts to access the job require selection of a new time window before binding can proceed.
Missed Window Rescheduling & Alerts
"As a tenant, I want automatic rescheduling when a vendor misses the window so that I don’t have to chase updates and can quickly secure a new appointment."
Description

Detect missed geofence-time windows and automatically prompt the vendor to propose new times within owner/tenant availability constraints. Offer one-tap rescheduling options, collect tenant confirmation, and update all stakeholders via push/SMS/email. Apply business rules for SLAs (e.g., auto-escalate after N misses), and synchronize new windows with the geofence enforcement layer. Provide dashboard indicators and reporting for missed and rescheduled visits. Expected outcome: faster recovery from failed visits and reduced coordinator workload.

Acceptance Criteria
Missed Window Detection Trigger
Given a scheduled access window with defined start/end times and an active geofence radius, When the end time passes and no vendor “Arrived” event was recorded within the geofence, Then mark the visit as "Missed," persist reason "No arrival," timestamp it, and emit a "window.missed" event within 2 minutes. Given a configurable grace period (default 5 minutes), When the vendor enters the geofence within the grace period after end time, Then mark the visit as "Late arrival" and do not trigger the rescheduling flow. Given a device enters the geofence after the grace period, When the window is already marked missed, Then do not change status to "Arrived"; log an "Unauthorized attempt" and deny access. Given any time-based evaluation, When computing missed status, Then use the property’s timezone and correctly handle daylight saving time changes.
Vendor Prompt & One-Tap Rescheduling
Given a visit is marked "Missed", When the missed event is emitted, Then send the vendor a push notification within 60 seconds containing at least 3 one-tap rescheduling options. Given rescheduling options are generated, When options are presented, Then they must comply with constraints: tenant availability windows, owner blackout dates, vendor working hours, minimum lead time of 2 hours (unless tenant policy allows sooner), and SLA due-by date. Given the vendor selects a one-tap option, When the selection is received, Then tentatively hold the slot and set status to "Pending tenant confirmation." Given the vendor proposes a custom time that violates constraints, When the proposal is submitted, Then block submission and display which rule(s) were violated. Given no vendor action within 15 minutes of the prompt, When the window remains missed, Then send a reminder; if no action within 60 minutes, set status to "Awaiting vendor" and notify the coordinator.
Tenant Confirmation & Fallback
Given a vendor-proposed reschedule time, When the system contacts the tenant via their preferred channel (push/SMS/email), Then include date, start/end times, tenant-local timezone, property label, and one-tap Confirm/Decline/Suggest buttons. Given the tenant confirms, When confirmation is received, Then set status to "Rescheduled - Confirmed," update calendars, and finalize the vendor slot. Given the tenant declines, When the decline is received, Then notify the vendor and present alternative slots that meet constraints. Given no tenant response, When 2 hours have elapsed, Then send a reminder (maximum 2 reminders spaced 2 hours apart); if still no response after 24 hours, escalate to coordinator or auto-confirm per property policy, and log the action and policy reference.
Multi-Channel Notifications & Idempotency
Given a reschedule lifecycle event (missed, proposed, confirmed, declined, escalated), When notifications are dispatched, Then notify vendor, tenant, and owner via their selected channels with event type, time window, and a deep link to the work order. Given a message retry for the same event within 10 minutes, When dispatch occurs, Then deduplicate using a correlation ID so each recipient gets a single notification. Given user notification preferences, When dispatching, Then respect opt-outs and attempt a fallback channel if the primary fails with a retriable error. Given recipients across timezones, When composing notifications, Then render all times in the recipient’s local timezone.
SLA Auto-Escalation After N Misses
Given a work order accumulates N missed windows (configurable per SLA, default 2), When the Nth miss is recorded, Then auto-escalate by notifying the property manager, tagging the work order as "Escalated," pausing vendor self-rescheduling, and optionally reassigning to a backup vendor pool. Given an escalation occurs, When auditing the work order, Then an immutable log entry captures trigger, previous assignee, new assignee (if any), timestamp, and SLA configuration used (N and policy ID). Given property-specific SLA overrides exist, When determining N, Then apply the property override before portfolio defaults.
Geofence Enforcement Sync
Given a reschedule is tenant-confirmed, When the system finalizes the new window, Then update and propagate geofence enforcement rules within 60 seconds to the vendor device/app. Given updated geofence rules, When the vendor attempts entry before the start of the new window, Then deny access and log reason "Too early." Given updated geofence rules, When the vendor is within the geofence during the new window, Then allow access and record an "Arrived" event tied to the new window ID. Given the vendor device is offline during updates, When connectivity is restored, Then apply queued rule updates immediately and reconcile any offline access attempts against the last-synced window, logging discrepancies.
Dashboard Indicators & Reporting
Given the Maintenance dashboard is opened, When KPIs are rendered, Then show Missed Visits (7/30 days), Rescheduled Visits, Average Time to Recovery, and Miss Rate by vendor/property with filters for date range, vendor, property, and issue type. Given a work order detail view, When viewing the timeline, Then display missed events, vendor prompts, tenant responses, escalations, and confirmations with actor and timestamp. Given a reporting request up to 10,000 rows, When exporting "Missed and Rescheduled Visits" to CSV, Then generate within 5 seconds including: work order ID, property, vendor, tenant, scheduled window, missed timestamp, proposed time(s), confirmation timestamps, escalation flag, and final status.
Audit Trail & Dispute Evidence Log
"As an owner, I want a verifiable log of when and how access was granted so that I can resolve disputes quickly and protect all parties."
Description

Record immutable arrival and departure events with timestamp, geofence status, device ID, and map snapshot, and append them to the job’s photo-timeline and activity feed. Support exportable, court-friendly PDF/CSV packages and a redacted tenant view. Include decisions (allowed/blocked, reason), code reveal time, and any overrides. Integrate with FixFlow’s existing timeline and storage, ensuring tamper-resistant hashes for key records. Expected outcome: transparent, defensible evidence that reduces responsibility disputes and owner admin time.

Acceptance Criteria
Log Arrival Within Geofence and Scheduled Window
Given a job with a configured geofence radius and an active scheduled window And a vendor assigned to the job using a location-enabled device When the vendor enters the geofence during the scheduled window and access is granted Then create an immutable arrival event containing: eventId, jobId, vendorId, eventType=arrival, decision=allowed, reason=in_window_and_in_geofence, timestamp=UTC ISO-8601, geofenceStatus=true, coords(lat,lon,accuracy_m), deviceId, devicePlatform, mapSnapshotUrl, codeRevealTimestamp(if shown) And store a SHA-256 hash of the canonical event payload And append the event to the job timeline and activity feed within 2 seconds of detection And enforce idempotency to prevent duplicate arrival events for the same vendor within 3 minutes
Blocked Entry Attempt Outside Geofence or Time Window
Given a job with a configured geofence and scheduled window When the vendor attempts access while outside the geofence or outside the scheduled window Then create an immutable access_attempt event with decision=blocked and reason in {outside_geofence, outside_window, location_permission_denied, location_spoofing_detected}, timestamp=UTC ISO-8601, geofenceStatus=false or out_of_window, coords if available, deviceId, devicePlatform, mapSnapshotUrl if coords available, codeRevealAttempted=false And do not reveal the access code And prompt the vendor to reschedule and log a reschedule_prompted event linked to this attempt And if the scheduled window elapses without an arrival, auto-create a missed_window event with reason=window_elapsed And append the event(s) to the job timeline and activity feed within 2 seconds
Log Departure Event With Geofence Status
Given a prior allowed arrival event exists for the job When the vendor exits the geofence or performs an explicit checkout after work completion Then create an immutable departure event containing: eventId, jobId, vendorId, eventType=departure, timestamp=UTC ISO-8601, geofenceStatus(current), coords(lat,lon,accuracy_m), deviceId, devicePlatform, mapSnapshotUrl And compute and store visitDuration = departure.timestamp - latest arrival.timestamp for the same visit And append the event to the job timeline and activity feed within 2 seconds And if no prior arrival exists, record the departure as decision=recorded_forensic_only with reason=no_prior_arrival
Admin Override of Blocked Access
Given a blocked access_attempt event exists for the job And an authorized admin/owner is authenticated with permission AccessOverride When the admin approves an override for that attempt Then create an immutable override event containing: eventId, parentEventId, jobId, approverId, approverRole, eventType=override, decision=allowed, reason=admin_authorized_<reason_code>, overrideScope(one_time|time_bound), overrideExpiresAt(if time_bound), timestamp=UTC ISO-8601, geofenceStatus(at time), coords(if available), deviceId, devicePlatform, mapSnapshotUrl And reveal the access code and record codeRevealTimestamp And store SHA-256 hashes for both the original blocked event and the override event And append the override event to the job timeline and activity feed within 2 seconds
Tamper-Resistant Hashing and Immutability
Given any audit event is created (arrival, access_attempt, override, departure, missed_window, reschedule_prompted) When the event is persisted Then compute SHA-256 over a canonicalized event payload and store eventHash and hashAlgorithm And link events in a per-job hash chain by storing previousEventHash for chronological integrity And store events in append-only storage; updates create new versions with new hashes while retaining prior versions; deletions are disallowed And expose a verification endpoint/utility that recomputes hashes and returns verificationStatus=true for unmodified records, false otherwise And surface verification failures in the UI and mark affected records in exports
Timeline and Activity Feed Integration
Given audit events exist for a job When viewing the job timeline and activity feed as Owner/PM, Vendor, or Tenant Then events are displayed in chronological order by timestamp with labels: Arrival, Departure, Access Blocked, Override, Missed Window, Reschedule Prompted And each event entry shows a thumbnail map snapshot and links to the full snapshot And role-based visibility is enforced: Tenant view is redacted; Owner/PM and Vendor see full details appropriate to their roles And new events appear within 2 seconds of creation And users can filter by eventType and date range and results are accurate
Export Court-Ready Evidence Packages (Full and Redacted)
Given an Owner/PM or Tenant requests an export for a job When the export is generated Then produce within 60 seconds a PDF and a CSV containing: jobId, property info, timezone, and an ordered list of events with fields [timestamp, eventType, decision, reason, geofenceStatus, coords(lat,lon,accuracy_m), deviceId, devicePlatform, map snapshots embedded or referenced, codeRevealTimestamp(if any), override info(if any), previousEventHash, eventHash, hashAlgorithm] And include a hash manifest and verification instructions And for Tenant exports, redact deviceId, precise coordinates (rounding or city-level), and access code details while retaining timestamps, geofenceStatus, and decisions/reasons And make files available via expiring signed URLs valid for <=24 hours And verification of exported records against stored hashes returns true
Offline/Low-Signal Operation & Grace Handling
"As a vendor, I want geofence access to work reliably even with poor signal so that I can complete jobs without unnecessary delays."
Description

Enable geofence checks with degraded connectivity by caching the geofence, schedule window, and access instructions in encrypted form and performing on-device validation using OS location services. Queue events for sync on reconnection, and apply a configurable offline grace policy (e.g., one-use emergency code via hotline with OTP verification). Implement basic spoofing detection (mock location checks, jitter analysis). Provide clear UX fallbacks and administrator-configurable rules. Expected outcome: reliable access control and logging even in basements or dead zones.

Acceptance Criteria
Offline Geofence Validation with Cached Data
Given the vendor has a scheduled appointment and the device is offline or low-signal And the app has a valid cached geofence radius, schedule window, and access instructions within the admin-configured cache TTL When the vendor arrives within the scheduled window and within the geofence using OS location services with accuracy ≤ admin threshold Then the app validates access on-device without network And reveals access instructions only after validation succeeds And records a timestamped "geofence_entered" event with device ID, appointment ID, accuracy, and battery level into the local queue within 2 seconds And denies access if the cache is expired or location accuracy exceeds the admin threshold, showing a clear offline error
Queued Event Sync on Reconnection
Given one or more offline events (e.g., geofence_entered, access_granted, access_denied, otp_used) are stored in the local queue And network connectivity is restored When the app detects connectivity Then it uploads queued events in FIFO order within 60 seconds, with retries and exponential backoff per admin policy And includes a monotonic timestamp, unique event ID, and checksum for each event to enable server-side deduplication And marks events as synced only after 200 OK server acknowledgment And preserves queue integrity across app restarts and OS kills
Emergency OTP Grace Policy
Given geofence validation fails due to offline/low-signal and the appointment is within the admin-configured grace tolerance When the vendor calls the hotline and passes OTP identity verification And support issues a one-use OTP code of admin-configured length and expiry Then entering a valid OTP unlocks a single access attempt and records reason code, issuer ID, and vendor photo verification And invalid OTP attempts are limited to the admin-configured maximum before lockout And the OTP event is queued and synced with full audit metadata on reconnection
Spoofing Detection and Handling
Given the device reports location updates When mock location providers, developer options allowing mock locations, or emulator signals are detected Or when jitter analysis indicates physically implausible movement (speed/heading/altitude) beyond admin thresholds Then the app blocks automatic access, requires secondary verification (e.g., OTP + photo), and flags the appointment as "location_suspect" And records spoofing indicators and OS signals locally for audit and sync And allows rescheduling flow as a fallback
Encrypted Caching and Data Hygiene
Given geofence, schedule window, and access instructions must be available offline When the app caches this data Then it stores it encrypted at rest using OS keystore-backed keys And redacts access instructions until in-geofence and in-window And automatically purges cached data after the appointment window + admin retention period, on sign-out, or upon admin remote revoke And denies access if decryption fails or keys are invalidated
UX Fallbacks and Messaging Offline
Given the vendor attempts check-in while offline or outside the window/geofence When validation cannot be completed on-device Then the app displays a clear status banner (Offline/Out of Window/Out of Geofence) and next steps within 1 second And provides actionable options: Retry Location, Call Hotline (OTP), and Request Reschedule And logs the selected fallback action to the local queue And supports localized text and large-text accessibility settings per OS
Admin-Configurable Offline Rules and Propagation
Given an administrator updates offline-related settings (cache TTL, location accuracy threshold, grace tolerance, OTP length/expiry/attempts, spoofing thresholds, sync backoff) When devices next sync successfully Then the new settings are delivered to devices and take effect without app update And devices continue using last-known-good settings when offline And all changes are captured in an immutable audit log with admin ID, timestamp, old/new values And disabling OTP immediately removes the OTP option from the client on next sync
Privacy & Data Retention Controls
"As a tenant, I want assurance that my location-related data is minimized and retained only as needed so that my privacy is respected while still enabling accountability."
Description

Limit location collection strictly to job-relevant events and scheduled windows, storing only event-level coordinates and not continuous tracks. Offer configurable retention (e.g., 12–36 months), data minimization for tenant views, and secure deletion workflows. Provide policy disclosures and access requests handling to meet regional privacy requirements. Integrate with FixFlow’s role-based access and data lifecycle management. Expected outcome: compliance-friendly handling of sensitive location data that maintains user trust.

Acceptance Criteria
Event-only location logging within scheduled geofence window
Given a work order with geofence radius R and a scheduled window [Start, End] And the vendor has granted location permissions When the vendor device crosses into the geofence during [Start, End] Then exactly one Arrival event is stored with {jobId, vendorId, timestampUTC, latitude, longitude, accuracyMeters, source="geofence-enter"} And no other location points are stored for that entry When the vendor device exits the geofence during [Start, End] Then exactly one Departure event is stored with {jobId, vendorId, timestampUTC, latitude, longitude, accuracyMeters, source="geofence-exit"} And no other location points are stored for that exit When the vendor device is outside the geofence or outside [Start, End] Then no location data is persisted for that job
No continuous tracking or intermediate points
Given the vendor remains inside the geofence for 30 minutes during the scheduled window When the device produces multiple OS/location callbacks Then the datastore contains at most two records for that interval (Arrival and Departure) And zero intermediate track points are stored Given the vendor moves outside any active job window for 60 minutes When background location callbacks occur Then zero location records are persisted for that subject and job
Configurable retention (12–36 months) with automated purge
Given an admin sets the location data retention policy to 12, 18, 24, or 36 months When any stored location event exceeds the configured retention Then it is purged within 24 hours of expiry And purged events are not retrievable via UI, API, or exports And a retention-purge audit entry is recorded with {eventIdHash, purgeTimeUTC, policyId, actor="system"} Given the retention setting changes from 24 to 12 months When a re-evaluation job runs Then all events older than 12 months are purged within 24 hours
Tenant-facing data minimization
Given a tenant views a job timeline that contains vendor location events Then the UI displays only arrival/departure statuses and timestamps And no coordinates, map pins, live location, or route lines are shown When the tenant calls any location-events API Then the response is 403 or contains a redacted payload with lat/long removed Given an owner/admin with permission views the same timeline Then detailed coordinates are visible only to authorized roles per RBAC
Secure deletion workflow with audit trail
Given a Compliance Admin initiates deletion of location data for a specified job/subject And confirms the action with MFA When the deletion request is submitted Then all matching events are irreversibly deleted from primary data stores within 1 hour And backup purge tasks are scheduled to complete within 30 days And an immutable audit record is stored with {requestId, actorId, scope, method, requestedAtUTC, completedAtUTC}; no raw coordinates are retained in the audit When a UI or API attempts to fetch the deleted records Then a 404/empty result is returned
Regional disclosures and consent gating
Given a vendor in a region requiring explicit consent (e.g., GDPR) first uses Geofence Window When they attempt to enable location features Then a disclosure is shown stating purpose, retention, legal basis, data controller contact, and policy link And the vendor must explicitly opt-in before any location data is collected And a consent record is stored with {subjectId, region, policyVersion, textVersion, consentedAtUTC, method} When the policyVersion changes or the vendor withdraws consent Then location collection is blocked until fresh consent is obtained And no events are recorded while consent is absent Given a region that does not require explicit consent Then a notice is displayed and collection follows applicable regional policy configuration
DSAR export and RBAC-restricted access to location data
Given a data subject submits an access request for their location data When a Compliance Admin processes the request Then the system generates an export within 30 calendar days containing only that subject’s event-level records for the requested period in JSON and CSV And records for other subjects are excluded And the export includes metadata fields (timestamps, jobId, source, accuracyMeters) but no data beyond event-level points Given a user attempts to view or export location data Then only Owner Admin and Compliance Admin roles with MFA can access raw coordinates And tenants and non-privileged roles cannot access raw coordinates And all views/exports are logged with {actorId, timestampUTC, scope, downloadChecksum}; audit entries do not include raw coordinates

Two-Party Consent

Require both tenant and owner/manager approval for non-emergency entries before issuing codes. Mobile consent is time-stamped and attached to the ticket, aligning with notice requirements and eliminating ‘no notice’ complaints.

Requirements

Dual-Consent Capture Flow
"As a tenant or owner/manager, I want to review and approve entry requests from my phone so that entry only happens at agreed times and with clear consent."
Description

Mobile-first consent flow that allows tenants and owners/managers to review entry details, propose/confirm time windows, and approve or decline non-emergency entries with a single tap. Captures e-sign acknowledgement, timestamp, user identity, IP/device metadata, and optional notes. Localized and accessible UI embeds in the ticket view and supports deep links from notifications. Handles partial states (one party approved), withdrawals, and edits, updating ticket status in real time to eliminate ‘no notice’ complaints and provide a clear, auditable agreement between parties.

Acceptance Criteria
Tenant One-Tap Consent with E‑Sign and Metadata
Given a non-emergency ticket with pending tenant consent When the tenant opens the deep link on a mobile device And the consent UI displays entry details and proposed time window And the tenant taps "Approve" and e‑signs Then the system records consent with timestamp (UTC ISO-8601), user ID, role=tenant, IP address, user-agent, device identifier (if available), and optional notes And attaches the consent record to the ticket as an immutable audit entry And sets the ticket consent state to "Tenant Approved, Owner Pending" And displays a success confirmation to the tenant within 1 second of API success
Owner/Manager Approval and Time Window Confirmation
Given a ticket where tenant has proposed or accepted a time window and owner consent is pending When the owner/manager opens the consent UI via deep link And they confirm the existing time window or propose an alternate within policy And they tap "Approve" and e‑sign Then the system records consent with timestamp, user ID, role=owner/manager, IP address, user-agent, device identifier (if available), and optional notes And attaches the consent record to the ticket as an immutable audit entry And if the owner/manager time window differs from the tenant’s, set consent state to "Time Window Conflict — Reconsent Required" and request tenant confirmation Else set consent state to "Dual Consent Complete" and update ticket status to "Entry Authorized" And display a success confirmation to the owner/manager within 1 second of API success
Dual Consent Gating for Code Issuance
Given any non-emergency ticket requiring property entry When an access/lockbox code issuance is requested by any system component or user Then verify both tenant and owner/manager consents exist, are not withdrawn, and reference the same consent version and time window And if verification fails, block code issuance and display/log a reason indicating which condition failed And if verification succeeds, issue the code and log the issuance event linked to the consent version and ticket
Partial Consent State Handling and Notifications
Given a ticket where only one party has approved Then display ticket consent state as "Awaiting Other Party" and indicate which party is pending And send a notification to the pending party within 1 minute of the first consent And send automated reminder notifications every 24 hours (configurable) until consent is completed, withdrawn, or ticket is closed And notifications include a secure deep link that opens the embedded consent UI for the specific ticket
Edit to Entry Details Requires Re‑consent with Versioned Audit Trail
Given a ticket with existing valid consents When any entry-impacting field (date, time window, assigned vendor/person, access method, or scope of work) is edited Then mark prior consents as "Superseded" and invalidate them for code issuance And increment the consent version (vN+1) and persist a read-only record of all prior versions with editor identity and timestamps And require both parties to re-consent to the updated details And set ticket consent state to "Reconsent Required" until both parties approve the new version
Consent Withdrawal Before Entry Time
Given a ticket with one or both consents recorded When either party withdraws consent before the approved time window begins Then record the withdrawal with timestamp, identity, and optional reason And immediately set consent state to "Consent Withdrawn" and update ticket status accordingly And block or revoke any associated access codes And notify the other party and the assigned vendor in real time
Localization and Accessibility of Mobile Consent UI
Given the user’s locale is supported Then render all consent UI text and date/time formats in that locale And ensure the consent UI meets WCAG 2.1 AA for contrast, focus order, labels, and screen-reader announcements for status changes And ensure tap targets are at least 44x44 dp and text scales with OS settings without layout breakage And ensure the embedded consent UI is reachable via deep link and loads within 2 seconds on a 3G connection in a 360x640 viewport
Consent Policy & Compliance Engine
"As a property manager, I want the system to enforce local notice and consent rules automatically so that entries comply with laws without manual checks."
Description

Configurable rules engine that determines when two-party consent is required versus emergency bypass, enforces jurisdictional notice requirements (e.g., minimum lead time, allowed hours), and validates that scheduling and code release cannot occur before the earliest legal entry time. Supports property- and unit-level policies, emergency flags from triage, override with reason and approver, and full decision logging. Integrates with scheduling, notifications, and code gate to prevent non-compliant actions while providing admins with transparent, auditable policy outcomes.

Acceptance Criteria
Non-Emergency Two-Party Consent Enforcement
Given a non-emergency maintenance ticket in a jurisdiction requiring two-party consent And the unit’s effective policy requires two-party consent When the tenant submits mobile consent with a recorded identity and UTC timestamp And the owner/manager submits mobile consent with a recorded identity and UTC timestamp Then the system marks consent status as Complete for both parties And the earliest legal entry time is calculated as the later of (latest consent timestamp + configured minimum notice lead time) and the next allowed entry-hours window in the property’s local timezone And the scheduling UI prevents start times earlier than the earliest legal entry time with error code CONSENT_LEADTIME_BLOCK And the code gate refuses code issuance before the earliest legal entry time with error code CONSENT_NOT_MET And the consent artifacts (party, method, timestamp, IP/UA) are attached to the ticket and visible to admins And confirmation notifications are sent to both parties including the scheduled window and jurisdictional notice text
Emergency Bypass From Triage
Given triage flags the ticket as Emergency=true And the jurisdiction configuration permits emergency entry without two-party consent When the engine evaluates consent requirements Then two-party consent is bypassed for this ticket And notice lead-time constraints are bypassed per emergency configuration And the code gate permits immediate code issuance if within emergency-allowed hours (as configured) And the audit log records the emergency basis, triage signal, policy version, evaluator, and timestamps And both parties receive emergency entry notifications containing the emergency reason and applicable legal template
Jurisdictional Notice and Allowed Hours Enforcement
Given the jurisdiction has configured minimum notice lead time (L hours) and allowed entry-hours windows When a scheduler selects a start time that violates L hours from the latest required consent Then the system blocks the selection with error code NOTICE_LEADTIME and displays the computed earliest legal entry time When a scheduler selects a start time outside the allowed entry-hours window Then the system blocks the selection with error code OUTSIDE_ALLOWED_HOURS And all calculations use the property’s local timezone for display and are stored in UTC And reschedules are validated against the same rules; attempts earlier than the earliest legal entry time are rejected
Policy Hierarchy Resolution (Property vs Unit)
Given a unit has both property-level policy P and unit-level policy U When the engine computes the effective consent and notice rules Then unit-level policy U overrides conflicting rules in P And for constraints of the same type, the stricter effective rule is selected And the effective policy source and resolution details are recorded in the audit log And the admin UI shows the effective policy and its sources to the scheduler
Administrative Override With Reason and Approver
Given a blocked action due to consent or notice non-compliance And a user with role Compliance Admin (or higher) initiates an override When the user provides required fields: structured reason (min 20 characters), approver identity, scope (this ticket/one-time), and expiration Then the system validates role and fields and records an immutable override entry with a unique Override ID And the engine reevaluates and allows the specific action per override scope And both parties are notified per jurisdictional template that an override-based schedule was set (if required) And reporting surfaces override counts and reasons by property and unit
End-to-End Integration Blocks Non-Compliant Actions
Given the engine is integrated with Scheduling, Notifications, and Code Gate When a non-compliant schedule save is attempted Then the Scheduling service returns HTTP 409 with machine-readable codes (e.g., CONSENT_NOT_MET, NOTICE_LEADTIME, OUTSIDE_ALLOWED_HOURS) and no event is persisted When a non-compliant code issuance is requested Then the Code Gate returns HTTP 403 with policy violation details and no code is issued And the Notification service suppresses pre-entry notices until compliance is achieved And upon compliance (all consents complete and earliest legal entry time reached), the system allows scheduling and code issuance without requiring a user session refresh And revalidation occurs at code-issuance time; if policy or schedule changed to non-compliant, issuance is blocked and the admin is alerted
Comprehensive Decision Logging and Auditability
Given the engine evaluates any consent or notice decision Then it logs inputs (ticket ID, property/unit IDs, policy IDs and versions, jurisdiction ID and version, triage flags, requester ID, relevant timestamps), the evaluation steps, and the final decision with reason codes And each consent capture records party identity verification status, timestamp, IP, device/UA, and is attached to the ticket And logs are immutable, time-stamped, signed, and retrievable via admin UI and API with filters (ticket, date range, property/unit, outcome, reason code) And an export endpoint provides CSV and JSON with correlation IDs linking schedule attempts, code requests, notifications, and decisions And audit retrieval performance meets ≤2 seconds p95 for queries up to 10,000 records
Notification & Reminder Orchestration
"As a tenant, I want clear notifications and reminders to approve entry so that I don’t miss important requests and can plan accordingly."
Description

Multi-channel messaging to request and collect consents via SMS, email, and push, with secure deep links to the consent screen. Includes customizable templates, quiet-hour windows, automatic reminders, and escalation to alternates when primary contacts are unresponsive. Tracks delivery, opens, and actions; retries on failures; and surfaces per-contact status in the ticket. Ensures timely response collection to reduce scheduling delays and coordinates with the consent policy engine to avoid sending requests outside legal notice windows.

Acceptance Criteria
Dispatch Consent Requests via SMS, Email, and Push with Secure Deep Links
Given a ticket requiring two-party consent and channels SMS, email, and push are enabled for the contact And the contact has valid destination identifiers for each enabled channel When the orchestrator initiates a consent request Then the system sends one message per enabled channel within 5 seconds of initiation And each message includes a signed, single-use deep link bound to the ticket ID, contact ID, and channel And the deep link token TTL is 72 hours or until the contact acts (whichever occurs first) And the message body is rendered from the active template for the channel and locale And the send timestamp and channel message IDs are stored on the ticket audit log
Quiet Hours and Legal Notice Window Coordination
Given org quiet hours 21:00–08:00 in the contact’s local timezone And the legal notice window for the ticket opens at a configured datetime When a send or reminder would occur during quiet hours or before the legal window opens Then the system does not send the message And schedules the message for the earliest allowed datetime And displays the scheduled send time and suppression reason on the ticket And recalculates the schedule if the legal window or quiet hours configuration changes before send time
Automated Reminders Until Consent or Cap Reached
Given a reminder policy of up to 3 reminders every 12 hours per contact When no consent or decline is recorded within the interval Then the system sends a reminder at the scheduled intervals And stops sending further reminders immediately upon consent, decline, or opt-out And never exceeds the maximum reminder count per channel And resets the reminder schedule if a manual resend is initiated by a user
Escalation to Alternate Contacts on Non-Response
Given an owner primary contact and an alternate owner contact with an escalation threshold of 24 hours of no action When the primary contact is deliverable but has taken no action for 24 hours after initial request Then the system sends the consent request to the alternate contact across their enabled channels And records the escalation time and recipient in the ticket audit log And does not escalate if the primary has consented or declined And prevents duplicate escalation if escalation has already occurred for this ticket
Per-Contact Delivery, Open, and Action Tracking in Ticket
Given messages are sent to a contact across multiple channels When delivery receipts, opens, and actions are received Then the ticket shows per-contact, per-channel status: Sent, Delivered, Opened (with timestamp), Actioned (Consent/Decline with timestamp) And the ticket summarizes the latest overall contact state (Awaiting, Consented, Declined, Undeliverable) And if all enabled channels for a contact result in permanent failure, the contact is marked Undeliverable and reminders are stopped
Retry and Fallback on Messaging Failures
Given a message send attempt returns a transient failure code (e.g., 408, 429, 5xx, or provider-marked retryable) When retrying Then the system retries up to 3 attempts per channel with exponential backoff (1m, 5m, 15m) And retries are suppressed during quiet hours and resume at the earliest allowed time And on permanent failure codes (e.g., 400, 403, 404, 410), the system does not retry that channel And if all attempts on a channel fail and another channel is enabled, the system attempts the next channel And each attempt and outcome is recorded in the ticket audit log
Template Customization and Personalization
Given SMS, email, and push templates with placeholders are configured for consent requests When a message is generated Then placeholders are rendered with ticket data: tenant name, property address, entry date/time window, ticket ID, and consent deep link And a preview renders exactly what will be sent per channel and locale before dispatch And SMS messages respect 160-character segments and include organization name and opt-out instruction where required And emails include a verified From address and subject per template And if a required placeholder is missing data, the message is not sent and an actionable error is surfaced
Entry Code Release Gate & Smart Lock Integration
"As a vendor, I want entry codes to be released only after both parties approve so that I arrive with assured access and avoid lockouts."
Description

Access-control gate that withholds and later issues time-bound entry credentials only after both tenant and owner/manager consents are recorded and legal notice windows are met. Integrates with supported smart lock providers and static keypad systems to generate single-use or time-boxed codes aligned with the approved window, automatically revoking on consent withdrawal or reschedule. Exposes codes only to assigned vendors, logs access details via webhooks, and provides fallback instructions for physical key pickup when digital access is unavailable.

Acceptance Criteria
Withhold Codes Until Dual Consent and Notice Met
Given a non-emergency maintenance ticket requires entry And tenant consent is recorded with server-side timestamp T_tenant And owner/manager consent is recorded with server-side timestamp T_owner And the property’s jurisdictional notice window N_hours is configured When one or both consents are missing Then no entry credential is issued and the vendor sees status "Awaiting consent" When both consents are present and current_time < max(T_tenant, T_owner) + N_hours Then no entry credential is issued and the vendor sees status "Pending notice window" When both consents are present and current_time >= max(T_tenant, T_owner) + N_hours and an approved entry window [W_start, W_end] exists Then the system becomes eligible to issue an entry credential scoped to [W_start, W_end] And both consent records are attached to the ticket timeline with immutable timestamps
Time-Boxed Code Issuance via Supported Smart Locks
Given the property has an active, healthy smart lock integration And both consents are recorded and the notice deadline has passed And an approved entry window [W_start, W_end] exists When issuing the credential Then the system creates a provider-enforced single-use or time-boxed code valid only between W_start and W_end And receives a success response including a provider credential identifier And stores a masked credential reference and validity window on the ticket And attempts to use the credential outside [W_start, W_end] are rejected and logged And for single-use mode, a second unlock attempt with the same credential is rejected and logged And the credential auto-expires and is revoked at W_end via the provider API
Automatic Revocation on Consent Withdrawal or Reschedule
Given a credential C exists for an approved window [W_start, W_end] When either the tenant or the owner/manager withdraws consent before W_end or the appointment is rescheduled Then the system immediately revokes C via the provider API and marks it "Revoked" on the ticket And subsequent attempts to use C are rejected and logged by the provider And the assigned vendor is notified of revocation within 5 minutes via their configured channels And a replacement credential is not issued until both parties re-consent, a new window is approved, and notice requirements are re-evaluated and met
Restrict Code Exposure to Assigned Vendors Only
Given an entry credential exists for a ticket When viewing the ticket as any user Then only users from the assigned vendor organization who are explicitly assigned to the ticket can view the plaintext credential And tenant and owner/manager users cannot view the credential And the credential is redacted in notifications and exports for all non-authorized users And all credential views are audit-logged with user ID and timestamp And unauthorized access attempts are denied and logged
Access Event Logging via Webhooks
Given the lock provider emits webhooks for access events involving issued credentials When an unlock or lock event occurs using the issued credential Then the system records event_type, provider, lock_id, credential_ref, vendor_user_id (if resolvable), provider_timestamp, received_timestamp, and result And attaches the event to the ticket’s annotated photo-timeline as an immutable entry And events are exportable from the ticket as CSV and JSON And if no webhook is received within 2 minutes of provider_timestamp, the ticket shows a delayed/missing event alert
Fallback to Physical Key Pickup When Digital Access Unavailable
Given the property has no compatible digital access or provider API calls to issue/revoke a credential fail And both consents are recorded, notice requirements are satisfied, and an approved window [W_start, W_end] exists When issuing access Then the system withholds any digital credential display And generates vendor-specific physical key pickup instructions including pickup location, hours, responsible contact, and key return policy And requires the vendor to acknowledge pickup instructions in-app And logs the acknowledgment and any pickup/return status changes on the ticket timeline
Static Keypad Temporary Code Programming
Given the property uses a supported static keypad that allows temporary PIN programming And both consents are recorded, notice requirements are satisfied, and an approved window [W_start, W_end] exists When issuing access Then the system programs a unique temporary PIN into an available slot valid only during [W_start, W_end] And ensures the PIN is not reused for the same property for at least 90 days And if no slots are available, the system deprograms expired temporary PINs and retries once; if still unavailable, it falls back to physical key pickup and flags the property for capacity review And the temporary PIN is revoked at W_end and revocation is confirmed via the provider API
Consent Audit Trail & Export
"As an owner, I want a complete, timestamped consent record attached to each ticket so that I can resolve disputes and prove compliance."
Description

Immutable audit logging that appends all consent events to the ticket timeline, including who acted, action taken, timestamps, device/IP, signature artifacts, notice content sent, and scheduled entry window. Provides an exportable, shareable PDF bundle and API payload for compliance reviews and dispute resolution. Supports role-based access so tenants, owners, managers, and vendors see only appropriate details while preserving a complete, defensible record for the account owner.

Acceptance Criteria
Append-Only Consent Event Logging
Given a tenant or owner/manager submits a consent action (approve, deny, reschedule, revoke) on a ticket When the action is saved Then an audit entry is appended containing: ticket_id, actor_role, actor_id, action, action_reason (optional), server_timestamp (UTC ISO-8601 with milliseconds), actor_local_timestamp (ISO-8601 with timezone), device_fingerprint (model, os, app_version), client_ip, signature_artifact (image or SHA-256 hash), notice_content_snapshot_id, scheduled_entry_window (ISO-8601 start/end), request_id And the audit entry has a unique monotonically increasing entry_id within the ticket And the audit log is immutable: update/delete operations on existing entries are rejected with 409; corrections are appended as new entries referencing prior_entry_id and correction_reason And the entry participates in a per-ticket hash chain (prev_entry_hash, entry_hash); recomputing the chain validates without error
Role-Based Timeline Visibility
Given an authenticated user with role tenant, owner, manager, vendor, or account_owner requests the ticket timeline When the timeline is returned Then field-level visibility is enforced per role: - tenant: sees own actions, opposing party consent status, notice content sent to tenant, scheduled entry window; cannot see other parties' IP/device/signature artifact (redacted) - vendor: sees consent status and scheduled entry window only; cannot see notice content, PII, IP/device/signature artifact (redacted) - owner/manager: sees actions, timestamps, notice content, scheduled windows, signer name; cannot see tenant IP/device/signature image (only signature hash) - account_owner: sees all fields without redaction And unauthorized access to any hidden field results in HTTP 403 and the field omitted/redacted in the payload And all timeline fetches are logged as access events in the audit trail (without exposing hidden fields)
Export PDF Bundle (Audience-Aware)
Given an authorized user with permission export_audit requests a PDF consent-audit export for a ticket When the export is generated Then the PDF is produced within 10 seconds for timelines up to 300 entries and queued otherwise with progress updates And the PDF includes: cover page (ticket_id, property address, parties, prepared_by, export_timestamp, timezone), chronological entries, embedded photos/signatures/notice snapshots, page numbers, and timezone labels And integrity metadata is embedded: SHA-256 checksum and a QR code linking to a public verification endpoint And filename matches FixFlow_Ticket-{ticket_id}_ConsentAudit_{YYYYMMDDThhmmssZ}.pdf And audience-level redaction is applied (full, tenant, vendor, regulator) And the download link is access-controlled, expires in 72 hours, and each download is logged
Export API Payload (Audited and Paginated)
Given an API client with scope consent_audit:read and access to the ticket When it calls GET /v1/tickets/{ticket_id}/consent-audit?audience={full|tenant|vendor|regulator}&from=&to=&cursor= Then the API responds 200 within 2 seconds for <= 200 entries and streams or paginates beyond via opaque cursor And the payload conforms to a published JSON schema including: ticket_id, entries[], entry_id, actor_role, actor_id, action, timestamps, device_fingerprint, client_ip, signature_artifact (or hash), notice_content_snapshot, scheduled_entry_window, prev_entry_hash, entry_hash And redactions are applied per audience in the payload And responses include ETag and Last-Modified headers; conditional requests return 304 when applicable And errors return 401 (unauthenticated), 403 (forbidden), 404 (not found), 429 (rate limited) with machine-readable error codes And a checksum of the full payload is included for verification
Notice Content and Entry Window Capture
Given a non-emergency entry notice is prepared and sent to the tenant as part of the two-party consent workflow When the notice is dispatched (SMS, email, in-app) Then the exact rendered notice content (subject, body, attachments, resolved variables) is snapshotted and linked to the ticket timeline And the scheduled entry window is stored as ISO-8601 start/end with timezone offset and displayed in the recipient's local timezone And any change to notice content or entry window appends a new snapshot entry referencing prior_snapshot_id; no in-place edits are allowed And attempts to send a notice without a valid entry window are blocked with a validation error and no audit entry created
Tamper-Evident Verification
Given an exported PDF or API payload for a ticket's consent audit When the QR code is scanned or the verification endpoint /v1/verify?ticket_id={id}&checksum={sha256} is called Then the system returns Pass when the checksum and entry hash chain match the canonical store and Fail otherwise, including a reason and the first mismatched entry_id And independent verification is possible using the provided per-entry prev_entry_hash and entry_hash values And any modification of a single entry or artifact causes verification to Fail
Consent Expiration & Rescheduling
"As a scheduler, I want consents to expire and trigger re-approval when dates change so that access is always based on current agreements."
Description

Business logic to define consent validity windows and automatically invalidate consent when the entry date/time or vendor changes, the legal notice period shifts, or a configured expiration is reached. Triggers re-consent workflows with pre-filled context, updates the schedule to the next legal time, and blocks access credential issuance until fresh approvals are obtained. Preserves prior consents in the audit trail to maintain full historical context.

Acceptance Criteria
Invalidate Prior Consents on Schedule Change
Given a non-emergency entry ticket with valid tenant and owner/manager consents and a scheduled entry date/time When the entry date or time is changed by staff or vendor Then all existing consents on the ticket are marked invalid with reason "schedule changed" And a re-consent workflow is initiated for both tenant and owner/manager within 1 minute with pre-filled context (ticket ID, property, new proposed date/time, vendor identity, legal notice requirements) And the schedule is automatically moved to the earliest legally permissible time based on jurisdictional notice rules computed from the re-consent request timestamp And any access credential issuance for this ticket is blocked until fresh consents from both parties are captured And the ticket timeline records the invalidation event and the re-consent requests with time-stamped mobile consent links in the property’s local time zone
Invalidate Prior Consents on Vendor Change
Given a non-emergency entry ticket with valid two-party consent and an assigned vendor When the assigned vendor is changed to a different vendor Then all existing consents on the ticket are marked invalid with reason "vendor changed" And a re-consent workflow is initiated for both tenant and owner/manager within 1 minute, pre-filled with the new vendor’s name and credentials summary And the schedule is automatically moved to the earliest legally permissible time based on jurisdictional notice rules computed from the re-consent request timestamp And any previously issued or pending access credentials are revoked and new credential issuance is blocked until fresh consents are captured And the ticket timeline shows the vendor change, consent invalidation, and re-consent dispatch with timestamps and actor attribution
Consent Expiration Window Enforcement
Given a configured consent validity window (e.g., 72 hours) for the property or jurisdiction and a non-emergency ticket with captured two-party mobile consents at time T0 When the current time reaches T0 plus the configured validity window before entry is completed Then the system marks the consents as invalid with reason "consent expired" And automatically triggers re-consent requests to both parties within 1 minute with pre-filled context And moves the scheduled entry to the next legally permissible time based on notice rules starting from the re-consent request timestamp And blocks issuance of any access credentials until both fresh consents are captured And logs the expiration event, including original consent timestamps and expiration policy applied, in the ticket timeline
Legal Notice Shift Recalculation and Rescheduling
Given a non-emergency ticket with valid consents and a scheduled entry that met legal notice at time of scheduling And jurisdictional notice configuration or calendar conditions (e.g., holidays, weekends, DST) change the earliest permissible entry time When the system detects the shift that renders the current schedule non-compliant Then existing consents are marked invalid with reason "legal notice shifted" And re-consent is requested from tenant and owner/manager with pre-filled context including the updated earliest permissible entry And the schedule is auto-adjusted to the earliest compliant time based on the recalculated notice window And access credential issuance remains blocked until fresh two-party consents are captured And all recalculation details (old vs. new earliest entry, rules applied, timestamps) are recorded on the ticket timeline
Block Access Credentials Until Fresh Two-Party Approval
Given a non-emergency ticket whose most recent consents are invalid (expired, vendor changed, or schedule changed) When a vendor or staff attempts to generate or retrieve access credentials for the entry Then the system denies the request with status "blocked: consent invalid" and records the attempt with timestamp and actor And no credentials are delivered via any channel (app, SMS, email) until both fresh consents are captured And upon receipt of both consents, credential issuance becomes available only for the rescheduled compliant time window And the ticket timeline shows the blocked attempts and the eventual credential issuance event with timestamps
Preserve Historical Consents in Audit Trail
Given a ticket that has undergone one or more consent invalidations and re-consent cycles When an auditor views the ticket timeline or exports the ticket record Then all prior consent records remain visible and unaltered, including: consentor identity (tenant/owner), capture method (mobile), timestamp, associated schedule/vendor, and invalidation reason And the audit trail includes a complete sequence of events (consent captured, invalidated, re-requested, re-captured) with property-local timestamps and actor attribution And the system prevents deletion or overwriting of historical consent records by non-privileged users And export/download of the audit trail includes the same details to support dispute resolution
Multi-Occupant & Proxy Consent Handling
"As a landlord, I want to manage consent across roommates and co-owners according to my policy so that entries remain fair and compliant in multi-occupant units."
Description

Support for units with multiple tenants and properties with co-owners or authorized agents. Configurable policies define whether all parties, any one, or a quorum must approve, with conflict resolution when a participant declines. Allows designation of proxies (e.g., property manager) with scoped authority and records proxy relationships in the audit trail. UI clearly communicates the required consensus model and current progress to reduce confusion and ensure compliant, transparent approvals in shared-occupancy scenarios.

Acceptance Criteria
Consensus Policy Configuration Enforcement
Given a unit with multiple tenants and co-owners and a configured policy of "All Tenants + Any One Owner/Agent" When approvals are collected for a non-emergency entry Then codes are not issued until all tenants have approved and at least one owner or authorized proxy has approved And the UI displays the active policy in the consent panel And any attempt to issue codes before criteria are met is blocked with an explanatory message And all approvals are time-stamped and attached to the ticket audit trail
Any-One Tenant Policy Behavior
Given a unit with three tenants and a configured policy of "Any One Tenant" When the first tenant approves via mobile consent Then the system marks tenant consensus as met regardless of other tenants' pending or declined statuses And a subsequent decline by another tenant does not revoke consent unless the original approver retracts prior to code issuance And the approval event is time-stamped and recorded on the ticket And the code issuance remains gated by any applicable notice window
Quorum Threshold with Dynamic Occupant Changes
Given a configured policy of "Quorum: 60% of current tenants" And there are five active tenants listed When three tenants approve within the consent window Then the quorum requirement is considered met And if the active tenant list changes before code issuance, the quorum is recalculated against the updated list at issuance time And previously collected approvals from removed tenants are excluded while newly added tenants are counted as pending And the UI updates the required count and progress accordingly
Decline and Conflict Resolution Path
Given a configured policy of "All Tenants" When any tenant explicitly declines entry Then the request is set to status "Blocked – Declined" And code issuance is disabled And the owner/manager is notified with options to reschedule, request policy-allowed override/escalation, or cancel And the decliner's identity, reason (if provided), and timestamp are recorded in the audit trail And if the conflict is resolved (e.g., rescheduled), the system re-requests consent from all required parties
Proxy Designation and Scope Enforcement
Given an owner designates a property manager as a proxy with scope "Approve entry" and an expiry date When the proxy submits an approval within scope and before expiry Then the approval is accepted and labeled as "Proxy approval by <Proxy Name> for <Principal Name>" with scope and expiry details in the audit trail And if the proxy attempts an out-of-scope action (e.g., change consensus policy) or after expiry, the action is blocked with an error message explaining the reason And the proxy relationship (principal, proxy, scope, created by, created date, expiry) is recorded and viewable on the ticket
UI Consensus Progress and Deadlines
Given any multi-party consensus policy is active for a ticket When a user (tenant, owner, or proxy) views the consent status screen Then the UI shows: policy description, list of required parties by name/role, who approved/declined with timestamps, remaining approvals needed, and consent deadline/notice window And changes (new approve/decline) are reflected in the UI within 5 seconds of submission And the consent screen meets WCAG 2.1 AA for contrast, focus indicators, and screen reader labels And mobile and desktop layouts clearly indicate next required actions
Legal Notice Timing and Code Issuance Gate
Given a non-emergency entry with a jurisdictional notice requirement (e.g., 24 hours) And all required consents have been obtained at time T When the system evaluates code issuance Then no entry code is issued before T plus the configured notice interval unless all required parties explicitly waive notice where legally permitted And upon issuance, the code, issuance timestamp, and recipient list are attached to the ticket And attempts to bypass the gate are prevented and logged in the audit trail

Instant Revoke

A one-tap kill switch to immediately invalidate active codes and remote unlock permissions. Sends alerts, rotates credentials, and pauses the visit—ideal for safety concerns, turnovers, or vendor reassignment.

Requirements

One-Tap Revoke Control
"As a property manager, I want to revoke all active access with one tap so that I can instantly secure a unit when a visit should not proceed."
Description

Implements a unified kill-switch UX and backend endpoint that immediately invalidates all active access artifacts (temporary PIN codes, mobile keys, remote unlock permissions) for a chosen scope: individual person, visit, property, or portfolio. Executes within seconds with atomicity across integrated devices and services, displays a confirmation with a summary of affected assets, and enforces idempotency to prevent duplicate actions. Integrates with FixFlow’s visit/access models, supports scoping and exclusions (e.g., common areas), provides real-time status of command execution per device, and exposes an API for automation.

Acceptance Criteria
One-Tap Revoke for Individual Person
Given an authorized FixFlow operator views a person with at least one active access artifact (temporary PIN, mobile key, or remote-unlock permission) across any property And the operator selects scope "Person" with that person’s identifier When the operator taps "Revoke now" and confirms Then backend authorization for that person denies all new access attempts within 3 seconds And all access artifacts linked to the person are marked invalid and propagated to integrated devices with commands dispatched within 5 seconds And the system rotates any shared credentials affected by the person’s access to prevent reuse And any active visits for the person transition to "Paused" And notifications are sent to configured recipients within 60 seconds And a confirmation is displayed showing timestamp, actor, correlation ID, affected visits/properties, and counts per artifact type And an audit log entry is recorded with before/after state and scope details
Visit-Level Revoke with Exclusions and Pause
Given a scheduled visit with associated access artifacts across areas where certain areas are flagged as excluded (e.g., common areas) And the operator selects scope "Visit" and enables exclusions for the flagged areas When the operator confirms revoke Then only non-excluded access artifacts for the visit are invalidated; excluded-area artifacts remain active And the visit status becomes "Paused" and any scheduled remote unlock windows are suspended And the confirmation summarizes included vs excluded assets and reasons for exclusion And notifications inform the visit’s assignees and property contacts And audit logs record the exclusion list and visit linkage
Portfolio-Wide Kill Switch
Given an operator with portfolio-level permissions selects scope "Portfolio" for a portfolio that has at least one active access artifact When the operator confirms revoke Then central authorization denies new access for all targeted persons/visits/properties in the portfolio within 5 seconds And device revoke commands are enqueued per property and dispatched concurrently, with a single correlation ID tracking the batch And the confirmation displays counts per property and artifact type and the number of devices targeted And rate limiting or batching does not leave any targeted artifact active in central authorization And audit logs capture the portfolio, properties affected, and the actor
Atomic Commit and Time-to-Invalidate SLAs
Given a revoke request is initiated for any supported scope When the system processes the request Then the central revoke commit is atomic: either all targeted artifacts are marked revoked together or none are, with no partial central state And on commit success, any subsequent access validations against central authorization are denied for the targeted scope And on commit failure, the system returns an error, makes no central-state changes, and does not dispatch device commands And 95% of successful requests deny central authorization within 3 seconds and dispatch device commands within 5 seconds, with worst-case not exceeding 10 seconds for dispatch
Idempotent Revoke Operations
Given a revoke request is submitted with an Idempotency-Key and identical scope parameters And the same request is retried within 24 hours due to client/network issues When the retry is received Then the system returns the original correlation ID, status, and summary without performing duplicate side effects And no duplicate alerts, rotations, or audit entries are produced And differing parameters under the same Idempotency-Key are rejected with a 409 conflict and no state change
Real-Time Device Execution Status and Retries
Given a revoke is in progress affecting multiple integrated devices When the operator views the status panel Then each device shows a real-time status (Pending, Success, Failed) with last-updated timestamp and attempt count And statuses refresh at least every 2 seconds until terminal And the system auto-retries Failed/Pending devices up to 3 times with exponential backoff (e.g., 2s, 8s, 30s) And operators can trigger a manual retry on Failed devices And upon overall completion or 15-minute timeout, a final summary is presented and emitted via webhook
API Endpoint and Webhook Automation
Given a service holds OAuth2 credentials with scope "access:revoke" When it POSTs to /api/v1/access/revoke with a valid scope (person_id, visit_id, property_id, or portfolio_id), optional exclusions, reason, and an Idempotency-Key Then the API validates permissions and scope, responds 202 with a correlation ID, and begins processing And invalid scope or permissions returns 400/403 respectively with no state change And the service emits webhooks: revoke.initiated, revoke.device.updated, revoke.completed (or revoke.failed) with correlation ID and per-device details And the API is rate-limited to prevent abuse but guarantees central authorization revocation is not deferred once accepted And the action is reflected in the audit log with the API client identity
Automated Credential Rotation
"As an owner, I want credentials to be automatically rotated after revocation so that previously shared codes cannot be reused."
Description

Automatically rotates and re-issues credentials following revocation: regenerates lock PINs, invalidates mobile keys, refreshes access tokens, and updates allow/deny lists per device capability. Ensures rotated credentials propagate to future scheduled visits, prevents reuse of revoked codes, and verifies rotation completion with per-asset success/failure telemetry. Integrates with supported smart-lock and access vendors, applies retry/rollback strategies, and records new credential metadata without exposing secrets.

Acceptance Criteria
Immediate Revocation Triggers Credential Rotation
Given an authorized user taps Instant Revoke for a visit or asset When the system processes the revocation event Then all active PINs, mobile keys, and access tokens tied to the visit/asset are invalidated within 60 seconds (95%) and within 5 minutes (100% with retries) And device allow/deny lists are updated according to each device’s capability And new device-appropriate credentials are generated and queued without exposing secrets And the visit status is set to "Paused" until rotation verification is complete And an audit event with timestamps, actor, visit ID, and affected asset IDs is recorded
Propagation to Future Scheduled Visits
Given one or more future scheduled visits exist for the affected asset(s) When credential rotation completes for an asset Then all future visits referencing that asset automatically reference the newly issued credentials And any links, invites, or work-order attachments are updated to point to the new credential identifiers And no future visit is allowed to use revoked credentials And stakeholders receive an update notification that excludes secret values
Prevent Reuse of Revoked Credentials
Given a revoked PIN, mobile key, or access token is presented to a lock or access API When an unlock attempt occurs after the revocation timestamp Then the attempt is denied by the device or access service And telemetry logs the attempt with reason "credential_revoked" and includes device ID, visit ID, and timestamp And the denial is visible on the visit’s audit timeline within 30 seconds
Per-Asset Telemetry and Rotation Verification
Given rotation is initiated for one or more assets under a visit When the rotation workflow executes Then for each asset a definitive success or failure record is captured with vendor, device ID, attempt count, latency, and timestamp And rotation is marked "Complete" only when all targeted assets report success or are flagged as failed after max retries And a summary result (counts of success/failure, duration, affected assets) is available via API and UI
Retry and Rollback Strategy for Unreachable Devices
Given a device returns transient errors or is offline during rotation When an operation to invalidate old credentials or issue new ones fails Then the system retries with exponential backoff up to 5 attempts over 10 minutes And on persistent failure the asset is marked "rotation_failed", old credentials remain revoked, and a high-priority alert is sent to the assigned user(s) And any partially created temporary credentials are invalidated and removed from the device/service when it becomes reachable And incident details and manual recovery steps are attached to the asset record
Vendor Capability Mapping and Fallback Handling
Given heterogeneous vendors and device capabilities (e.g., PIN-only locks, mobile-key platforms, token-based controllers) When rotation runs Then the platform selects the appropriate operation per device capability (PIN regenerate, mobile key revoke/reissue, token refresh, allow/deny update) And unsupported operations are skipped with explicit telemetry status "unsupported_capability" without blocking supported operations on other devices And affected assets with unsupported capabilities are flagged for manual action with clear guidance
Secrets Handling, Redaction, and Access Control
Given new credentials are generated and rotation metadata is recorded When writing logs, events, notifications, or API responses Then no secret values (full PINs, raw tokens, key material) are stored or exposed in any channel And only masked or hashed identifiers are persisted And access to rotation metadata is limited to authorized roles and verified via role-based tests And automated redaction checks pass in CI with zero critical findings
Real-time Multichannel Alerts
"As a landlord, I want all stakeholders alerted immediately when access is revoked so that everyone knows the visit is paused and does not attempt entry."
Description

Delivers immediate notifications to all impacted parties (tenant, vendor, owner, coordinator) when Instant Revoke is triggered, including reason code, scope, and next steps. Supports push, SMS, email, and in-app banners with localized templates, urgency flags, rate limiting, and acknowledgment tracking. Updates activity feeds, revokes or masks access links in messages, and provides administrators with a delivery/engagement report.

Acceptance Criteria
Immediate Multichannel Alert Dispatch on Instant Revoke
Given an active visit with impacted parties (tenant, vendor, owner, coordinator) and an authorized user When Instant Revoke is triggered with a reason code and scope Then the system sends one notification per channel (push, SMS, email, in-app banner) to each impacted party within 5 seconds And each notification contains the reason code, scope, timestamp, next steps, and a shared correlation ID And delivery attempts per channel are logged with status (queued, sent, delivered, failed) and timestamps
Localization and Urgency Flag Rendering
Given each recipient has a stored locale and timezone When alerts are generated Then message content is rendered using the recipient’s locale template with ICU formatting And dates/times are shown in the recipient’s timezone And the urgency flag is displayed as High with the channel-appropriate visual indicator And if a locale template is missing, the English fallback template is used And no unresolved placeholders (e.g., {{reason_code}}) appear in the message
Rate Limiting and Deduplication for Burst Revokes
Given multiple Instant Revoke events occur for the same visit within 60 seconds When a subsequent event is processed Then per-recipient, per-channel rate limiting caps sends at 1 alert per 60 seconds unless the reason code changes or the scope expands And duplicate alerts are consolidated into a single updated in-app banner for that recipient And suppressed sends are recorded with suppression counts and reasons in delivery logs
Acknowledgment Tracking and Timed Escalation
Given an alert has been delivered to a recipient When the recipient taps the push action, clicks the in-app Acknowledge button, or replies "ACK" to the SMS Then the system records an acknowledgment with user ID, channel, timestamp, and correlation ID And the in-app banner is dismissed for that recipient And if neither vendor nor coordinator acknowledges within 10 minutes, an escalation alert is sent to the coordinator and owner via SMS and email And escalation halts immediately once any required role acknowledges And acknowledgment status per role is visible in the event’s activity feed
Activity Feed Update and Access Link Masking
Given existing messages for the visit may contain access links or codes When Instant Revoke is triggered Then an activity feed entry is created within 5 seconds including initiator, reason code, scope, and correlation ID And all previously issued access links/codes for the visit are invalidated server-side And any displayed links in the UI are masked with a "Revoked" label without exposing credentials And attempts to open old links return HTTP 410 Gone with a revoke explanation And masked historical content remains visible without actionable secrets
Administrator Delivery and Engagement Report
Given an administrator opens the delivery report for a specific revoke event When the report loads Then it lists each recipient and channel with delivery status (Sent, Delivered, Failed), timestamps, opens/clicks, and acknowledgment status And the report is exportable to CSV And 99% of delivery and engagement records are available within 60 seconds of the revoke event And failed deliveries display error codes and retry counts And all aggregates reconcile to raw event logs within ±1% variance
Visit Pause and Lockdown
"As a coordinator, I want the visit to be automatically paused and locked down after revocation so that the property is secured and coordination errors are minimized."
Description

Transitions the active visit to a Paused state, cancels the live access window, disables check-in/out, and instructs devices to deny entry. Presents quick actions to reschedule, reassign a vendor, or resume with fresh credentials. Synchronizes state with calendars, dispatch workflows, and billing/authorization holds to prevent accidental work orders from proceeding while access is blocked.

Acceptance Criteria
Instant Revoke pauses an active visit and revokes access
Given an active visit with an open access window and valid credentials When the user taps Instant Revoke for that visit Then the visit state updates to Paused within 3 seconds And the access window is immediately canceled (start and end times cleared or set to now) And all digital keys, PIN codes, and remote unlock tokens for the visit are invalidated within 5 seconds And the visit shows a Paused badge and the API returns state=paused and revokedCredentials=true
Devices deny entry and handle offline locks
Given one or more access devices (locks/hubs) linked to the visit When the visit is paused Then online devices receive a deny-entry command within 5 seconds and respond with success And offline devices are marked lockdown pending with command queued for next heartbeat And any remote unlock requests for the paused visit are rejected with HTTP 403 and reason=visit_paused And an event is logged per device with device_id, command_status, and timestamp
Check-in/out disabled and timers halted
Given the visit is paused When the assigned vendor attempts to check-in or check-out Then the action is blocked with message "Visit is paused" and the attempt is logged And time tracking and on-site timers stop within 2 seconds of pause And auto check-in/out rules do not trigger while paused
Quick actions after pause: reschedule, reassign, resume with fresh credentials
Given the visit is paused When the user opens the paused visit Then quick actions for Reschedule, Reassign Vendor, and Resume are visible to authorized roles only And selecting Reschedule opens the scheduler, updates the calendar event, and leaves the visit paused And selecting Reassign Vendor unassigns the current vendor, notifies them, invites the new vendor, and keeps access blocked And selecting Resume issues new credentials, sets a fresh access window, clears the paused state, and records a resume event
System-wide synchronization with calendars, dispatch, and billing holds
Given the visit is paused When integrations synchronize Then the calendar event status updates to "On Hold" and any live access time is removed from ICS feeds within 60 seconds And the dispatch workflow sets the job status to "On Hold" and blocks task progression requiring on-site access And billing places an authorization hold; attempts to bill, approve time, or release funds for the visit are blocked with reason=visit_paused And third-party webhooks receive a pause payload with visit_id, state=paused, and occurred_at
Notifications and auditable timeline
Given the visit is paused or resumed When the state changes Then alerts are sent to the owner/manager, assigned vendor, and tenant per preference (push/email/SMS) within 30 seconds And notification content includes visit_id, property, state, reason (if provided), and next steps And the photo-timeline and activity log include Pause and Resume markers with actor, timestamp, and affected credentials And duplicate notifications for the same state change are not sent within a 5-minute window
Overlapping visits and scope control
Given multiple active visits exist for the same unit or property When Instant Revoke is triggered for Visit A Then only Visit A transitions to Paused and only its credentials are revoked And visits B/C remain unaffected and retain valid access, with their credentials rotated only if they were shared with Visit A And attempting to pause all visits requires explicit user confirmation with a separate action And concurrent Pause and Resume requests resolve deterministically with last-write-wins and both events recorded
Audit Trail and Timeline Annotation
"As an owner, I want a clear audit trail of what was revoked and when so that I can resolve disputes and meet compliance needs."
Description

Creates an immutable, timestamped audit entry for each revoke event capturing actor identity, MFA status, reason code, affected assets, command outcomes, and notification results. Automatically annotates the unit’s photo-timeline at the moment of revoke, supports attaching notes and evidence, and exposes filters and exports for dispute resolution and compliance. Applies retention policies and tamper-evident storage to maintain integrity.

Acceptance Criteria
Complete Revoke Audit Entry
Given a permitted user initiates Instant Revoke for a unit And the action is confirmed by the user When the revoke command executes Then the system writes a single immutable audit entry with fields: event_id, event_type="revoke", iso8601_utc_timestamp, actor_id, actor_role, auth_method, mfa_status, reason_code, affected_assets, commands_issued, command_outcomes, notifications_attempted, notification_results, correlation_id And commands_issued include code_invalidation, credential_rotation, remote_unlock_revocation, and visit_pause where applicable And command_outcomes record per-command status (success/failure), status_code, and completion_timestamp And the audit entry is persisted within 2 seconds of command execution completion And the audit entry cannot be edited or deleted via any user interface or API And any corrections are appended as new audit entries referencing the original event_id
Timeline Annotation at Revoke Moment
Given a revoke event completes for a unit When the unit's photo-timeline is viewed Then an annotation titled "Access Revoked" is inserted at the revoke timestamp (±100 ms) And the annotation displays actor name and role, reason code, and command outcome summary And the annotation deep-links to the full audit entry and attached evidence And the annotation is visible within 2 seconds after the audit entry is persisted And the annotation is read-only and includes the annotation_id for reference
Notes and Evidence Attachment
Given a revoke audit entry exists When a user with edit rights adds notes and uploads evidence to the revoke event Then the system stores the note text and each file with metadata: attachment_id, uploader_id, iso8601_utc_timestamp, filename, mime_type, size_bytes, sha256_checksum And supported file types include jpg, jpeg, png, heic, mp4, pdf up to 100 MB per file, maximum 20 files per event And attachments and notes are read-only once saved; updates create new versioned entries linked to the revoke event And deletions (if permitted) create a separate "attachment_removed" audit entry referencing the original attachment_id And previews and downloads are available and the downloaded bytes match the stored sha256_checksum
Search and Filter Revoke Audit
Given multiple revoke events exist across units When a user filters by unit, date range, actor, reason code, MFA status, command outcome, or notification result Then the results include only audit entries matching all selected filters And sorting by newest, oldest, actor, or reason code updates the order accordingly And the first page of results is returned within 2 seconds for datasets up to 10,000 events And the UI displays total count and accurate pagination
Export Audit Records for Compliance
Given a user has a filtered set of revoke audit entries When the user exports the results to CSV or JSON Then the exported file includes all selected fields plus event_id and sha256_event_hash And the export metadata includes export_timestamp (ISO 8601 UTC), filter_params, and record_count And the file is generated and available for download within 5 seconds for up to 10,000 events And a separate verification file containing the export hash and signature is provided
Retention Policy and Legal Hold
Given an organization-level retention policy is configured When a revoke audit entry reaches its retention expiration without an active legal hold Then the system purges or redacts the entry per policy and writes a "retention_purge" audit entry with event_id, purge_timestamp, and retention_policy_id And if a legal hold is applied before expiration, the entry is retained until the hold is removed And administrators can generate a report showing entries purged and entries on legal hold within a specified date range And purge operations are irreversible and verifiable via absence in queries and exports
Tamper-Evident Storage and Verification
Given revoke audit entries are stored using tamper-evident mechanisms When a verifier requests integrity validation for a given event_id Then the system returns the event payload, its sha256 hash, and a chain proof linking to the previous event hash And integrity verification succeeds for unmodified data and fails for any altered field And any verification failure triggers an administrative alert within 60 seconds and is logged as a "integrity_alert" audit entry
Role-Based Authorization with MFA
"As an account admin, I want Instant Revoke protected by roles and MFA so that only authorized users can trigger it and we reduce mistakes."
Description

Restricts Instant Revoke to permitted roles with granular scopes (portfolio, property, unit, visit) and requires multi-factor confirmation plus an explicit reason prior to execution. Provides safeguards such as a confirmation dialog, cooldown to prevent rapid repeats, optional second-approver for high-risk properties, and comprehensive attempt logging for security review.

Acceptance Criteria
Authorized Execution With MFA and Reason
Given a user assigned a role with permission "instant_revoke:execute" at scope S that contains target T And the user has a registered MFA method and is not in cooldown When the user initiates Instant Revoke for target T, enters a reason of at least 10 characters, completes step-up MFA within 60 seconds, and confirms in the dialog Then the system executes the revoke for target T and returns HTTP 200 with a success message And all active access codes and remote unlock permissions for target T are invalidated, any active visit is paused, credentials on affected devices are rotated, and alerts are sent to configured recipients
Scope Enforcement Across Portfolio, Property, Unit, and Visit
Given a user with portfolio-scoped permission for portfolio P1 When they attempt to revoke a visit V1 under P1 Then authorization succeeds and the revoke may proceed Given a user with property-scoped permission for property PR1 When they attempt to revoke any visit under PR1 Then authorization succeeds and the revoke may proceed Given a user with unit-scoped permission for unit U1 When they attempt to revoke any visit under U1 Then authorization succeeds and the revoke may proceed Given a user with visit-scoped permission for visit V2 When they attempt to revoke a different visit V3 or any higher scope Then authorization fails with HTTP 403 and no revoke occurs
MFA Requirement and Failure Handling
Given a permitted user initiates Instant Revoke When MFA is not completed successfully (incorrect code, timeout after 60 seconds, or device unavailable) Then the revoke is not executed, no access codes/permissions are changed, no credentials are rotated, and no alerts are sent And the user sees an error indicating MFA is required to proceed And the attempt is logged with outcome "denied_mfa"
Reason Requirement Validation and Capture
Given a permitted user with valid MFA initiates Instant Revoke When the reason field is empty or shorter than 10 characters Then submission is blocked with inline validation message "Reason is required (min 10 characters)" When the reason meets validation and the user confirms Then the reason text is stored with the audit record and is included in the confirmation summary and alert payloads
Second-Approver Workflow for High-Risk Properties
Given the target resides under a property flagged as high risk with policy requiring a second approver When a permitted user submits an Instant Revoke with valid reason and MFA Then the system sends an approval request to an eligible second approver (excluding the initiator) and shows a pending state And the revoke executes only after the second approver approves within 10 minutes And if the approver rejects or the request expires, the revoke does not execute and the initiator is notified And all approval outcomes are logged with approver identity and timestamps
Confirmation Dialog and Cooldown Throttle
Given a permitted user initiates Instant Revoke When the confirmation dialog appears Then it displays the target scope and impact summary and requires explicit Confirm to proceed And after any completed attempt (success, rejected, denied, or error), the actor enters a 60-second cooldown for the same target scope When the actor attempts another revoke on the same target during cooldown Then the system blocks the attempt with an informative message and logs the event as "blocked_cooldown"
Comprehensive Audit Logging and Traceability
Given any Instant Revoke attempt occurs Then the system writes an immutable audit record with a unique ID including: actor ID and role, target scope and IDs (portfolio/property/unit/visit), reason text, timestamp (UTC), client IP/device, MFA method and result, second-approver requirement and outcome, final outcome (success/denied_mfa/denied_scope/rejected/blocked_cooldown/error), and correlation IDs for downstream actions (alerts, credential rotation) And audit records are queryable by time range, actor, target, and outcome
Offline and Fallback Handling
"As a property manager, I want revocation to work even if a lock is offline so that the unit remains protected during connectivity issues."
Description

Ensures revocation is effective under degraded connectivity by queuing commands, applying local deny-lists where supported, shortening code validity windows, and executing retries with backoff until devices confirm enforcement. Surfaces partial-failure states to operators, issues contingency alerts, and produces a reconciliation report once all assets have synchronized. Provides manual escalation paths when hardware limitations prevent immediate enforcement.

Acceptance Criteria
Immediate Revoke Under No Connectivity
Given an operator initiates Instant Revoke for a visit with at least one device currently unreachable When the revoke is submitted Then the system queues a revoke command per unreachable device within 5 seconds And sets the visit state to Paused within 5 seconds And invalidates any server-side remote unlock tokens immediately And marks each unreachable device as Pending Enforcement in the UI with last-seen timestamp And sends an alert to the operator within 30 seconds indicating partial enforcement
Queued Revocation with Exponential Backoff
Given at least one device has a queued revoke command due to connectivity failure When delivery attempts are made Then the system retries with exponential backoff starting at 30 seconds, doubling up to a maximum interval of 30 minutes And continues retries for up to 24 hours or until confirmation is received And logs each attempt with timestamp, result, and next retry time And upon device confirmation of revocation, stops retries for that device and updates status to Enforced within 10 seconds
Local Deny-List Enforcement on Supported Locks
Given the target lock model supports local deny-lists and has previously synchronized deny-list capability When Instant Revoke is initiated Then the system generates and syncs a deny-list entry for the active code on that device at next contact And if the device is currently reachable via any supported channel, pushes the deny-list within 30 seconds And the device blocks the revoked code offline without cloud connectivity, as verified by a negative unlock attempt within 2 minutes of push And the system records the deny-list version and device acknowledgment
Shortened Code Validity Window During Degraded Network
Given a device cannot immediately confirm revocation When Instant Revoke is initiated Then the system reduces the active code’s server-side validity TTL to no more than 5 minutes And prevents issuance of new remote unlock tokens for the visit And rotates any shared credentials (e.g., API keys, mobile keys) and invalidates prior ones within 60 seconds And records the TTL change and rotation in the audit log
Operator Visibility of Partial-Failure and Contingency Alerts
Given Instant Revoke results in at least one device pending enforcement When the operator views the visit details Then the UI displays a per-asset status: Enforced, Pending Enforcement, or Not Supported, with last update time And shows recommended contingency steps for each pending or not supported device And sends an immediate notification to the operator and owner on first partial failure and a summary every 60 minutes until resolved And allows the operator to subscribe or unsubscribe per visit to further alerts
Reconciliation Report After Full Synchronization
Given Instant Revoke has been initiated When all targeted devices have either confirmed enforcement or hit retry timeouts Then the system generates a reconciliation report within 5 minutes And the report includes device list, enforcement outcome per device, timestamps of attempts and confirmations, TTL reductions, credential rotations, alerts sent, and any manual actions taken And the report is stored as an auditable record and accessible via the visit timeline and exportable as PDF and CSV
Manual Escalation When Hardware Lacks Immediate Enforcement
Given a device is identified as Not Supported for immediate revoke or has exceeded the retry window without confirmation When the operator selects Manual Escalation Then the system provides escalation options: on-site lockout request, vendor reassignment, rekey or physical override, or contact resident And allows assignment to a vendor with SLA target and notes And generates a unique escalation ticket linked to the visit with status tracking And pauses any automated retries for that device until escalation is resolved or canceled

Access Ledger

A tamper-evident timeline that merges code creation, identity checks, geofence/NFC events, and entry/exit timestamps with photos and notes. Exportable for audits and owner reporting, it ends access disputes with clear, auditable proof.

Requirements

Access Code Lifecycle Logging
"As a property owner, I want every access code’s creation and lifecycle recorded against the job so that I can prove who had authorized access and when."
Description

Capture and persist the full lifecycle of every access code (creation, issuer, recipient, delivery channel, validity window, scope, usage attempts, revocation) and bind it to the job, unit, and property. Integrate with smart lock/code providers and FixFlow’s internal code generator to record issuance and rotation triggers, detect collisions, and track failed attempts. Store immutable lifecycle events in the Access Ledger with encrypted at-rest storage, enforce least-privilege access, and expose a consistent API for retrieval. Provide offline-safe logging, reconciliation on reconnect, and human-readable context to eliminate ambiguity during disputes.

Acceptance Criteria
Creation Event Logged to Access Ledger
Given an access code is created via FixFlow internal generator or an integrated provider for a specific job, unit, and property When the code is issued to a named recipient via a defined delivery channel Then an immutable Access Ledger event is persisted with fields: code_id (tokenized), provider, issuer_id, recipient_id, delivery_channel, scope (lock_id/unit_id/property_id), job_id, created_at (UTC), validity_start (TZ-aware), validity_end (TZ-aware), issuance_trigger, metadata_version And the event is write-once with a content-addressable hash and prior_hash reference And the event is encrypted at rest
Usage Attempts and Identity Checks Captured
Given a recipient attempts to use an issued code at a lock When the attempt occurs Then a usage_attempt event is recorded with fields: code_id (tokenized), lock_id, attempt_at (UTC), result (success|fail), reason (expired|revoked|collision|mismatch|outside_geofence|nfc_mismatch|invalid), identity_method (NFC|geofence|photo|none), identity_result (match|no_match|not_provided), entry_exit (entry|exit|unknown), device_id, geo (lat,lon,accuracy), media_refs, note_id And failed attempts are incremented per code and per lock And the retrieval API returns the last N attempts and aggregate counts per code
Revocation and Rotation Logged
Given a code must be revoked or rotated When revocation is enacted or a new code replaces an existing one Then revoke/rotate events are written with fields: code_id, replaced_by (if rotation), reason (job_complete|vendor_change|schedule_update|owner_request|suspected_compromise), effective_at (UTC), triggered_by (system|user_id), notification_outcomes (per channel delivered|failed) And any further usage attempts after effective_at record result=fail with reason=revoked And rotation links old and new codes via linkage fields for auditability
Collision Detection and Handling
Given a new code is generated or imported for the same lock and overlapping validity window When the proposed code value collides with an existing active or scheduled code Then the system blocks issuance, returns error CODE_COLLISION, and logs a collision_detected event with fields: colliding_code_id, existing_code_id, lock_id, overlap_window, resolver (auto|user_id), resolved_at (if applicable) And no notifications are sent to recipients for the blocked code And upon request an alternative non-colliding code is auto-generated, issued, and logged as a new issuance
Offline-safe Event Capture and Reconciliation
Given the device or edge service is offline during issuance or usage attempt When events are generated locally Then events are queued with monotonic sequence numbers, local timestamps, and a deduplication key And upon reconnect, events are transmitted, deduplicated, ordered by sequence then timestamp, and committed to the Access Ledger without loss or duplication And reconciliation status per event is visible via API (queued|synced|conflicted|error) with retry/backoff and a max staleness SLA of 15 minutes
Consistent Retrieval API with Filters and Context
Given an authorized client requests lifecycle events When calling GET /access-ledger/events with filters (job_id, unit_id, property_id, code_id, lock_id, event_types, from, to) and pagination (limit<=100, cursor) and sort (asc|desc by timestamp) Then the API returns 200 with a stable schema including human_readable_context strings for key fields, total_count (if requested), and a next_cursor when more results exist within 500ms for the 95th percentile And unauthorized roles receive 403; invalid filters receive 400 with error details And every event includes a verifiable hash and signature to prove immutability
Security: Encryption at Rest and Least-Privilege Access
Given Access Ledger data is stored When at rest in databases and object storage Then AES-256 encryption at rest is enforced with keys managed in KMS and rotated at least every 90 days And access to events is restricted to roles (Owner, PropertyManager, VendorAssignedToJob, System) with least-privilege scopes; all access is logged with subject, action, resource, and time And attempts to modify or delete existing events are rejected with 405 and recorded as tamper_attempt events
Unified Access Event Ingestion
"As an operations manager, I want all access-related events to flow into one normalized stream so that the timeline shows a complete, coherent picture."
Description

Ingest and normalize access-related events from multiple sources (smart locks, lockboxes, NFC taps, mobile geofence check-ins, manual confirmations, and code usage). Provide webhook, polling, and SDK adapters; ensure idempotency, deduplication, and UTC normalization with timezone context. Enrich events with user, vendor, job, unit, and property metadata; sequence them deterministically for timeline coherence. Include retry and backfill mechanisms, event schema versioning, observability (metrics, traces, dead-letter queue), and administrative tools to replay or quarantine malformed events.

Acceptance Criteria
Webhook Authentication and Idempotency
- Given a registered webhook with HMAC signature validation configured When an event POST with a valid signature is received Then the event is accepted with HTTP 202 and an ingestion_id is returned - Given the same event is redelivered up to 10 times with identical idempotency key or payload hash within 24 hours When processed Then only one normalized event is persisted and subsequent deliveries return HTTP 200 with the original ingestion_id - Given an event with an invalid or missing signature When received Then it is rejected with HTTP 401, no event is persisted, and metric access_ingest.webhook.auth_fail is incremented by 1 - Given a burst of 100 events per second When received Then the system sustains processing with p95 end-to-end latency under 2 seconds without violating idempotency
Adapter Polling/SDK Retry and Backfill
- Given a smart lock polling adapter configured with a 60-second interval When the remote API is available Then new events since the last checkpoint are fetched and normalized within 2 minutes and the checkpoint is advanced atomically - Given a 30-minute upstream outage When service resumes Then the adapter backfills all missed events using cursors without duplicates and restores an accurate checkpoint - Given HTTP 429 or 5xx responses When encountered Then exponential backoff with jitter and respect for Retry-After headers is applied and no events are dropped - Given the mobile SDK submits a batch with batch_id and monotonically increasing local_seq When received Then events are accepted in order, duplicates within the batch are dropped by idempotency key, and a 207 Multi-Status response reports per-item results - Given the SDK retries the same batch_id due to a network error When retried Then no duplicate normalized events are created and the same ingestion_ids are returned
UTC Normalization with Timezone Context
- Given an incoming event with local timestamp and timezone offset When normalized Then occurred_at_utc is stored in ISO-8601 UTC and timezone.name and timezone.offset fields are preserved - Given an event missing timezone metadata but with unit.property.timezone configured When normalized Then occurred_at_utc is computed using the property timezone and a normalization_warning is recorded - Given DST transitions When events cross DST boundaries Then occurred_at_utc values remain correct for the historical offset and timezone.offset reflects the offset at event time
Deterministic Sequencing Across Sources
- Given multiple events for the same job within a 5-minute window from NFC tap, geofence check-in, manual confirmation, and lock code use When sequenced Then events are ordered by occurred_at_utc, then source_priority (lock_code_use=1, nfc_tap=2, geofence_checkin=3, manual_confirmation=4), then event_id ascending to produce a stable sequence_id - Given two events with identical timestamps and equal source_priority When sequenced Then the tie-breaker by event_id ensures the order is stable across replays - Given late-arriving events up to 48 hours When ingested Then the timeline is re-sequenced deterministically without duplication and a timeline.updated event is emitted for affected jobs
Metadata Enrichment and Association
- Given an incoming event with external_user_id and lock_id When normalized Then the event is enriched with user_id/vendor_id/job_id/unit_id/property_id from the FixFlow directory and enrichment_status="complete" - Given no matching user is found When normalized Then enrichment_status="partial", user_id is null, and the event is routed to the enrichment-review queue with reason USER_NOT_FOUND - Given a job_id is provided in adapter context When normalized Then the event is associated to that job and appears in the job's access ledger within 5 seconds
Event Schema Versioning and Compatibility
- Given incoming events declare schema_version in {1,2} When normalized Then the payload is validated against the declared JSON Schema and mapped losslessly into the canonical internal schema; original schema_version is retained on the record - Given an adapter sends an event with an unsupported future schema_version When received Then the event is rejected with HTTP 409 and reason SCHEMA_UNSUPPORTED or routed to DLQ based on reject_on_future_schema configuration - Given a schema migration is deployed When canary enabled per adapter Then backward-compatibility tests pass in CI and metric schema.version.usage reports counts per version without regression
Observability, Dead-Letter, and Administrative Controls
- Given the ingestion service is running When processing events Then Prometheus metrics are exposed: access_ingest.events_total, normalized_events_total, dedup_skips_total, dlq_total, processing_latency_ms_bucket, adapter_error_total, and timeline_updates_total - Given distributed tracing is enabled When an event is processed end-to-end Then a trace with spans adapter.fetch, ingest.validate, normalize, enrich, sequence, persist is emitted and trace_id is stored on the normalized event - Given a malformed event fails schema validation When encountered Then it is placed on the DLQ with reason, validation errors, trace_id, and payload snapshot retained for 30 days - Given an operator selects DLQ events by time range and reason When Replay is triggered Then events are reprocessed preserving original event_id, replay_count increments, and successful replays are removed from DLQ - Given an operator enables quarantine for a source When active Then new events from that source are ingested to quarantine storage only, not propagated downstream, and alert ingest.quarantine.active is fired
Tamper-Evident Hash Chain & Digital Signatures
"As a landlord, I want the ledger to be tamper-evident so that any dispute can be resolved with trustable evidence."
Description

Implement a cryptographic hash chain across all ledger entries, signing entries with FixFlow keys and optionally vendor/device keys to provide non-repudiation. Any modification triggers a new versioned entry with linked diff, author, timestamp, and reason codes; original entries are preserved. Provide automatic integrity checks, periodic checkpointing, and export-verification artifacts. Surface integrity status and anomalies in the UI and API, and alert on chain breaks or signature validation failures. Store write-once semantics via append-only storage patterns.

Acceptance Criteria
Create Entry: Hash Linkage and Signatures
Given a new Access Ledger entry is created via POST /api/ledger/{ledgerId}/entries When the entry is persisted Then the entry includes prev_hash referencing the immediately prior committed entry for the ledger (or null for the genesis entry) And entry_hash equals the deterministic hash of the canonicalized payload including prev_hash, type, payload, author_id, created_at, and reason_code (if present) And the entry is signed with the FixFlow signing key and signature_fixflow verifies against the published FixFlow public key And if a vendor or device signing key is registered for the source, signature_vendor verifies against the corresponding public key; otherwise signature_vendor is null And GET /api/ledger/{ledgerId}/entries/{entryId} returns integrity_status = "ok" and chain_position with the correct index And recomputing the hash client-side using the documented canonicalization yields the same entry_hash
Update Entry: Versioning with Immutable Original
Given a user attempts to change fields of an existing Access Ledger entry When the change is submitted through POST /api/ledger/{ledgerId}/entries/{entryId}/versions Then the system appends a new versioned entry with a new entry_id, increments version_number, links prev_hash to the prior version, and preserves the original entry unchanged And the new version includes a machine-readable diff of changed fields, author_id, timestamp, and a required reason_code from the configured enum And GET /api/ledger/{ledgerId}/entries/{entryId}/versions returns an ordered, immutable history where all entry_hash values and signatures validate And the UI marks the entry as “Edited” with the displayed reason, and integrity_status remains "ok" for the chain
Automated Integrity Sweep and Surfacing
Given automated integrity checks run on a configurable schedule (default every 15 minutes) and on-demand via POST /api/ledger/{ledgerId}/verify When a sweep executes Then the system verifies contiguous hash-chain linkage and validates all required signatures from the last checkpoint (or genesis if none) And it records results with a sweep_id, started_at, finished_at, totals, and anomalies (if any) with types [CHAIN_BREAK, SIG_INVALID, MISSING_PREV, DUP_ENTRY] And the latest per-ledger integrity_status is surfaced in the UI (badge: ok/warning/failed) and via GET /api/ledger/{ledgerId} as integrity_status and last_verified_at And if anomalies are present, GET /api/ledger/{ledgerId}/anomalies lists them with entry references and verification evidence
Periodic Checkpointing for Efficient Verification
Given entries are appended to the Access Ledger over time When either 100 new entries are added or 24 hours elapse since the last checkpoint (configurable thresholds) Then the system appends a CHECKPOINT entry containing a cumulative_chain_hash, entry_range, and signature_fixflow that validates And subsequent integrity sweeps may start from the latest checkpoint and complete within 10% of the time required from genesis for the same range And GET /api/ledger/{ledgerId}/checkpoints returns all checkpoints with their verification status and coverage ranges
Export with Verification Artifacts
Given an owner requests an audit export for a date or entry range via POST /api/ledger/{ledgerId}/export When the export is generated Then the resulting package contains entries.json (canonicalized), checkpoints.json, anomalies.json (if any), a manifest.json with export_hash, range, created_at, and signer metadata, and a jwks.json or public key bundle for verification And every entry and checkpoint in the export verifies offline using the published verification procedure, yielding a PASS result And any byte-level modification to entries.json or manifest.json causes the offline verifier to return FAIL with a specific reason (e.g., SIG_INVALID or HASH_MISMATCH) And GET /api/ledger/{ledgerId}/exports/{exportId} returns status (pending|ready|failed) and a stable download URL
Append-Only Enforcement and Mutation Handling
Given a client attempts to mutate or delete an existing ledger entry via PUT or DELETE When the request is made to /api/ledger/{ledgerId}/entries/{entryId} Then the API rejects the request with HTTP 405 Method Not Allowed and an error_code = APPEND_ONLY_ENFORCED and guidance to create a new version instead And any internal write path that attempts in-place mutation is blocked and logged as a security event with actor, timestamp, and reason And the data store enforces append-only semantics such that a read-after-write of the original entry returns the unmodified record and a separate appended version is present when created via the supported versioning endpoint
Alerting on Chain Breaks and Signature Failures
Given a chain break or signature validation failure is detected during write-time validation or an integrity sweep When the anomaly is confirmed Then the system creates an incident of type INTEGRITY_FAILURE with ledger_id, entry_id (if applicable), first_detected_at, severity, and evidence, and sets ledger integrity_status to "failed" And notifications are dispatched within 60 seconds via configured channels (email, webhook) containing incident details and a link to the anomalies view And GET /api/incidents/{incidentId} and GET /api/ledger/{ledgerId}/anomalies reflect the incident and remain available for audit And the UI displays a blocking banner on the affected ledger until the anomaly is resolved or acknowledged by an authorized role
Identity Verification & Binding
"As a property manager, I want access events tied to verified identities so that I can hold the correct person accountable."
Description

Verify and bind identities for all participants (vendors, tenants, owners, staff) to access events using MFA, government ID scan with liveness, device binding, and contact verification. Associate identity artifacts and verification outcomes to each access code issuance and on-site event. Minimize and encrypt stored PII, capture consent, and enforce retention policies compliant with applicable privacy regulations. Provide fallback verification via manager attestation with explicit flags in the ledger. Expose confidence scores and verification status in the timeline for transparency.

Acceptance Criteria
MFA Enrollment and Authentication Binding
Given a new participant with an unverified account, When they enroll an MFA factor (TOTP, SMS, or push), Then the system binds the factor to the identity record and requires MFA on next login. Given a participant with enrolled MFA, When they authenticate, Then login succeeds only after correct primary credentials and successful MFA, and the ledger records factor type, success, timestamp, IP, and device identifier. Given a participant changes or disables an MFA factor, When the change is saved, Then all active sessions are revoked, a confirmation is sent to a previously verified contact, and the ledger records the factor change event. Given a user requests issuance of an access code, When they have not passed MFA within the last 10 minutes, Then issuance is blocked with a specific error and the ledger notes "MFA not recent".
Government ID Scan with Liveness Detection
Given a participant submits a government ID image and a liveness selfie/video, When the verification is processed, Then document authenticity and liveness must meet configured thresholds (>= 0.85) and selfie-to-ID match must meet similarity (>= 0.85) or the attempt fails. Given a successful ID verification, Then only derived attributes (full legal name, DOB, document type, last 4 of document number, issuing country) are stored; raw images/video are purged within 24 hours unless a retention hold is set; all stored artifacts are encrypted. Given a failed or below-threshold result, Then identity status is set to "Unverified", access code issuance is blocked, and the ledger records the failure reason and scores. Given retry limits of 3 attempts per 24 hours, When the limit is exceeded, Then further attempts are blocked until the window resets and the event is logged.
Device Binding Enforcement and Re-Verification on Change
Given a user completes MFA on a new device, Then a device fingerprint is computed, bound to the identity, and the binding event is recorded in the ledger. Given an access code issuance request from an unbound device, Then step-up MFA and explicit device binding are required before issuance; otherwise issuance is denied. Given the device fingerprint changes materially for a bound device, Then active sessions on that device are invalidated, re-authentication is required, and a "device change" event is logged. Given an on-site geofence or NFC event is recorded, Then the bound device identifier is captured with the event; mismatches between event device and bound device are flagged in the ledger.
Contact Verification (Email/SMS) with OTP and Rate Limiting
Given a user provides an email and/or phone, When OTPs are sent, Then each OTP is single-use, expires in 5 minutes, and sending is rate-limited to 5 per channel per hour and 10 attempts per day. Given a correct OTP within validity, Then the contact channel is marked verified with timestamp and method, and the ledger records the verification success. Given 3 consecutive failed OTP attempts on a channel, Then that channel is locked for 15 minutes and an alert is sent to any other verified channel if available. Given an unverified contact channel, Then it cannot be used for password resets, critical notifications, or approvals for access code issuance.
Identity Artifacts and Verification Transparency in Timeline and Exports
Given an access code is issued, Then the ledger entry includes linked identity artifacts (MFA last success time, ID verification outcome and scores, bound device ID, contact verification status) and a unique artifact hash for tamper evidence. Given an on-site entry/exit event (geofence/NFC), Then the timeline shows authenticated identity, bound device ID, geolocation/NFC tag ID, timestamp, and confidence scores; any missing artifact displays "Not Verified" with reason. Given a timeline is exported to PDF or JSON, Then verification statuses and scores are included with redacted PII (email masked, phone last 2 digits, ID doc last 4), and the export is cryptographically signed and time-stamped. Given any ledger record is altered after creation, Then the hash chain verification fails and a tamper-evidence alert is visible in the audit export.
Consent Capture, PII Minimization, Encryption, and Retention Enforcement
Given a user starts identity verification, Then they must accept a versioned consent that states purpose, retention period, and data usage; consent timestamp, IP, and policy version are stored in the ledger. Given PII is stored, Then all PII fields are encrypted at rest (AES-256) and in transit (TLS 1.2+); access requires appropriate role permissions and all reads/writes are audit-logged. Given configured retention policies (e.g., 7 days for raw biometrics, 24 months for derived attributes), Then a scheduled job deletes or detaches data on schedule, writes deletion logs, and the timeline shows "artifact expired" without breaking hash continuity. Given an export or data access is requested by an unauthorized role, Then the operation is denied and logged; authorized exports require a justification entry and are rate-limited.
Manager Attestation Fallback with Explicit Ledger Flags and Thresholds
Given automated verification is unavailable or fails, When a manager performs a fallback attestation, Then they must select a reason code, provide notes, optionally upload supporting documents, and set an attestation confidence; the ledger flags the identity as "Attested" with manager identity and timestamp. Given an identity is attested, Then access code issuance requires manager approval within the last 24 hours and the timeline displays an "Attested" badge; automatic dispatch based solely on attested identities is blocked unless an explicit override is recorded. Given automated verification later succeeds for the same identity, Then the attestation flag is superseded, the ledger records the transition, and the confidence score is updated to reflect the automated result. Given an attested identity is used for on-site events, Then all related timeline entries are flagged and included in exports for owner review.
Geofence/NFC Presence Validation
"As a landlord, I want on-site presence verification for entries and exits so that I can confirm the vendor actually attended the unit."
Description

Validate physical presence at the property by combining mobile geofencing and on-site NFC/BLE check-ins. Support configurable radius, dwell time thresholds, and grace periods; detect mock-location/spoofing and require secondary proof when signals are suspicious. Correlate presence proofs with lock events and code usage to confirm authorized entry and exit. Support offline capture with delayed sync, multiple entry points per property, and per-property policy controls. Flag timeline discrepancies when lock activity lacks presence evidence.

Acceptance Criteria
Geofence Radius and Dwell-Time Validation with Grace Period
Given a property policy with geofenceRadius=75m, dwellTime=120s, gracePeriod=60s and a verified technician identity When the technician’s device GPS enters the 75m radius and remains inside for at least 120s within any contiguous 180s window Then the system records a presence proof as "Valid - Geofence" with entry timestamp, accuracy, and policy version Given the technician exits the geofence before completing dwell time but re-enters within the 60s grace period When total in-radius time sums to >=120s within the grace window Then the presence proof is marked valid and the grace utilization is logged Given the technician never accumulates the configured dwell time within the grace window When the time window closes Then no presence proof is created and the attempt is logged as "Insufficient dwell" Given the device location accuracy reading exceeds 50m for >50% of samples during dwell evaluation When presence is otherwise eligible Then the system marks the proof as "Low Accuracy" and requires an on-site NFC/BLE check-in or secondary proof per policy
On-site NFC/BLE Check-in Correlated to Smart Lock Code Use
Given an entry point with registered NFC tag UID=TAG-A and BLE beacon ID=BEACON-A and a technician assigned a valid lock code When the technician taps TAG-A or is within 2m RSSI threshold of BEACON-A and confirms check-in Then the system records a presence proof "Valid - On-site Check-in" with tag/beacon ID, timestamp, device ID, and user ID Given a successful on-site check-in When the assigned smart lock code is used within ±5 minutes of the check-in timestamp at the same property Then the entry event is correlated to the presence proof and the timeline shows "Authorized Entry - Correlated" Given an on-site check-in occurs When no lock activity is detected within the correlation window Then the presence proof remains valid but is labeled "No lock correlation" and the system awaits exit events Given a recorded exit via NFC/BLE at the same property When the technician performs an exit check-out within ±5 minutes of lock relock or geofence exit Then the presence proof is updated with exit timestamp and duration
Mock-Location/Spoofing Detection and Secondary Proof Escalation
Given a device reports "mock location enabled" or emulator indicators or inconsistent sensor fusion (GNSS vs Wi‑Fi delta >300m) during a check-in attempt When a geofence arrival is detected Then the event is flagged "Suspect Location" and auto-validation is blocked pending secondary proof per policy Given a presence attempt is flagged as suspect When the technician submits a liveness selfie with dynamic challenge and a photo of the property entry (both GPS/EXIF + server time watermark) within 10 minutes Then the system validates challenges, verifies proximity (<=75m), and upgrades the presence to "Valid - Secondary Proof" Given a presence attempt is flagged as suspect When secondary proof is not provided within the policy window (e.g., 15 minutes) Then the attempt is marked "Failed - Secondary Proof Timeout" and cannot correlate to lock events as authorized presence Given velocity/telemetry indicates implausible motion (e.g., >150 km/h within 2 minutes of check-in) When evaluating presence validity Then the system auto-flags as "Suspect" and requires secondary proof regardless of other signals
Multiple Entry Points Presence Proof Aggregation
Given a property with entry points A and B, each with distinct geofence zones and NFC/BLE identifiers When a technician checks in at entry point A but uses the assigned lock code at entry point B within ±3 minutes Then the system aggregates proofs at the property level and marks the entry as "Valid - Cross-Entry Correlated" if policy allows cross-entry correlation Given cross-entry correlation is disabled by property policy When check-in and lock usage occur at different entry points Then the system marks the correlation as "Rejected - Entry Mismatch" and flags a discrepancy Given a technician moves between entry points during a job When separate presence signals exist for A and B within the same job window Then the timeline consolidates into a single job presence interval with segmented entry-point annotations
Offline Presence Capture with Delayed Sync Integrity
Given the technician’s device is offline with no network connectivity When the technician performs an NFC/BLE check-in and captures required photos Then the app stores events locally with monotonic timestamps, device signature, and a tamper-evident hash chain Given offline events are stored locally When the device reconnects within the policy sync window (e.g., 24 hours) Then the app uploads the batch, the server verifies hash continuity and device signature, and creates server-signed presence proofs with original timestamps adjusted for server time skew Given the device clock skew exceeds 5 minutes relative to server time When processing uploaded offline events Then the system normalizes timestamps using server receipt time and embedded monotonic deltas, and labels the proofs as "Clock Adjusted" Given offline events are uploaded after the policy sync window When validation runs Then the system marks presence as "Late Upload" and applies correlation/backfill rules per property policy
Timeline Discrepancy Flagging for Lock Events Without Presence
Given a lock "Unlock" event is received for a property When no valid presence proof exists in the window [-10 minutes, +10 minutes] around the event per policy Then the system creates a timeline discrepancy of type "Lock Without Presence", severity=High, and notifies the owner/manager Given a discrepancy "Lock Without Presence" exists When a valid presence proof is backfilled within the allowable backfill window (e.g., 30 minutes) and correlates to the event Then the discrepancy is auto-resolved with an audit note linking the proof Given repeated discrepancies (>3) occur for the same user within 30 days When generating reports Then the export includes a risk indicator and counts for that user and property
Per-Property Policy Controls Enforcement
Given a property-level policy defines geofenceRadius, dwellTime, gracePeriod, correlationWindows, secondaryProofRules, offlineSyncWindow, and crossEntryCorrelation When presence and lock events are processed for that property Then the system applies the property’s policy values and records the policy version on each proof for auditability Given a property’s policy is updated by an admin When new events occur after the change Then only events after the effective timestamp use the new policy; historical proofs retain the prior policy version Given a property without custom policy When events are processed Then the system applies the organization defaults and records that defaults were used
Annotated Photo Timeline & Notes
"As a vendor, I want to add annotated photos and notes to the access timeline so that I can document property condition and actions taken."
Description

Enable capture of entry/exit photos and notes directly from the mobile app and web, automatically timestamped, geotagged, and associated with the specific job and access event. Support multi-photo uploads, markup/annotations, redaction tools (e.g., blur PII), OCR for text extraction, and size optimization for fast upload. Maintain immutable originals with versioned annotations and clear authorship. Provide role-based visibility controls, offline capture with queued sync, and linkage to condition checklists to create a clear, auditable narrative of work performed.

Acceptance Criteria
Mobile Entry Photo Capture with Auto Timestamp & Geotag
Given a logged-in Vendor at an active Job with an open Access Event and camera/location permissions granted When the user taps "Capture Entry" and takes between 1 and 10 photos Then each photo is saved with an ISO 8601 UTC timestamp and local timezone display, GPS lat/long with ≤30 m accuracy (or accuracy="approximate" if >30 m or unavailable), associated to the JobID and AccessEventID, and tagged with UserID, Role, and DeviceID And the immutable original file is stored, and a timeline Entry event appears within 3 seconds of upload completion And if geofence is not validated, the capture is allowed but flagged "Out of geofence" and highlighted in the timeline And if permissions are denied, the user is prompted to enable them and no photo is saved until granted
Multi-Photo Upload and Size Optimization (Mobile & Web)
Given a user selects between 2 and 20 images via mobile gallery or web drag-and-drop for an active Job/Access Event When the upload begins Then originals (up to 25 MB each) are preserved immutably in storage And an optimized derivative is generated client-side per image with max dimension 1920 px and JPEG quality 80–85% targeting ≤2 MB And per-item progress is displayed, with cancel and retry controls And uploads use chunking and resume after interruptions without duplicating files And any failed items are reported individually with error codes and are retryable without re-uploading successful items
Annotations, Markup, and Versioned Edits with Authorship
Given a user with Edit permission opens a photo from the timeline When they apply markup (freehand, arrow, rectangle, highlight, text label) or add a note Then a new annotated version v{n+1} is created without altering the immutable original And the version history lists v1 (original) and each subsequent version with author (UserID), timestamp, and change summary And reverting creates a new version rather than overwriting prior versions And notes are stored as structured metadata with authorship and timestamps and can be edited without modifying the image binary
PII Redaction via Blur with Audit Trail and Role Limits
Given a user with Redact permission opens an image or annotated version When they apply a blur redaction to selected regions and save Then a derivative version is created where the redacted pixels are irreversibly obfuscated (Gaussian blur/pixelate kernel ≥15 px) And the redaction is labeled as Redaction in metadata with who/when/why (free-text reason) And unredacted originals remain invisible to Owner and Tenant roles; only redacted derivatives are served to those roles And audit logs record redaction create/update/revert events and the actor, and Vendors cannot remove or reduce redactions
OCR Text Extraction and Searchable Metadata
Given a photo (original or annotated) is saved and OCR is enabled When the OCR pipeline runs Then text is extracted in English and Spanish with word-level confidence scores and only text with confidence ≥0.60 is stored And extracted text is stored as searchable, indexable metadata linked to the image and visible to roles with Metadata-View permission And redacted regions are excluded from OCR input And if offline or OCR fails, the system retries up to 5 times over 24 hours and surfaces status as Pending, Complete, or Failed And users can copy OCR text from the UI where permitted
Offline Capture with Queued Sync and Conflict Handling
Given the device is offline and the user captures photos and adds notes for an active Job/Access Event When the user saves Then items are stored locally with AES-256 encryption at rest, marked Queued, and show local timestamps and geotags And upon connectivity restoration, queued items automatically sync, preserving original capture timestamps and geotags And uploads retry with exponential backoff up to 24 hours; failures are user-visible with retry controls And if the associated Job/Access Event is closed or deleted before sync, the user is prompted to reassign or discard; no data is lost without explicit discard And duplicate detection via checksum prevents duplicate originals on re-sync
Role-Based Visibility and Checklist Linkage
Given roles exist (PM, Vendor, Owner, Tenant) and a Job has an attached condition checklist When a photo or note is added Then the contributor can link it to 0–5 checklist items; linked items display on the timeline and in checklist views And default visibility applies: PM sees all originals and versions; assigned Vendor sees originals and their own and PM annotations; Owner sees only redacted derivatives and notes marked Share with Owner; Tenant sees entry/exit items for their unit only, redacted derivatives, and no private notes And PM can override visibility per item via a Share With control without exposing unredacted originals to Owner/Tenant And exports and API responses honor visibility and redactions for the requesting role
Audit Export & Secure Sharing
"As an owner, I want to export and securely share the access ledger so that external stakeholders can verify access without needing a FixFlow account."
Description

Produce audit-grade export packages in PDF (human-readable summary) and JSON/CSV (raw events) that include hash chain proofs, checksums, and digital signatures for third-party verification. Allow scoped exports by date range, job, property, or vendor; include code lifecycle, identity checks, presence validations, photos, and notes. Provide owner-branded formatting, expiring share links with access controls and view logs, and webhooks for delivery to owner storage. Include a lightweight verification utility so recipients can independently validate integrity without a FixFlow account.

Acceptance Criteria
Generate Cryptographically Proven Export Package
Given an authorized owner selects export formats PDF and JSON/CSV for a specific scope, When the export is initiated, Then a single downloadable ZIP is generated containing summary.pdf, events.json and/or events.csv (as selected), manifest.json, proofs.json, checksums.txt, signature.sig, and public_key.pem. Given the generated ZIP, When SHA-256 is computed for each included file, Then each hash matches the corresponding entry in checksums.txt. Given manifest.json and proofs.json, When the event hash chain is recomputed in sequence, Then all links validate and the terminal hash matches the root hash recorded in manifest.json. Given signature.sig and public_key.pem, When verifying the signature over manifest.json, Then verification succeeds and the signer key matches public_key.pem. Given the export completes, When the download is initiated, Then the ZIP filename includes the scope identifier and an ISO 8601 UTC timestamp.
Scoped Export Filters (Date, Job, Property, Vendor)
Given a date range and one or more filters (job, property, vendor) are selected, When an export is generated, Then only events matching all selected filters are included. Given a date range and a property timezone, When the export is generated, Then the start boundary is inclusive at 00:00:00 and the end boundary is inclusive at 23:59:59 of the selected timezone unless explicit times are provided. Given no events match the selected scope, When the export is generated, Then a valid package is produced with summary.pdf stating "No events in scope" and empty events files, with valid manifest, checksums, and signature. Given an export is generated, When counting events in events.json/CSV, Then the count equals manifest.json.event_count.
Complete Content Coverage in Exports
Given an export package is generated, When inspecting event records, Then code lifecycle events (create, activate, rotate, revoke), identity checks, presence validations (geofence/NFC), entry and exit timestamps, photos, and notes are present where applicable. Given photos are included, When validating files, Then each photo exists as an original binary with metadata (filename, MIME type, size, SHA-256) and is referenced by event ID, and the summary.pdf displays annotated thumbnails with timestamps and captions. Given notes are included, When inspecting, Then each note records author identity, ISO 8601 timestamp, and redaction markers where applied. Given optional media or notes are absent for an event, When rendering summary.pdf, Then placeholders indicate absence without errors or broken references.
Owner-Branded PDF Summary
Given an owner with configured brand assets (logo and colors), When generating summary.pdf, Then the document applies the owner logo, color palette, and displays the owner name on cover and headers. Given brand assets are not configured, When generating summary.pdf, Then the FixFlow default theme is used and a footer note indicates default branding. Given summary.pdf is generated, When comparing to raw data files, Then branding does not alter hashes of raw event data; only presentation files are branded. Given summary.pdf is generated, Then each page footer includes "Generated by FixFlow" and the UTC timestamp of generation.
Expiring Share Links with Access Controls and View Logs
Given an owner creates a share link with a TTL and optional passcode/role restrictions, When the link is accessed before expiry with valid credentials, Then the package is viewable and downloadable. Given the same share link after TTL expiry or after manual revocation, When it is accessed, Then access is denied with an explicit expiry/revocation message and no package bytes are served (HTTP 403/410). Given a share link is used, When the package is viewed or downloaded, Then a view log entry is recorded with timestamp (UTC), IP address, user-agent, viewer identity where available, and outcome (success/denied). Given an owner requests the view log for a share link, When retrieved, Then all entries are returned in chronological order and can be exported as CSV.
Webhook Delivery to Owner Storage
Given an owner-configured delivery endpoint with a shared secret, When an export completes, Then the system sends an HTTPS POST containing export metadata (including manifest) and a signature header (HMAC-SHA256) and/or uploads the package to the configured storage target as specified. Given the receiver computes the HMAC using the shared secret, When compared to the signature header, Then the values match and the request is accepted. Given the endpoint returns a non-2xx status or times out, When delivery is attempted, Then retries occur with exponential backoff up to 5 attempts and are idempotent via a stable delivery_id. Given a delivery attempt completes, When checking delivery logs, Then success or failure with HTTP status and timestamp is recorded.
Standalone Verification Utility (No Account Required)
Given a recipient downloads the verification utility (CLI or browser page), When they provide an exported package, Then the utility verifies file checksums, hash chain integrity, and the signature over manifest.json without requiring FixFlow authentication or network access. Given all integrity checks pass, When results are displayed, Then the utility outputs an overall PASS and per-check results (checksums, chain, signature) as PASS. Given any file is tampered or missing, When verification runs, Then the utility outputs FAIL and identifies the failing component and reason. Given the public key is invalid or absent, When verification runs, Then signature verification fails with a clear error message and remediation instructions to supply the correct key.

Cap Matrix

Define granular spend caps by unit, category (plumbing, HVAC, appliances), urgency level, and time period (per visit, monthly, quarterly). Under‑cap work auto‑approves and dispatches; over‑cap items auto‑route for review. Portfolio templates let you roll policies to new units in minutes, keeping costs predictable without slowing emergencies.

Requirements

Cap Rules Engine
"As a property manager, I want to set granular spending caps by unit, category, urgency, and time period so that maintenance costs stay predictable without manual approvals for routine issues."
Description

Implements a configurable rules engine that defines spending caps by unit, category (e.g., plumbing, HVAC, appliances), urgency level (emergency, urgent, routine), and time window (per visit, monthly, quarterly). Supports rule inheritance and precedence across portfolio → property → unit, with sensible defaults and conflict detection. Provides a UI and API for creating, validating, and testing rules, including currency, tax/fees inclusion options, and whether caps apply to labor, materials, or total. Evaluates caps synchronously during intake and prior to dispatch, ensuring fast performance and deterministic outcomes across timezones.

Acceptance Criteria
Synchronous Cap Evaluation at Intake and Dispatch
Given a valid maintenance request with unitId, category, urgency, cost breakdown (labor, materials, taxesFees), currency, and timestamp in any timezone When the request is submitted to the intake API Then the cap decision is computed synchronously and returned in the same response with outcome ∈ {auto_approve, needs_review}, ruleId, appliedScope ∈ {labor, materials, total}, includeTaxesFees flag, capAmount, spendToDate, remainingAmount, windowStart, windowEnd, and rationale code. Given the same request payload When evaluated by the pre-dispatch check Then the decision outcome and numeric fields are identical to the intake decision within the same time window and timezone. Given identical inputs repeated within 60 seconds When evaluated multiple times Then results are deterministic and idempotent (same outcome and values).
Create and Validate Cap Rule With All Dimensions
Given the UI or API is used to create a rule specifying portfolio/property/unit scope, category, urgency, timeWindow ∈ {per_visit, monthly, quarterly}, capAmount (>=0), currency (ISO 4217), appliesTo ∈ {labor, materials, total}, includeTaxesFees ∈ {true,false} When the rule is submitted Then it is persisted with a unique ruleId and is retrievable via GET with all fields. Given missing or invalid fields (e.g., negative capAmount, unknown currency code, invalid timeWindow, invalid appliesTo) When submitted Then the API returns 400 with machine-readable error codes and the UI blocks save with inline validation. Given a rule with capAmount=0 When evaluated Then any non-zero applicable cost yields needs_review with rationale "cap_exceeded_zero". Given a rule with includeTaxesFees=false When evaluated Then taxes and fees are excluded from the spend calculation; if true then included. Given appliesTo=labor/materials/total When evaluating a request with cost breakdown Then only the specified components are used in cap comparison.
Rule Inheritance and Precedence Resolution
Given portfolio-, property-, and unit-level rules that all could apply When evaluating a request for a unit Then precedence is unit > property > portfolio; the highest-precedence matching rule is used. Given two rules at the same scope with overlapping filters (same category, urgency, timeWindow) When saved Then the system rejects the save with conflict error listing conflicting ruleIds and overlap details. Given no matching rule exists at any scope When evaluating a request Then the outcome is needs_review with rationale "no_matching_rule". Given a rule marked as stopInheritance=true at property scope When evaluating a unit under that property Then portfolio-level rules that would otherwise apply are ignored.
Automatic Decisioning Under and Over Cap
Given a matching rule and a computed applicableCost and remainingAmount in the active window When applicableCost <= remainingAmount Then outcome is auto_approve; when applicableCost > remainingAmount Then outcome is needs_review with rationale "cap_exceeded". Given applicableCost equals remainingAmount exactly When evaluated Then the outcome is auto_approve. Given the request urgency is emergency and a matching rule exists When evaluated Then the same comparison logic applies; no special bypass occurs unless explicitly configured by a rule. Given the request lacks a required cost breakdown for the rule’s appliesTo setting When evaluated Then the outcome is needs_review with rationale "insufficient_cost_data". Given a request is auto_approved at intake When dispatch is triggered for the same request within the same window Then no additional approval is required and the same ruleId is referenced on the dispatch record.
Time Window Aggregation and Reset Across Timezones
Given a property timezone TZ and a monthly timeWindow rule When evaluating spend on the last and first days around month boundaries in TZ Then spend aggregates per calendar month in TZ; windows reset at 00:00:00 local time in TZ, respecting DST transitions. Given a quarterly timeWindow rule When evaluated Then quarters align to Jan–Mar, Apr–Jun, Jul–Sep, Oct–Dec in the property timezone. Given a per_visit timeWindow rule When evaluated Then only the current request’s applicableCost is compared to cap; prior spend is not aggregated. Given requests created in different origin timezones but for the same property TZ When evaluated Then aggregation and remainingAmount are consistent and independent of the client’s timezone.
Performance and Scalability of Cap Evaluation
Given a production-like rule set of 10,000 rules across 1,000 units When evaluating requests at 100 RPS sustained for 5 minutes Then p95 decision latency ≤ 200 ms and p99 ≤ 400 ms measured at the API boundary; error rate ≤ 0.1%. Given cold start conditions (empty caches) When processing the first 1,000 evaluations Then p95 decision latency ≤ 300 ms. Given a single evaluation When performed Then the API returns within 100 ms for simple per_visit rules at p95.
Rule Test Harness via UI and API
Given a draft or active rule set When a user submits a dry-run test via UI or POST /rules/test with unitId, category, urgency, cost breakdown, and timestamp Then the response returns the same decision payload structure as live evaluation and does not persist any changes. Given an invalid test payload When submitted Then the API returns 400 with validation details identical to live evaluation. Given multiple saved test cases in the UI When run in batch Then the system shows pass/fail per case with the evaluated ruleId and rationale codes.
Under-Cap Auto-Approval & Dispatch
"As an independent landlord, I want under-cap work to auto-approve and dispatch so that repairs move forward quickly without my intervention."
Description

Automatically approves and dispatches work orders when the estimated cost falls under the applicable cap. Generates a cap-aware purchase order limit on the work order, selects a vetted vendor from the appropriate pool, schedules the visit, and notifies tenants and owners. Blocks vendor invoices from exceeding the cap without explicit approval, and re-checks caps if scope or estimate changes during the job.

Acceptance Criteria
Applicable Cap Evaluation Across Time Windows
Given a new work order for unit U with category C, urgency L, and estimated cost E And active caps exist for U by C and L for per-visit, monthly, and/or quarterly periods with remaining amounts RPv, RM, RQ (nullable) When the work order is submitted Then the system evaluates E against each applicable remaining amount And sets capEvaluation = "UNDER_CAP" if E <= all non-null remaining amounts And sets capEvaluation = "OVER_CAP" if E > any applicable remaining amount And stores an evaluation snapshot including cap IDs, remaining amounts, E, and timestamp on the work order
Auto-Approval, Vendor Dispatch, and Scheduling When Under Cap
Given capEvaluation = "UNDER_CAP" on submission And a vetted vendor pool exists for category C in the service area of unit U and supports urgency L When the work order is processed Then the system sets status = "Approved" and dispatches a vendor from the appropriate pool per configured dispatch policy And creates a scheduled visit with the vendor's next available slot And sends notifications to the tenant and owner including vendor, date/time, and PO limit And completes all actions within 2 minutes of submission
Cap-Aware Purchase Order Limit Generation
Given capEvaluation = "UNDER_CAP" When generating the purchase order for the work order Then PO.limitAmount = minimum of all applicable remaining cap amounts at the time of approval And PO.limitAmount is displayed on the work order and in the vendor portal And PO.currency matches the property's currency And the PO is attached to the vendor dispatch record
Invoice Submission Block Above Cap Without Approval
Given a work order with PO.limitAmount = L and current invoicedTotal = I When a vendor attempts to submit an invoice with amount T such that I + T > L Then the system blocks submission with error "Invoice exceeds cap — approval required" And sends an approval request to the designated approver And logs the attempt on the work order audit trail And if explicit approval is granted for an updated limit L2 >= I + T, then the invoice is accepted and the PO.limitAmount is updated to L2
Re-evaluate Caps on Estimate or Scope Change
Given an in-progress under-cap work order with estimate E and PO.limitAmount = L When the estimate E is increased or new scope items are added changing E' > E Then the system re-evaluates caps using E' against current remaining per-visit, monthly, and quarterly amounts And if E' exceeds any applicable remaining cap, the work order is put on hold with status "Needs Review", dispatch pauses, and tenant, vendor, and owner are notified And if E' remains under all applicable caps, the PO.limitAmount is recalculated to min(applicable remaining amounts) and updated; changes are recorded in the audit trail
Reserve and Reconcile Remaining Budgets for Monthly/Quarterly Caps
Given a monthly or quarterly cap with remaining amount R at time of auto-approval When a work order is auto-approved with PO.limitAmount = L Then the system reserves L against the period's remaining amount so updated remaining = R - L And subsequent cap evaluations in the same period use the updated remaining And when the work order is closed with final invoiced total F <= L, the system releases L - F back to the remaining amount And all reservations and releases are captured in the audit trail
Over-Cap Review & Escalation
"As a portfolio owner, I want over-cap requests to route for review with clear context and fast approval options so that I control exceptional spend without delaying decisions."
Description

Routes work orders exceeding caps to the correct approver with contextual details (estimates, photos, history) and one-tap approve/deny/adjust options. Supports configurable SLAs, reminders, and escalation paths to backups if approvals stall. Allows temporary overrides with revised limits and captures rationale. Re-evaluates the request on approval to continue dispatch flow seamlessly.

Acceptance Criteria
Auto-Route Over-Cap Work Order to Primary Approver
Given a work order is created or updated with an estimate total exceeding any applicable cap (per visit, monthly, or quarterly) for its unit, category, and urgency level When the system evaluates caps Then the work order status changes to "Awaiting Approval" within 2 seconds And the request is routed to the configured primary approver for that policy within 10 seconds And an in-app and email notification is sent to the primary approver containing the work order ID and deep link And the work order is not dispatched to a vendor until approval is granted And if no primary approver is configured, the request is routed to the organization's default approval queue within 10 seconds
Approver Sees Contextual Evidence Package
Given the approver opens the approval screen for an over-cap work order When the view loads Then it displays in a single screen: estimate total and line items, applicable cap(s) and time window(s), variance amount and percentage, unit and vendor details, last 3 related work orders, attached photos and annotated timeline, and requester notes And the view loads in ≤ 2 seconds for 95% of requests with ≤ 10 photos And all displayed data matches the latest system records at the time of load
One-Tap Approve/Deny/Adjust with Input Validation
Given a pending over-cap approval and the user has approval permission When the user taps Approve Then the system records approver identity and timestamp and marks the request as Approved within 1 second And the system proceeds to dispatch flow When the user taps Deny Then the system requires a denial reason of at least 10 characters before submission And upon submission, the system records the denial, notifies the requester, and stops dispatch When the user taps Adjust Then the system requires a revised limit amount that is numeric and ≥ the current estimate total and a rationale of at least 10 characters And invalid inputs are blocked with inline error messages and no state change occurs And upon valid submission, the system records the override and marks the request as Approved (Adjusted) within 1 second
SLA Reminders and Escalation Path Enforcement
Given an approval SLA configuration exists for the portfolio (e.g., SLA = 2 hours; reminders at 30 minutes and 90 minutes; escalation to backup approver at 2 hours) When an over-cap request enters "Awaiting Approval" Then the system schedules reminders per configuration And sends reminders at the configured times if still pending (in-app and email) And if the SLA time elapses with no decision, the system routes the request to the next approver in the configured escalation path within 5 minutes And the prior approver remains able to act but is marked as superseded by escalation And all reminder and escalation events are logged
Temporary Override with Time-Bound Revised Limits and Rationale
Given an approver chooses Adjust on a pending over-cap request When they enter a revised temporary cap amount, select scope as "this work order only", and set an expiry (date/time or "until work order completion") with a rationale ≥ 10 characters Then the system validates amount > 0 and required fields And upon save, applies the override only to the specified scope and until the specified expiry And displays the effective cap and expiry on the approval screen and work order header And after expiry or work order completion, automatically reverts to the baseline cap policy
Post-Approval Re-Evaluation and Seamless Dispatch
Given an over-cap request is Approved or Approved (Adjusted) When the approval is recorded Then the system re-evaluates the request against the effective cap immediately And Approve bypasses cap checks for this request and resumes dispatch flow without requiring additional approvals And if Approved (Adjusted) and the revised cap covers the estimate, the system auto-dispatches per portfolio dispatch rules within 10 seconds And if the action was Deny, the system cancels dispatch and notifies the requester with the reason And duplicate vendor notifications are prevented on repeated approvals (idempotent)
End-to-End Audit Trail and Notification Logging
Given any approval lifecycle event occurs (route, reminder, escalation, approve, deny, adjust) When the event is processed Then the system appends an immutable audit entry with timestamp (UTC), actor, previous value, new value, rationale (if any), notification delivery results, and SLA state And the full audit trail is viewable in the work order timeline and exportable to PDF and JSON And audit entries are searchable by work order ID and date range And existing audit entries cannot be modified; corrections are recorded as new entries linked to the original
Portfolio Policy Templates & Bulk Apply
"As a small property manager, I want to roll out standardized cap policies across my portfolio so that I can onboard new units quickly and keep policies consistent."
Description

Enables creation of reusable cap policy templates that bundle rules across categories, urgencies, and periods. Supports bulk application to properties and units, inheritance with per-unit overrides, versioning, preview of impacted units, and safe rollout with change summaries. Provides import/export to replicate policies across portfolios in minutes.

Acceptance Criteria
Create and Save Cap Policy Template
- Must allow adding rules with dimensions: category ∈ {Plumbing, HVAC, Appliances, ...}, urgency ∈ {Emergency, High, Standard}, period ∈ {Per Visit, Monthly, Quarterly}, capAmount > 0 in portfolio currency. - Template must require a unique name within the portfolio; name length ≤ 100; optional description length ≤ 500. - Saving requires at least one rule; on success, template is persisted with version = 1 and listed in the template library. - Invalid inputs block save and display field-specific error messages identifying the offending field and rule index.
Bulk Apply Template with Impact Preview
- User can select a template and target scope (properties and/or units) and system resolves the total impacted unit count before confirmation. - Preview shows: counts of units to be updated, rules per category/urgency/period to be applied, and number of units with existing overrides that will be preserved. - Confirming applies the template atomically per property; reapplying the same template to the same scope is idempotent (no duplicate or conflicting rules created). - Completion provides a summary with counts of units updated, units skipped, and failures, with a downloadable detailed report.
Inheritance and Per-Unit Overrides Resolution
- Effective rule precedence is Unit override > Property override > Portfolio template. - Per-unit overrides persist through future template version rollouts unless the user explicitly selects "reset overrides" during rollout. - Unit view displays the effective cap value and its source (Portfolio/Property/Unit) for each category/urgency/period. - Removing a unit-level override reverts the effective value to the inherited source without altering the template.
Template Versioning, Rollout, and Rollback
- Editing a template creates a draft; publishing increments the version number by 1 and locks prior versions read-only. - Publishing requires review of a generated change summary and explicit confirmation of rollout scope (all inheritors or selected) and timing (immediate or scheduled date/time). - Rollout applies only the diffs between versions to the selected scope and records old vs new values per rule. - Rollback to the previous version restores prior effective rules for the same scope and records a reversal summary.
Change Summary Generation for Safe Rollouts
- Pre-rollout summary lists added/removed/modified rules with before/after values and impacted unit counts grouped by property. - Post-rollout summary reports counts of successes, skips (due to overrides), and failures, and links to units requiring manual review. - Change summaries are exportable as CSV and JSON and are retained for at least 365 days.
Import Templates with Validation and Conflict Handling
- Import accepts a JSON file matching the template schema with required fields: name and rules[] of {category, urgency, period, capAmount}. - Dry-run mode validates schema and enumerations, detects duplicate template names, and presents a preview of rules and conflicts without persisting data. - On name conflict, user can choose to create a new version (if compatible) or create a new template with an auto-suffixed name; incompatible structures block import with explicit errors. - Successful import creates the template in the selected portfolio and displays an import summary with created version and rule counts.
Export Templates for Cross-Portfolio Replication
- User can export any template version to JSON and CSV that round-trip through import without data loss. - Export includes metadata (name, description, version, author, timestamps) and the full rules array. - Exports from one portfolio can be imported into another; any unmapped categories/urgencies are flagged during the import preview for user resolution.
Real-Time Cap Monitoring & Alerts
"As a landlord, I want real-time visibility and alerts on cap consumption so that I can avoid overruns and adjust policies proactively."
Description

Continuously aggregates spend and commitments against caps per unit/category/urgency and period, showing remaining budget in real time. Triggers alerts at configurable thresholds (e.g., 80%, 100%) and supports dashboards and filters. Handles period resets, partial invoices, revisions, and cancellations to maintain accurate cap consumption and avoid surprises.

Acceptance Criteria
Real-Time Remaining Budget Calculation
Given caps configured per unit, category, urgency, and period When a new commitment or approved invoice is recorded for a matching cap Then the consumed amount for that cap increases by the exact amount within 5 seconds And the remaining budget equals cap amount minus consumed and updates across unit, category, and dashboard views And monetary values are rounded to 2 decimal places per portfolio currency settings And duplicate submissions for the same work order revision do not change totals more than once
Configurable Threshold Alerts at 80% and 100%
Given threshold alerts configured at 80% and 100% for a cap When consumed crosses 80% for the first time in the period Then an Approaching Cap alert is generated within 5 seconds including unit, category, urgency, period start/end, cap amount, consumed, remaining, and percent used When consumed reaches or exceeds 100% Then a Cap Reached alert is generated within 5 seconds including the overage amount And alerts trigger only on threshold crossing events and do not repeat unless consumption drops below and crosses again And updates to threshold values affect future evaluations without issuing retroactive alerts
Cap Dashboard and Advanced Filters
Given the cap dashboard is open When the user filters by portfolio/property, unit, category, urgency, period type, threshold state (>=80%, >=100%), and over/under-cap status Then only caps matching all selected filters are displayed And each row shows Cap Amount, Consumed, Remaining, Percent Used, Period Start, Period End, Threshold State, and Last Updated timestamp And sorting by any visible column works and persists for the session And the dashboard returns results for up to 10,000 caps within 2 seconds at the 95th percentile
Cap Period Reset Behavior
Given a monthly cap aligned to the portfolio timezone When the period rolls over at local midnight on the first day of the month Then consumed resets to 0 and remaining resets to the cap amount for the new period And the prior period is archived read-only with final consumed, remaining, and alert history Given a per-visit cap When a new visit is created Then a new cap period instance is created and consumption for that visit is tracked independently And no consumption or alerts carry over between periods
Partial Invoices, Revisions, and Cancellations Handling
Given a work order with an initial commitment within an active period When a partial invoice is approved Then cap consumption for that work order equals the greater of total approved invoices-to-date or current commitment to avoid double counting When a commitment is revised up or down Then the cap consumption updates within 5 seconds to reflect the revision (or approved invoice total if greater) When a work order or invoice is canceled or voided Then the previously consumed amount for that item is removed from the period within 5 seconds And all recalculations are reflected consistently across all related views and dashboards
Data Freshness and Consistency Guarantees
Given any cap-related view is open When underlying spend or commitment data changes Then all open views reflect updated consumed and remaining within 5 seconds without manual refresh And data for a given cap is consistent across dashboard, unit page, work order page, and alert views with no discrepancies longer than 5 seconds And events are attributed to periods using the portfolio timezone to prevent misassignment due to clock skew or timezone differences
Emergency Override & Grace Caps
"As a property manager, I want emergencies to bypass normal caps within controlled limits so that critical repairs are not delayed while still maintaining spend governance."
Description

Provides urgency-aware logic that optionally auto-approves emergencies with a defined grace cap or elevated limit, then requires post-incident review. Ensures dispatch is never blocked for critical issues while enforcing maximum per-visit limits and documenting decisions. Configurable by category, time of day, and unit risk profile.

Acceptance Criteria
Auto-Approval: Emergency Under Grace Cap
Given unit 12A has Emergency Override enabled for Plumbing with grace cap $300 and per-visit max $1000 And a verified maintenance intake is classified as Emergency with severity Critical And the initial vendor triage estimate is $250 When the request is submitted Then the work order is auto-approved and a vetted vendor is auto-dispatched within 60 seconds And the authorization amount is set to $250 (≤ grace cap) And no manual approval is required pre-dispatch And an audit entry is created capturing cap type=Grace, cap value=$300, used=$250, classifier=Emergency, source=Estimator, timestamp, and actor=System
Elevated Limit: Over Grace Cap, Within Elevated Emergency Limit
Given unit 12A has Emergency Override configured for Plumbing with grace cap $300, elevated emergency limit $800, and per-visit max $1000 And the initial estimate is $700 When the request is classified as Emergency Then the vendor is auto-dispatched within 60 seconds And the authorization amount is set to $700 (capped by elevated limit) And a post-incident review task is created and assigned to the Owner Approver group with a due time of 24 hours after dispatch And notifications are sent to Owner and Property Manager with details of cap usage and authorization amount
Time-of-Day Rules: Nighttime Elevated Limit Applies
Given a building-wide Emergency Override nighttime window from 10:00 PM to 6:00 AM local time with elevated limit multiplier 2x (base grace cap $300 → nighttime elevated limit $600) And current local time is 11:15 PM And a qualifying Emergency in Plumbing has an estimate of $550 When the request is submitted Then auto-dispatch occurs within 60 seconds And the authorization amount is set to $550 (≤ nighttime elevated limit $600) And the audit entry records the time-window rule ID applied, computed elevated limit $600, and local time zone used
Category Rules: Dispatch-Only Override for Appliances
Given Appliances category is configured for Dispatch-Only Emergency Override (no grace cap, no elevated limit) with per-visit max $400 And a tenant submits an Emergency for a refrigerator failure categorized as Appliances with estimate $200 When the request is submitted Then the system auto-dispatches a vetted vendor within 60 seconds And the authorization amount is set to $200 (≤ per-visit max $400) with override mode=Dispatch-Only recorded And a post-incident review task is created due in 24 hours And the audit entry records that no grace/elevated cap was applied due to category policy
Risk Profile: High vs Low Unit Caps Applied
Given unit 9C has risk profile High with grace cap $500 and elevated limit $1200 And unit 2B has risk profile Low with grace cap $200 and elevated limit $600 And identical Emergency HVAC leak estimates of $700 occur on unit 9C and unit 2B When each request is classified as Emergency Then unit 9C auto-dispatches with authorization $700 and creates a post-incident review task due in 24 hours And unit 2B auto-dispatches with authorization $600 (capped at elevated limit) and flags the remaining $100 as pending approval And both events are logged with risk profile IDs and applied caps
Post-Incident Review: Creation, SLA, and Escalation
Given any Emergency Override (grace, elevated, or dispatch-only) was applied for a work order When the work order status transitions to In Progress Then a review task is created with due date 24 hours after dispatch and assigned to the Owner Approver group And if the task is not completed by the due time, an escalation notification is sent to the Owner and Property Manager, and the task priority is set to High And the review requires a decision of Approve Spend or Adjust/Recover, capturing notes and evidence attachments And the review outcome sets work order compliance=Pass/Fail and, when Fail, blocks further Emergency Overrides on the unit until resolved by an Admin
Per-Visit Maximum: Make-Safe NTE Enforcement
Given the per-visit maximum for unit 12A is $1000 regardless of override type And an Emergency sewer backup has either no reliable estimate or an estimate of $2500 When the request is submitted Then the vendor is auto-dispatched within 60 seconds with an NTE authorization of $1000 And vendor instructions specify to perform make-safe work up to the NTE and pause for additional approval thereafter And any invoice charges exceeding $1000 without post-approval are auto-flagged and blocked from payout And the audit trail records the NTE issuance, vendor acknowledgment timestamp, and cap enforcement status
Audit Trail & Policy Change Log
"As an owner, I want a complete audit log of cap decisions and policy changes so that I can resolve responsibility disputes and justify spend to stakeholders."
Description

Maintains an immutable audit trail of cap evaluations, approvals, overrides, and policy changes, including timestamps, actors, rule versions, and artifacts (photos, estimates, messages). Integrates with FixFlow’s photo-timeline to produce an auditable record for disputes and owner reporting. Supports exports and role-based access for compliance and transparency.

Acceptance Criteria
Cap Evaluation Logged with Rule Version and Outcome
Given a work order is evaluated against Cap Matrix policies When a cap decision is computed (under-cap, at-cap, over-cap) Then the system writes one immutable audit event containing: event_type="cap_evaluation"; work_order_id; unit_id; category; urgency; time_period; cap_rule_id; cap_rule_version; computed_amount; cap_threshold; decision; actor="system"; timestamp (UTC ISO8601 with milliseconds); correlation_id; request_id; source (portal|API|mobile) And the event is queryable by work_order_id within 1 second of decision And any attempt to update or delete audit events via API/UI is blocked and a "tamper_attempt" audit event is recorded with actor and reason And audit events for the same work order share the same correlation_id and are returned in deterministic order by timestamp then event_id
Approval and Override Decision Trail
Given a permitted user reviews a cap decision When they approve, reject, or override the decision Then an audit event is recorded with event_type in {"approval","rejection","override"}, user_id, role, auth_method, ip, timestamp, previous_decision, new_decision, justification (non-empty for overrides), and cap_rule_version And overrides require justification length >= 10 characters and capture attachment_refs when provided And the approval/override event references the related cap_evaluation via correlation_id And the system prevents approval actions after dispatch; any such attempt records a "rejected_action" audit event with reason
Policy Change Log with Diff and Effective Versioning
Given an admin edits a Cap Matrix policy or rolls out a portfolio template When the change is saved Then a "policy_change" audit event is recorded with policy_id, scope (portfolio|property|unit), fields_changed (before/after diff), change_note (required), editor user_id, timestamp, and new policy_version And effective_from is captured and cannot be earlier than timestamp And historical audit events remain bound to their original policy_version and are not retroactively altered And rolling a template to N units generates N "policy_change" events grouped by batch_id with counts of successes and failures
Artifact Attachment and Photo-Timeline Linkage
Given artifacts (photos, estimates, invoices, messages) are added or referenced on a work order When an artifact is uploaded or linked Then an "artifact_added" audit event records artifact_id, artifact_type, checksum (SHA-256), uploader (user_id or system), timestamp, and storage_ref And cap_evaluation, approval, and override events store links to the nearest photo-timeline frame_id at event time when available And artifact links in audit events remain immutable; replacements require creating a new artifact and corresponding audit event
Role-Based Access and Field Redaction
Given users with roles Owner, Property Manager, Vendor, or Auditor access the audit trail When a user queries audit events Then only events within the user's scope are returned, with redactions applied per role: Vendor (their work orders only; policy diffs and other vendors' PII redacted), Owner (their properties; vendor email masked), Property Manager (full for managed properties), Auditor (cross-portfolio read-only) And access checks occur at query time; denied requests return 403 and create an "access_denied" audit event And redacted fields include redaction_reason and policy_reference metadata And median query latency for 10k-event result sets is <= 2s and p95 <= 5s
Export with Integrity Verification and Tamper Evidence
Given a permitted user requests an audit export for a portfolio/property/unit and date range When the export is generated Then the system produces CSV and JSONL files containing all audit fields ordered by timestamp then event_id And a manifest includes export_id, creator user_id, created_at, filters, record_count, SHA-256 checksums for each file, and a detached signature of the manifest And files are delivered via pre-signed URLs expiring in <= 24 hours and purged from temporary storage within 48 hours And re-import validation verifies checksums and signature and reports PASS/FAIL with details
Search, Filter, and Pagination Performance
Given a user searches the audit trail When they filter by event_type, actor, unit_id, property_id, date range, decision, or policy_version and paginate Then the API returns correct results with total_count, page_size, page_token, and stable ordering by timestamp then event_id And filters are combinable and time zone inputs are normalized to UTC And for datasets up to 1,000,000 events, p95 response time is <= 3s for pages up to 200 items; timeouts return 504 and create a "query_timeout" audit event

Predictive Range

At intake, FixFlow predicts an expected cost range using issue type, photos, vendor rates, and historicals. The system sets a smart pre‑approval ceiling and warns when quotes or in‑progress totals trend over the forecast, helping you prevent overruns while keeping routine fixes moving without manual checks.

Requirements

Intake Cost Prediction Engine
"As an independent landlord, I want FixFlow to predict the expected cost range when a tenant submits an issue so that I can set expectations and automate approvals without risking unexpected overruns."
Description

Compute an expected low-to-high cost range at maintenance intake by combining issue classification, tenant-provided photos, free-text descriptions, vendor rate cards, property attributes, urgency, and historical job outcomes. Produce a confidence score and key drivers, and expose the prediction synchronously in the intake workflow and via an internal service API. Support incremental updates as new evidence arrives (e.g., additional photos, vendor diagnostics) and versioned models with safe fallbacks when inputs are incomplete. The output feeds downstream pre-approvals, dispatch decisions, and alerting to keep routine fixes moving while preventing overruns.

Acceptance Criteria
Synchronous Intake Prediction Display
Given a tenant submits a maintenance intake with issue type, description, property ID, urgency, and optional photos When the intake form is validated and submitted Then the system returns a predicted cost_low and cost_high, a confidence score (0.00–1.00, two decimals), top 3 key drivers, and a pre-approval_ceiling synchronously And p95 end-to-end response time (request to UI render) is ≤ 500 ms for complete inputs And currency and locale on the range match the property’s settings And the prediction payload is persisted with the intake ID and timestamp
Internal Prediction API Contract
Given a POST to /internal/predictions with valid payload (issue_type, description, photo_refs[], property_id, urgency, vendor_rate_context, request_id) When the request is processed Then the API responds 200 with {request_id, cost_low, cost_high, confidence, key_drivers[3]{name,impact}, model_version, features_used[], pre_approval_ceiling, currency, generated_at} And p95 service latency (ingress to egress) is ≤ 300 ms under nominal load And invalid payloads respond 400 with machine-readable error codes and do not mutate state And if the primary model is unavailable, respond 200 using the configured fallback model with flag fallback=true and emit an ops metric
Incremental Updates on New Evidence
Given an intake with an existing prediction When new evidence is attached (additional photo, vendor diagnostic, or corrected classification) Then a new prediction is computed within 5 seconds and versioned (prediction_version incremented) And the delta to cost_low/high and confidence is recorded with change_reason referencing the evidence IDs And if the new pre-approval ceiling changes by ≥ 10%, downstream consumers are notified via event prediction.updated and the UI reflects the update within 1 minute
Safe Fallback for Incomplete Inputs
Given an intake missing one or more primary features (e.g., no photos, unknown vendor rates) When a prediction is requested Then the engine uses default priors and regional average rates while marking completeness=false And the returned confidence ≤ 0.40 and the cost range width ≥ 2× the median width for that issue type And a key_driver item includes reason codes for missing inputs And the workflow is not blocked; a prediction is still returned and persisted with fallback=true
Model Versioning and Auditability
Given any produced prediction When persisted to the predictions store Then it includes model_version (semver), feature_hash, input_snapshot_ref, and generated_at And re-running with the same model_version and input_snapshot reproduces cost_low/high within ±1% tolerance And predictions are immutable; corrections create a new record linked by prior_prediction_id
Pre‑Approval Ceiling Application
Given an owner policy cap may exist for the property When a prediction is generated Then pre_approval_ceiling = min(cost_high, owner_policy_cap if present) And quotes ≤ pre_approval_ceiling auto-approve; quotes > pre_approval_ceiling require manual review and are flagged in the UI and API status And the applied ceiling and policy source are included in the prediction payload
Overrun Trend Warning
Given a job with an approved prediction When any vendor quote or in‑progress total reaches ≥ 90% of cost_high, or projected total based on current rate×ETA exceeds cost_high Then an overrun_warning is generated within 1 minute, notifying assigned PM/owner and posting an event to the timeline And the warning includes current_total, projected_total (if applicable), variance_percent, and recommended actions
Smart Pre-Approval Ceiling
"As a property manager, I want a smart pre-approval cap set from the prediction so that vendors can proceed on routine jobs without waiting for me, while staying within budget limits."
Description

Automatically derive a pre-approval cap from the predicted range using owner-configured policies (e.g., median, P50+10%, max of $X) and attach it to the work order. Display the cap to vendors during dispatch, enforce soft/hard spend controls at quote and job progress milestones, and require in-app approval for cap overrides. Support per-portfolio/property rules, emergency exceptions, and audit of policy versions to streamline routine fixes while controlling spend.

Acceptance Criteria
Cap Calculation via Policy Hierarchy
Given a property has a portfolio default cap policy "P50+10%" and a property-specific override policy "Median" And the predicted range for a new work order is Min=$120, P50=$180, Median=$200, Max=$260 (USD) When the work order is created Then the pre-approval cap is set to $200 USD And the selected policy label is stored as "Median" And the cap amount, currency, policy label, policy version ID, prediction inputs, and calculation timestamp are stored on the work order Given no predicted range is available for a new work order And the applicable fallback policy is "Max $250" When the work order is created Then the pre-approval cap is set to $250 USD And the calculation record indicates "Fallback - No Prediction"
Cap Attached and Visible to Vendor at Dispatch
Given a work order has a pre-approval cap of $200 USD with policy label "Median" When a property manager dispatches a vendor via FixFlow Then the dispatch screen and vendor portal show "Pre-approval cap: $200 USD (Median)" And the vendor must acknowledge the cap before accepting the job And the vendor acknowledgment event is recorded on the work order with vendor ID, timestamp, and client IP/user agent
Soft vs Hard Controls at Quote Submission
Given a work order has cap = $200 USD and quote control mode = Soft When the vendor submits a quote for $220 USD Then the system accepts the quote and sets status = "Pending Owner Approval - Over Cap by $20 (10%)" And approvers are notified via in-app and email notifications And scheduling of work cannot proceed until approval is recorded Given a work order has cap = $200 USD and quote control mode = Hard When the vendor attempts to submit a quote for $220 USD Then the submission is blocked with error "Exceeds pre-approval cap" And the vendor is presented with a "Request Override" action to route for approval
In-Progress Spend Monitoring and Threshold Alerts
Given a work order has cap = $200 USD and progress control = Soft And accrued spend = $150 USD When a new time/materials entry of $20 USD is posted Then accrued spend updates to $170 USD And 80% cap alert notifications are sent to the owner/PM and vendor showing accrued, remaining, and cap Given progress control = Soft And accrued spend reaches $205 USD Then the work order is flagged "Over Cap" And additional spend entries require approval before posting Given progress control = Hard When a spend entry would push accrued spend above $200 USD Then the entry is blocked with error "Exceeds pre-approval cap" And a "Request Override" action is provided
In-App Override Request and Approval Flow
Given a work order has cap = $200 USD When a vendor or PM submits an override request to increase the cap to $260 USD with reason "Parts price increase" Then the request requires selection of an approver or approver group per owner policy And the request stores the current policy version ID and the proposed cap change When an approver approves the request Then the work order cap updates to $260 USD immediately And the prior cap value remains in audit history And the vendor is notified of the new cap and must re-acknowledge if a quote exists And all actions are logged with actor, timestamp, reason, and policy version
Emergency Exception Policy Application
Given a portfolio emergency exception is configured as "Use Max $400, Soft controls, 24h window" And a work order is flagged Emergency with justification "No heat" When the work order is created Then the cap is set to $400 USD and control modes are set to Soft for the exception window And the exception window end time is recorded as creation time + 24h When the exception window expires without an approved override Then controls revert to the standard policy for the work order And any spend over the standard cap requires approval
Policy Versioning and Auditability
Given portfolio policy version v3.4 is effective on 2025-09-01 When a work order cap is calculated on 2025-09-17 Then the work order stores policy_version = "v3.4", a policy_snapshot JSON, and a prediction_inputs snapshot And an immutable audit entry is created for cap calculation, vendor acknowledgment, quote submissions, spend blocks, and overrides And audit entries are exportable via API and CSV with filters by date range, property, portfolio, vendor, and action outcome
Overrun Trend Alerts
"As an owner, I want proactive alerts when quotes or job totals trend over the forecast so that I can take action before costs spiral."
Description

Continuously monitor vendor quotes, line items, and in-progress totals against the predicted cost range and pre-approval cap. Trigger proactive alerts when proposals or accrued costs approach or exceed configurable thresholds (e.g., 80% of cap, exceeding upper bound) and provide one-click approve, request revision, or pause actions. Deliver alerts via in-app notifications, email, and SMS, and log all decisions to the job timeline to prevent overruns and delays.

Acceptance Criteria
80% Cap Threshold Alert on Quote Submission
Given a job with a predicted cost range and a configured pre-approval cap and an active approver list And a vendor submits or updates a quote whose total reaches >=80% and <100% of the pre-approval cap When the system evaluates thresholds Then an overrun trend alert is created within 60 seconds and shown on the job in-app And email and SMS alerts are sent to all designated approvers within 60 seconds And the alert content includes job ID, property, vendor, predicted range (min–max), pre-approval cap, quote total, and percent of cap And the alert provides one-click actions: Approve, Request Revision, Pause And duplicate alerts for the same threshold crossing are suppressed for 10 minutes
Upper Bound/Cap Exceeded Alert on Accrued Costs
Given a job with a predicted cost range and pre-approval cap And in-progress line items/accruals are posted by the vendor When cumulative accrued amount exceeds the predicted upper bound OR reaches/exceeds 100% of the pre-approval cap Then an overrun alert is created within 60 seconds and delivered in-app, email, and SMS And the alert content includes current accrued total, delta over upper bound and/or cap, and one-click actions And the job is not auto-paused unless Pause is selected by a user And the event is logged to the job timeline with timestamp, triggering metric, and channel delivery statuses
Configurable Alert Thresholds by Scope
Given organization-, portfolio-, and property-level alert threshold settings exist with defaults (e.g., 80% of cap, upper-bound exceed) When an authorized user updates threshold values and scope and saves Then subsequent evaluations use the new thresholds immediately And jobs scoped to the override honor the override; others use defaults And changes are persisted and survive system restarts And threshold changes are auditable with actor, old value, new value, scope, and timestamp
One-Click Approve from Alert
Given an approver receives an overrun alert with one-click Approve When the approver clicks Approve and confirms Then the system validates authorization and applies approval to the specific quote or accrual overage And the job status updates to reflect approval and allows work to proceed And the vendor is notified of approval via in-app and email within 60 seconds And the decision is logged to the job timeline including actor, decision, affected amount, rationale (if provided), and timestamp
One-Click Request Revision from Alert
Given an approver receives an overrun alert with one-click Request Revision When the approver clicks Request Revision, enters a note, and confirms Then the system marks the quote as Revision Requested and blocks approval until a new quote is submitted And the vendor is notified with the note via in-app and email within 60 seconds And the decision is logged to the job timeline including actor, requested changes, affected quote reference, and timestamp
One-Click Pause Work from Alert
Given an approver receives an overrun alert with one-click Pause When the approver clicks Pause and confirms Then the system sets the job to Paused and prevents additional accruals from being auto-approved And vendors attempting to add line items are warned and changes require re-approval And the decision is logged to the job timeline and all stakeholders are notified via in-app and email within 60 seconds
Vendor Rate Management
"As a FixFlow admin, I want accurate vendor rate data managed in the system so that predictions and quote validations reflect real market costs."
Description

Ingest, store, and normalize vendor rate cards by trade, geography, and effective dates, including labor, trip, and common materials rates. Allow manual entry and CSV import, validate currency and units, and surface the most relevant rates to the prediction engine. Use rates to sanity-check quotes and flag anomalies. Integrate with vendor onboarding and updates to keep predictions accurate and quotes consistent.

Acceptance Criteria
Manual Rate Card Entry with Validation
Given a property manager with permission to manage vendor rates and a vendor with defined trade and geography; When the user manually creates a rate card with labor hourly, trip fee, and common materials lines including units, currency, and effective start/end dates; Then the system validates required fields, ISO 4217 currency codes, allowed units (hour, visit, unit), positive numeric values, and non-overlapping effective date ranges per vendor/trade/geography; And on success persists the normalized rate card and returns a success response with the rate card ID; And on validation failure blocks save and returns field-level error messages for each invalid field.
CSV Rate Card Import with Row-Level Error Handling
Given the published CSV template for rate cards; When a user uploads a CSV file to import vendor rates; Then the system validates file type/encoding, header names, and row formats/values; And displays a preview showing total rows, valid rows, and per-row errors; And allows importing only valid rows while rejecting invalid rows with reasons; And produces an import summary containing counts of created, updated, rejected, and skipped rows and a downloadable error CSV.
Applicable Rate Resolution and Prediction Engine Exposure
Given multiple vendor rate card versions across geographies and effective dates; When the prediction engine requests rates for trade T, geography G, and service date D; Then the system resolves the applicable rate set by matching trade and best geography via the configured fallback (ZIP > City > State > Country > Global) and choosing the most recent version where start <= D <= end; And returns the resolved rate set with a stable version ID and metadata; And if no match exists, returns a NO_APPLICABLE_RATE outcome and emits a warning event for remediation.
Unit and Currency Normalization to Canonical Schema
Given rate lines captured in various units and currencies; When a rate card is saved; Then the system stores both original values and normalized values using canonical units (labor per hour, trip per visit, material per unit) and the platform base currency; And applies currency conversion using the configured FX source as of the effective start date with documented rounding rules; And exposes both original and normalized values via API and UI responses.
Quote Sanity-Check and Anomaly Flagging Using Rates
Given a vendor-submitted quote for a work order with known trade and geography; When the quote is created or updated; Then the system compares quoted labor and trip rates to the applicable normalized rates and flags any line exceeding the configured variance threshold (default 15%) or using disallowed units; And computes an expected subtotal and variance versus quoted total; And marks the quote as Flagged and surfaces warnings to the manager; And requires an override reason to approve when flags exist and records the decision.
Vendor Onboarding Requires Current Rate Card and Update Flow
Given a vendor onboarding workflow where trades and service areas are selected; When a vendor attempts to complete onboarding; Then the system requires at least one current effective rate card per selected trade and primary geography (start <= today and (no end date or end >= today)); And blocks completion with specific prompts for missing or expired rate cards; And schedules reminders for rates expiring within 30 days; And upon rate updates revalidates, reindexes, and refreshes the prediction engine cache.
Audit Logging and Role-Based Permissions for Rate Management
Given role-based access controls; When a user creates, updates, imports, or deletes a rate card; Then only authorized roles (e.g., Org Admin, Ops, Vendor self for own card) can perform the action per policy; And every change is recorded with actor, timestamp, source (UI/API/CSV), before/after values, and reason; And an immutable audit trail is queryable by vendor and date range; And unauthorized attempts are denied with 403 and logged.
Photo & Text Analyzer
"As a property manager, I want the system to interpret photos and descriptions to refine the cost estimate so that predictions are accurate even when tenants provide limited detail."
Description

Analyze tenant-uploaded photos and description text to extract features such as issue type, severity, likely parts, and access complexity. Use lightweight computer vision and NLP models optimized for common maintenance categories, with graceful degradation when media quality is poor. Feed extracted signals into the prediction engine and retain annotated artifacts for the job’s photo-timeline to improve accuracy and auditability.

Acceptance Criteria
Extract Issue Type from Photos and Description
Given an intake with tenant-uploaded photos and description across supported categories {plumbing, electrical, appliance, HVAC, lock/door, pest, water damage, structural}, when analyzed, then the system outputs issue_type from this taxonomy with confidence in [0,1] and modality_used ∈ {photo, text, both}. Given the curated validation set of ≥500 labeled cases across the taxonomy, when batch inference is executed, then macro-F1 ≥ 0.82 and per-class F1 for plumbing, electrical, appliance, HVAC ≥ 0.85. Given an intake missing photos or missing description, when analyzed, then a result is returned with issue_type and confidence, and degraded_modality = true without errors or timeouts. Given unsupported category text (e.g., "internet slow"), when analyzed, then output issue_type = "other" with confidence ≤ 0.5 and route_to_human = true. Given multiple plausible issues detected, when analyzed, then top_1_label is returned and secondary_labels includes up to 2 alternates with descending confidences.
Assess Severity and Access Complexity
Given any intake, when analyzed, then severity ∈ {low, moderate, urgent, emergency} with rationale (≤200 chars) and confidence in [0,1]. Given the severity validation set of ≥300 labeled cases, when batch inference runs, then overall accuracy ≥ 0.78 and recall for emergency ≥ 0.95. Given textual cues of active leak, gas smell, sparking outlet, or no heat with ambient < 40°F, when analyzed, then severity ∈ {urgent, emergency} and escalation_flag = true. Given images indicating panel access blocked, ladder required (ceiling >10ft), or landlord-only access (e.g., utility room), when analyzed, then access_complexity ∈ {appointment_required, special_access} with detected_cues enumerated. Given missing or ambiguous access cues, when analyzed, then access_complexity defaults to none and confidence ≤ 0.6.
Identify Likely Parts and Materials
Given supported issue types that typically require parts, when analyzed, then parts_candidates are returned normalized to internal catalog IDs with name, quantity_estimate, and confidence per item. Given the parts validation set of ≥200 jobs with known parts, when batch inference runs, then top-5 recall ≥ 0.75 and precision@1 ≥ 0.60. Given a faucet leak with a visible cartridge, when analyzed, then a specific cartridge candidate or generic "faucet cartridge" is included with confidence ≥ 0.60 and needs_model_number flag set when specificity is insufficient. Given cases where no parts are likely needed (e.g., GFCI reset), when analyzed, then parts_candidates = [] and parts_required = false. Given synonymous tenant terms (e.g., "tap" vs "faucet"), when analyzed, then normalization maps to the same catalog ID.
Graceful Degradation on Poor Media Quality
Given photos failing quality checks (blurry, low-light, occluded) with quality_score < 0.5, when analyzed, then the system falls back to text-dominant inference, reduces confidence by ≥ 0.15, and sets needs_better_photos = true. Given no photos and minimal text (<15 tokens), when analyzed, then output includes insufficient_signal = true and do_not_autopreapprove = true, without throwing errors. Given poor media conditions, when analyzed, then processing completes within latency SLOs and returns safe defaults: severity ≤ urgent unless explicit emergency cues appear in text. Given a tenant session integration, when poor quality is detected, then a structured prompt requesting clearer photos with up to 2 actionable tips is emitted.
Annotated Artifacts Persisted to Photo-Timeline
Given any analyzed photo, when annotations are generated, then an annotated image is stored alongside the original in the job’s photo-timeline with overlay labels for issue cues and redaction applied to faces and personal identifiers. Given an analysis result, when saved, then metadata includes model_version, timestamp, input_modalities, and per-signal confidences; audit record is queryable by job_id. Given screen-reader access, when the timeline is rendered, then alt_text summarizing extracted signals (≤140 chars) is present for each annotated photo. Given a subsequent re-analysis, when run, then a new timeline entry is appended; prior artifacts remain immutable and retain their audit metadata.
Signals Integrated into Prediction Engine
Given a completed analysis, when the prediction engine runs, then issue_type, severity, parts_candidates, and access_complexity are consumed and reflected in cost_range and preapproval_ceiling outputs. Given an ablation test where analysis signals are zeroed, when predictions are recomputed, then cost_range shifts by ≥ 5% in ≥ 70% of cases where signals imply material impact (e.g., severity upgrade or parts present). Given extractor unavailability, when prediction runs, then the engine falls back to baseline priors, sets limited_signals = true, and logs a WARN without blocking intake. Given a job that later exceeds forecast, when auditing, then the stored analysis signals used at prediction time are retrievable from the photo-timeline and metadata store.
Performance and Resource Constraints
Given typical intake payloads (1–5 photos up to 2MB each, description ≤500 tokens), when analyzed, then P95 end-to-end latency ≤ 2.0s and P99 ≤ 4.0s on a standard CPU-only instance. Given sustained load of 20 requests/second, when soaked for 10 minutes, then error rate (5xx or timeouts) ≤ 1% and queue wait P95 ≤ 300ms. Given the running service container, when measured at steady state, then peak RSS memory ≤ 350MB and there is no GPU dependency. Given a transient failure and single automatic retry, when retried, then success rate ≥ 99.5% and outputs are idempotent for the same job_id (confidence deltas ≤ 0.02).
Historical Cost Repository
"As a product analyst, I want high-quality historical job data captured and standardized so that the prediction models and benchmarks improve over time."
Description

Maintain a structured repository of completed jobs with final cost breakdowns, materials, time-on-site, root causes, property and seasonality attributes, and vendor used. Support anonymization across clients, data quality checks, and backfilling of existing records. Expose aggregated benchmarks to the prediction engine and analytics to continuously improve accuracy and provide cost insights.

Acceptance Criteria
Ingest Completed Job Record from Work Order
- Given a closed work order with vendor invoice, itemized materials, labor time logs, attached photos, root cause code, property metadata, season/date, vendor_id, and final amounts When the ingestion service runs on the work order Then a repository record is created with a unique work_order_id, vendor_id, property_id, issue_type, root_cause, materials[], labor_minutes, labor_rate, labor_cost, materials_cost, taxes, fees, discounts, total_cost, currency, season, completion_date, photo_timeline_uri, and source="ops" - Given currency values in different tenant locales When they are stored Then amounts are normalized to system currency=USD and original_currency captured - Given the same work order is processed again (retry) When ingestion runs Then no duplicate record is created and the existing record is upserted with updated fields and record_version incremented with updated_at timestamp - Given successful ingestion Then required fields (work_order_id, total_cost, issue_type, vendor_id, completion_date) are non-null and pass schema validation - Given any attachment present on the work order Then photo_timeline_uri points to an immutable gallery containing time-stamped images linked to the record
Backfill Legacy Work Orders into Repository
- Given a backfill file/API with N legacy jobs When the backfill job runs Then ≥ 99% of valid rows are imported, invalid rows are quarantined with error reasons, and a run report summarizes totals_imported, quarantined_count, and deduped_count - Given legacy jobs may lack fields When fields are missing Then missing values are stored as null and data_quality_flags[] enumerate missing_required, inferred_value, or normalized_value cases per field - Given duplicate detection keys (work_order_ref, vendor_id, property_id, completion_date, total_cost) When duplicates are encountered Then a single canonical record is retained and duplicates are linked via duplicate_of field - Given a dataset of 10,000 records When backfill runs Then throughput is ≥ 5,000 records/minute and the job completes without timeouts under standard infra sizing - Given the backfill job is restarted after failure When it resumes Then it is idempotent and does not create duplicates, respecting checkpoint offsets
Anonymize Cross-Client Job Data
- Given repository data is exported for cross-client aggregation When anonymization runs Then all direct identifiers (owner/tenant names, emails, phone numbers, invoice numbers, exact street addresses) are removed - Given property location data When used in aggregates Then location is coarsened to ZIP3 or a 5 km geohash, and client_id/property_id are replaced by irreversible salted hashes - Given event timestamps When used in aggregates Then dates are truncated to month and no time-of-day is exposed - Given any cohort bucket for aggregation When counts are computed Then results are suppressed unless cohort_size ≥ 20 to preserve privacy - Given anonymized exports are generated When validation runs Then zero PII fields are present per the PII field list and a checksum report is stored with run_id and field presence counts
Data Quality Validation on Ingestion
- Given a record to ingest When validation executes Then total_cost equals labor_cost + materials_cost + taxes + fees - discounts within ±$0.50 tolerance - Given labor_minutes and labor_rate When calculating labor_cost Then labor_cost equals ceil(labor_minutes/60) * labor_rate when vendor billing is hourly, or matches provided line items when billing is flat-rate - Given time-on-site When validated Then labor_minutes is within 1–720 minutes; values outside range cause the record to be quarantined with reason="labor_minutes_out_of_range" - Given issue_type and root_cause When validated Then both map to a controlled vocabulary; unmapped values are rejected with reason="invalid_taxonomy" - Given currency normalization When original_currency != USD Then an FX rate at completion_date is applied and original_amount, fx_rate_used are stored - Given validation failures When any rule fails Then the record status is set to "quarantined", not available to analytics, and an alert event is emitted
Aggregated Cost Benchmarks API
- Given an authenticated service with scope=predictions:read When it calls GET /benchmarks?issue_type=...&region=...&season=... Then the API returns 200 with JSON containing count, mean, median, p25, p75, p90, stddev, trimmed_mean, currency, last_updated_at - Given a cohort filter When cohort_size < 20 Then the API returns 204 No Content with reason="insufficient_cohort" - Given a valid request When processed Then P50 latency <= 200 ms and P95 <= 500 ms under 50 RPS sustained - Given response versioning When Accept-Version header is provided Then the schema version matches; otherwise default latest stable is used and the version is echoed in X-Schema-Version header - Given cache policy When identical queries repeat within 15 minutes Then responses are served from cache and include Cache-Control: max-age=900
Prediction Engine Access to Aggregates
- Given the prediction engine requests benchmarks during cost prediction When repository aggregates are updated Then new aggregates are available to the engine within 10 minutes, verified by a freshness timestamp no older than 10 minutes - Given a failed benchmarks lookup When no cohort is available Then the engine receives a typed error and falls back to vendor-rate + issue-type heuristics without throwing - Given schema evolution of benchmarks When a new metric is added Then the prediction engine remains backward compatible and continues to parse existing fields - Given an A/B test flag use_new_benchmarks=true When enabled for 50% of traffic Then traffic is split deterministically and prediction outputs are logged with benchmark_version for evaluation - Given auditability requirements When a prediction is generated Then the benchmark snapshot_id and parameters (filters) used are stored alongside the prediction record
Prediction Explainability & Audit Trail
"As an owner, I want to see why the cost was predicted and how decisions were made so that I can justify approvals and resolve disputes quickly."
Description

Provide transparent explanations for each predicted range, including comparable historical jobs, key drivers (e.g., issue type, vendor rates), and confidence. Record all cap calculations, overrides, approvals, and alert events in an immutable audit log tied to the job’s photo-timeline. Offer exportable reports for owners and vendors to resolve responsibility disputes and support billing accuracy.

Acceptance Criteria
Explainability Panel at Intake
Given a maintenance intake has a predicted cost range When a user opens the Prediction Explanation panel Then the panel shows the predicted range (min, max, currency) and confidence (0–100%) with a qualitative label (e.g., Low/Medium/High) And the top 3–5 key drivers with relative weights/contributions are displayed And at least 3 comparable historical jobs are listed with similarity score, final cost, date, and property type And the vendor-rate basis (rate card ID or cohort average) and its effective date are shown And the model version, prediction timestamp (ISO 8601, tenant timezone), and data sources are displayed And the panel renders within 500 ms from cached explanation And no PII (e.g., tenant name, phone, email) appears in drivers or comparables
Smart Cap Calculation Logged
Given a predicted range exists for a job When the system calculates the smart pre-approval cap Then an audit entry is appended capturing job ID, cap amount, calculation method/policy, inputs (range, confidence, policy params), model version, timestamp, and actor=system And the entry includes a content hash chained to the prior audit entry And the entry is visible in the Audit tab within 2 seconds of calculation And the entry is non-editable and non-deletable via UI and API
Override, Approval, and Alert Events Logged
Given a user with permission performs a cap override or approval, or an overrun alert triggers When the event occurs Then an audit entry records event type, before/after values, reason code (required), optional note, actor, timestamp, and linked artifacts (e.g., quote ID, photo ID, alert ID) And alert acknowledgment/dismissal is logged as a distinct event with actor and timestamp And any redaction is stored as a new event; original content remains intact And the audit feed is strictly ordered by a monotonic timestamp
Audit–Photo Timeline Linkage
Given an audit entry references photos or visual evidence When the user opens the Photo Timeline Then each referenced photo is annotated with the originating audit event ID and type And selecting the annotation navigates to the corresponding audit entry And from the audit entry, users can preview the referenced photo(s) And missing or removed media shows a placeholder with a reason code without breaking navigation
Exportable Dispute Report
Given a completed job or an active dispute When a user exports the Dispute Report Then the system generates PDF and CSV within 10 seconds for jobs with ≤100 audit events and ≤50 photos And the report contains: prediction explanation snapshot, smart cap history, overrides/approvals, alert timeline, vendor quotes/invoices, and photo thumbnails with timestamps And the report includes a cover page with job metadata, document hash, and generation timestamp And restricted PII is excluded or masked per tenant policy And exported files are accessible only to authorized roles and expire after 7 days
API Access to Explanation and Audit
Given an API client holds a valid OAuth token with job scope When it calls GET /jobs/{id}/prediction-explanation and GET /jobs/{id}/audit-log Then the API returns 200 with required fields, supports pagination and filtering by event type and date range And responses include a chain-hash and last-event-id for integrity verification And unauthorized/forbidden requests return 401/403; nonexistent jobs return 404 And rate limiting is enforced at 60 requests/min with a Retry-After header
Immutability and Retention Enforcement
Given the audit store is append-only When any actor attempts to edit or delete an existing audit entry Then the system blocks the change, records a tamper-attempt event with actor, timestamp, and vector, and returns 405 And all audit entries are retained for at least 7 years unless extended by legal hold And chain-hash verification failures trigger a high-severity alert and block report export

Exception Pulse

Instant, actionable owner/manager notifications when a cap will be exceeded. Messages include delta over cap, reason summary, photos, and ETA. Approvers can one‑tap Approve, Cap & Continue, Request Quote, or Reassign. Auto‑escalation and expiry keep jobs from stalling, and all actions are audit‑logged.

Requirements

Cap Policy & Threshold Configuration
"As an owner, I want to set spend caps and escalation rules per property and category so that Exception Pulse triggers only when it matters to me."
Description

Provide a configurable policy layer for owners/managers to define spend caps and escalation rules at portfolio, property, unit, and category/urgency levels. Supports fixed caps, time‑of‑day/week variations (e.g., after‑hours uplift), currency settings, tolerances/rounding, and default actions on expiry. Includes UI and API for creating, versioning, and validating policies, with RBAC controls to restrict who can edit. Policies feed Exception Pulse to determine when to trigger, who to notify, and how to escalate. Changes are effective‑dated, audited, and safely rolled out with validation to prevent conflicting or incomplete configurations.

Acceptance Criteria
Effective-Dated Multi-Scope Policy Creation and Precedence
Given a portfolio owner with edit permission, When they create policies at portfolio, property, unit, and category/urgency scopes with overlapping applicability and future effective dates, Then the system saves each as a new version with no active version overlap per scope. Given overlapping policies exist across scopes, When evaluating a maintenance request context, Then the system applies deterministic precedence: Unit > Property > Portfolio, and within scope Category/Urgency-specific overrides General. Given a future-dated version, When its effectiveStart timestamp is reached, Then the version becomes active automatically and the prior version is retired but retained for audit. Given a backdated effectiveStart that would overlap an active version, When submitted, Then validation blocks the save and lists the conflicting version IDs. Given a policy version is archived, When evaluating, Then the engine ignores archived versions and uses the latest active non-archived version for the context.
Time-Based Variations and After-Hours Uplift
Given a policy with time-of-day and day-of-week rules, When a request is evaluated at 19:30 on Saturday in the property's timezone, Then the after-hours uplift defined for weekends is applied to the cap. Given multiple time windows are configured for a day, When saving the policy, Then the system rejects overlapping windows and accepts adjacent non-overlapping windows. Given the property's timezone is set, When evaluating any request, Then all time rules use the property's timezone regardless of user/vendor timezone. Given both a percentage uplift and a fixed uplift amount are configured, When evaluating, Then the engine applies the configured precedence or defaults to the higher uplift and records which was applied in the evaluation result. Given a time rule references an invalid day or malformed time range, When saving, Then validation fails with field-specific errors and no changes are persisted.
Currency, Tolerance, and Rounding Controls
Given a policy specifies currency EUR, When a cap is saved, Then the amount must be numeric with up to 2 decimal places and stored with ISO 4217 currency code. Given tolerance is set to 5% and rounding mode is "down to whole unit", When evaluating an estimated cost of €101.79 against a €100 cap, Then the permitted amount is €105 and the rounded cap used is €100. Given both absolute tolerance (e.g., €10) and percentage tolerance (e.g., 5%) are set, When evaluating, Then both are enforced and the lesser permitted overage applies. Given an invalid rounding mode value is provided, When saving the policy, Then validation rejects the value and returns the allowed set: up, down, nearest. Given an active policy version, When attempting to change its currency, Then the system requires creating a new future-dated version and blocks in-place currency changes.
RBAC-Controlled Editing and Audit Logging
Given roles Owner Admin or Property Manager with PolicyEditor permission, When accessing the UI or API, Then only authorized users can create/update/archive policies; others have read-only or are denied per RBAC. Given a policy change is saved, When the transaction commits, Then an audit entry records actor, timestamp, tenant, scope, fields changed with before/after values, and effective dates. Given an API call uses a token from a different tenant, When attempting to modify a policy, Then the request is denied with 403 and only an access-denied audit entry is recorded. Given a user edits notification targeting outside their tenant, When saving, Then validation enforces tenant boundaries and rejects cross-tenant recipients. Given an archived policy is viewed, When requested, Then the audit history remains accessible and immutable.
Policy Validation and Conflict Prevention
Given a new policy version draft, When required fields (scope, currency, cap, escalation rules, default expiry action) are missing, Then validation fails with field-specific errors and 422 status for API. Given time-of-day/week rules overlap or create ambiguous edges, When saving, Then the system blocks the save and highlights conflicting windows. Given multiple policies at different scopes could both apply without clear precedence, When saving, Then validation enforces the global precedence rules and rejects ambiguous configurations. Given a policy references a non-existent category or urgency, When saving, Then validation fails with an invalid reference error and the save is aborted. Given a policy configuration would result in no notification recipients for Exception Pulse, When saving, Then validation fails with a "no notify target" error.
Default Expiry Actions and Exception Pulse Triggering
Given a policy defines default expiry action Approve, Cap & Continue, Request Quote, or Reassign, When an Exception Pulse approval timer expires, Then the configured default action executes and is audit-logged with policy version ID and timestamp. Given a cap will be exceeded by an incoming estimate or vendor quote, When evaluated against the active policy, Then the engine calculates the delta over cap considering tolerance/rounding and emits a trigger payload to Exception Pulse including cap, evaluated amount, delta, reason summary, notify list, escalation path, and expiry SLA. Given no applicable policy exists for the request context, When evaluation occurs, Then a safe default is applied that requires manual approval and optionally uses a global cap if configured; dispatch is blocked until approval. Given an expiry action is updated in a future-dated version, When the effective date arrives, Then pulses created after that time use the new default while existing pulses retain their original action.
UI/API Parity and Evaluation Performance
Given the UI supports creating/editing policies, When the same payload is sent to the public API, Then the API accepts identical fields, performs the same validations, and returns consistent error codes documented in OpenAPI. Given the evaluation endpoint /v1/policy/evaluate receives a context (tenant, property, unit, category, urgency, timestamp, estimated amount, currency), When processed, Then it returns resolved cap, tolerance applied, rounding mode, expiry action, escalation targets, and whether a trigger is required. Given 1000 concurrent evaluations under typical load, When measured, Then p95 latency is <= 150 ms and error rate is < 0.1%. Given an invalid API payload, When calling any policy endpoint, Then a 422 response is returned with machine-readable error codes and JSON pointers to offending fields. Given a successful create/update via API, When reloading in the UI, Then the new version appears with correct status, effective dates, and scope.
Real-Time Cap Breach Detection
"As a manager, I want instant detection when a job will exceed its cap so that I can intervene before unnecessary costs are incurred."
Description

Continuously evaluate work orders against configured caps using both projected and actual costs to detect imminent or current overages. Ingests inputs from triage estimates, vendor quotes, change orders, parts pricing, taxes/fees, and time & materials logs. Computes the delta over cap, identifies primary reasons (e.g., emergency surcharge, parts cost variance), and classifies severity. Publishes a single deduplicated event per breach state with idempotent semantics and suppresses flapping via hysteresis/tolerances. Integrates with FixFlow’s triage/dispatch pipeline so detection occurs before spend commits whenever possible.

Acceptance Criteria
Imminent Breach Detected from Triage Estimate (Pre‑Dispatch)
Given a work order with cap C and a triage estimate projecting total P > C When triage completes and before dispatch authorization Then the system computes delta D = P − C and sets breach_state = "Imminent" And publishes the breach event prior to any dispatch commit And the dispatch pipeline is gated until an approval/override or cap change clears the breach And detection-to-publication latency is within the configured detection SLA
Current Breach Detected from Vendor/Actuals Update
Given a work order with cap C When a vendor quote, change order, parts purchase, T&M log, or taxes/fees update raises committed or projected cost P' above C Then breach_state = "Current" is set or updated and delta D = P' − C is computed and published And the event includes source_type corresponding to the triggering update (Vendor Quote | Change Order | Parts | T&M | Taxes/Fees) And detection-to-publication latency is within the configured detection SLA
Cost Aggregation from All Inputs Is Accurate
Given any combination of cost inputs (base estimate, parts, labor, surcharges, taxes/fees, T&M) When the total cost is computed Then total = sum(components) using standard rounding rules (to the cent) And the event payload includes per-component amounts and the grand total And automated tests validate representative combinations (including fractional cents, zero/negative adjustments, and refunds) with 100% pass rate
Primary Reason Identification and Reason Summary
Given multiple contributing reasons to a cap breach When a breach is detected Then primary_reason equals the largest absolute contributor to delta_over_cap And reasons are listed with {label, amount} in descending contribution order And labels are drawn from the controlled set ["Emergency Surcharge","Parts Cost Variance","Labor Rate Variance","Additional Scope","Taxes/Fees","T&M Overrun"] And ties are resolved by deterministic priority: Emergency Surcharge > Additional Scope > Parts Cost Variance > Labor Rate Variance > Taxes/Fees > T&M Overrun
Severity Classification Based on Delta Over Cap
Given delta_over_cap D and organization-configured severity bands When the breach is computed Then severity is assigned per the configured thresholds (e.g., Minor/Moderate/Severe/Critical) And the event payload includes severity and thresholds_version And updating thresholds reclassifies severity on next evaluation without creating a new breach event unless state changes or hysteresis is exceeded
Deduplicated Breach Events with Idempotent Semantics
Given multiple evaluations without a breach-state transition and |delta change| ≤ hysteresis H When duplicate or retried input messages are processed Then only one event exists for the current breach_state per work order And reprocessing the same input yields the same event_id (idempotency key) and no additional record And a new event is published only when breach_state changes or |delta change| > H And updates to the same breach state increment event_version while preserving event_id
Hysteresis/Tolerance Suppresses Flapping Near Cap
Given oscillations in projected/actual costs around the cap within hysteresis H When costs cross above and below the cap within H Then no additional breach-state transitions are emitted and the current state remains stable And when |delta change| exceeds H, exactly one transition and one event are emitted And H is configurable per organization and defaulted when unset
Rich Notification Payload Composition
"As an approver, I want notifications that show the overage amount, reasons, photos, and ETA so that I can make a quick, informed decision without opening the full job."
Description

Generate actionable notification payloads that include formatted delta over cap, concise reason summary, last annotated photos from the job, current vendor ETA, and key job metadata (address, tenant impact, priority). Embed secure deep links for immediate actions and render channel‑appropriate templates (in‑app, push, SMS, email) with localization and time‑zone correctness. Sanitize/redact sensitive data, compress media for bandwidth, and include fallbacks if certain artifacts (e.g., photos or ETA) are unavailable.

Acceptance Criteria
Cap Delta and Reason Summary Formatting
Given a job where the estimated cost exceeds the approval cap, When composing the notification payload, Then include a deltaOverCap value equal to (estimate - cap) formatted as localized currency with 2 decimal places and correct currency symbol for the recipient. Given a cap-exceeded event, When composing the payload, Then ensure deltaOverCap is positive and includes thousands separators according to locale. Given a textual reason summary is available, When composing the payload, Then include a concise reasonSummary trimmed and normalized to ≤120 characters without breaking words; if truncated, append an ellipsis. Given any PII or internal codes appear in the reason summary, When composing the payload, Then strip/redact them before inclusion. Given the estimated cost does not exceed the cap, When preparing Exception Pulse payloads, Then do not generate the cap-exceeded notification template.
Key Job Metadata Inclusion
Given a cap-exceeded notification is triggered for a job, When composing the payload, Then include address (single-line format: street, unit if present, city, state/province, postal code), tenantImpact (from a controlled list), priority (P1/P2/P3), and jobId. Given a current vendor ETA exists, When composing the payload, Then include eta in the recipient's local time with date and time components. Given tenantImpact or priority values are outside the allowed set, When validating payload, Then reject composition and log an error; do not send until corrected. Given all required metadata fields are present, When rendering, Then ensure none are empty strings and each field passes schema validation.
Secure Deep Links for Immediate Actions
Given an authorized recipient (owner/manager), When composing the payload, Then include deep links for Approve, Cap & Continue, Request Quote, and Reassign. Given deep links are generated, When issuing tokens, Then sign each link with a recipient- and job-scoped token that expires in ≤24 hours and is single-use. Given a deep link is opened after expiry or reuse, When the endpoint is invoked, Then return an expiration message and instructions to request a new approval link; no action is performed. Given links are included, When validating security, Then ensure HTTPS is used for web, app-scheme for in-app, no PII appears in query parameters, and tokens cannot be replayed (nonce enforced). Given a deep link is clicked, When server receives the request, Then log the event with jobId, recipientId, action, timestamp, and tokenId for audit.
Channel-Appropriate Rendering and Size Constraints
Given in-app delivery, When rendering the notification, Then display full payload (deltaOverCap, reasonSummary, address, tenantImpact, priority, ETA) with up to 5 annotated photo thumbnails and 4 action buttons. Given push delivery, When composing the push, Then set title ≤50 characters and body ≤120 characters (localized), include deltaOverCap and a shortened reasonSummary, and attach a single 512×512 thumbnail ≤100 KB. Given SMS delivery, When composing the message, Then include a concise text ≤320 characters (localized) with deltaOverCap and a single short URL to a secure web view; do not attach images via MMS. Given email delivery, When composing the email, Then include a responsive HTML template with subject containing property/address and deltaOverCap, body including reasonSummary, ETA, and up to 5 thumbnails linking to a secure gallery. Given any channel-specific size limit would be exceeded, When composing, Then truncate non-critical text at word boundaries and omit extra images while preserving required fields.
Localization and Time-Zone Accuracy
Given a recipient's language and time zone preferences, When composing the payload, Then format currency, dates, times (including ETA), numbers, and address according to the recipient's locale and time zone, including zone abbreviation or UTC offset in displayed times. Given a property time zone differs from the recipient's, When displaying ETA, Then convert from property/vendor source time to the recipient's time zone and account for DST rules. Given no language preference is set, When localizing, Then default to en-US language and the property's time zone for times. Given multi-lingual templates, When rendering, Then select the correct translation keys and pluralization rules; fall back to English only if the requested locale key is missing.
Sensitive Data Redaction and Payload Sanitization
Given tenant and vendor records contain PII, When composing the payload, Then exclude tenant/vendor names, phone numbers, emails, and exact unit access codes; include only tenantImpact labels and job metadata specified by requirement. Given annotated photos are included, When attaching media, Then strip all EXIF/metadata (GPS, device identifiers) before upload or embedding. Given free-text fields (reasonSummary, notes) may contain HTML or scripts, When processing content, Then sanitize/escape to neutralize HTML/JS and permit only a safe subset of formatting (if any). Given URLs are embedded, When composing, Then ensure no secrets or tokens appear in clear within the URL path or query beyond the signed action token; use short links that resolve server-side.
Media Compression and Artifact Fallbacks
Given annotated photos exist, When preparing media, Then generate channel-specific renditions: in-app/email thumbnails ≤200 KB each at ≥1024 px long edge (WebP/JPEG), push thumbnail ≤100 KB at 512 px square, and provide a link to originals in a secure gallery. Given network or processing constraints prevent media preparation within 2 seconds, When composing the payload, Then send a text-first version immediately and lazy-load images for in-app/email; push/SMS omit images. Given no annotated photos are available, When composing, Then omit the photos section and insert a localized placeholder message indicating photos are not yet available; ensure payload remains valid. Given vendor ETA is unavailable, When composing, Then display a localized 'ETA pending' placeholder and omit time-specific fields. Given push notification payload limits, When validating, Then keep total push payload size ≤3.8 KB; if exceeded, remove non-critical fields before sending.
One‑Tap Approval Actions
"As an owner, I want to approve or redirect an over‑cap job with one tap so that work doesn’t stall and my intent is captured immediately."
Description

Enable approvers to execute Approve, Cap & Continue (update cap to new value), Request Quote (pause non‑critical work and solicit quote), or Reassign (swap to vetted alternative vendor) directly from the notification or a lightweight approval screen. Enforce permissions and multi‑factor as needed, validate business rules (e.g., life‑safety exceptions), and perform atomic state changes with optimistic concurrency to prevent double actions. Actions immediately update the work order, notify vendors, and append outcomes to the photo‑timeline and audit trail. Deep links are single‑use, time‑boxed, and idempotent to ensure consistency.

Acceptance Criteria
One‑Tap Approve from Exception Pulse Notification
Given an authorized approver receives a cap‑exceed Exception Pulse with a valid single‑use deep link When the approver taps Approve within the link validity window Then the work order status changes to Approved within 5 seconds And the assigned vendor is notified within 10 seconds with reason summary, delta over cap, photos, and ETA And the photo‑timeline is appended with an approval entry and the approver’s note (if provided) And the audit trail records actor, action=Approve, source=Notification, timestamp, requestId, and previous→new state And the approval action is idempotent such that repeat taps return the final Approved state without duplicate side‑effects
Cap & Continue with Updated Spend Cap
Given an approver views an over‑cap work order via the approval screen or deep link And the approver has permissions to modify caps When the approver selects Cap & Continue and enters a new cap value >= current cap and <= policy maximum Then the system validates numeric format and policy bounds and rejects invalid input with inline errors And on success, the cap is updated atomically with the approval and work continues And vendor is notified within 10 seconds of the new cap and instructions And the photo‑timeline and audit trail capture previousCap, newCap, actor, action=Cap&Continue, requestId And the action is idempotent such that resubmission returns the same final cap and does not duplicate notifications
Request Quote Pauses Non‑Critical Work
Given a non‑critical work order that exceeded cap When an authorized approver selects Request Quote Then the work order status changes to Awaiting Quote and active tasks are paused within 5 seconds And vendors receive a quote request with scope, required line‑items, and due‑by timestamp And no spend is authorized beyond the existing cap until approval is granted And SLAs tied to completion are paused and quote SLA timers begin And the photo‑timeline and audit trail are updated with action=RequestQuote, fields {dueBy, vendorRecipients, actor} And repeat submissions return the same Awaiting Quote state without duplicating notifications
Reassign to Vetted Alternative Vendor
Given an over‑cap work order with at least one vetted alternative vendor available When an authorized approver selects Reassign and chooses an alternative vendor Then the assignment switches atomically to the selected vendor and the prior vendor is notified of deassignment with reason And the new vendor receives the full job context (reason summary, photos, ETA expectations) within 10 seconds And SLAs and scheduled windows are preserved or recalculated per policy and surfaced to both parties And the photo‑timeline and audit trail record previousVendor→newVendor, actor, action=Reassign, requestId And re‑tapping the deep link returns the final assignment without duplicating messages
Permissions and MFA Enforcement for One‑Tap Actions
Given a user attempts an approval action (Approve, Cap & Continue, Request Quote, or Reassign) When the user lacks the required role or resource scope Then the action is blocked, no state changes occur, and the user sees a permissions error And the audit trail records a denied attempt with actor, attemptedAction, reason=InsufficientPermissions When the user has the required role but MFA is required and not satisfied Then the system prompts for MFA and only proceeds after successful verification within the session window And on success, the selected action executes; on failure or timeout, no state changes occur and denial is logged
Optimistic Concurrency Prevents Double Actions
Given two approvers attempt different actions on the same work order within a short interval When the first request succeeds using the current version/ETag Then the second request with a stale version is rejected with HTTP 409/conflict and message=ActionAlreadyApplied And no duplicate state transitions, notifications, or timeline entries occur And the conflict response includes the current authoritative state and lastAction metadata And subsequent retries using the updated version succeed only if a new valid action is chosen
Single‑Use, Time‑Boxed, Idempotent Deep Links
Given an Exception Pulse approval deep link with TTL=30 minutes and single‑use token When the link is used the first time within TTL Then the requested action executes once and the token is immediately invalidated When the same link is used again or after TTL expiry Then no action executes and the user is shown ActionAlreadyApplied or LinkExpired with a path to the approval screen And all attempts (success/expired/replay) are audit‑logged with tokenId (hashed), actor (if known), and outcome And tokens cannot be replayed across devices or sessions and are bound to the specific work order and action
Auto‑Escalation and Expiry Workflow
"As a property manager, I want over‑cap requests to escalate automatically and expire if ignored so that repairs keep moving and tenants aren’t left waiting."
Description

Orchestrate time‑boxed approval windows with configurable expiry and multi‑level escalation (e.g., owner → backup approver → on‑call). Respect business hours/quiet hours where configured, provide snooze/deferral options, and support default actions at expiry (auto‑cancel, auto‑approve up to a limit, or auto‑request quote). Include throttling to prevent notification storms, and surface real‑time status to the job timeline so teams can see who’s next and when. All transitions are resilient to service outages and recoverable on restart.

Acceptance Criteria
Time‑boxed multi‑level escalation sequence
- Given a job with cap $250 and escalation chain Owner → Backup → On‑Call with level windows 15m/20m/30m - And no action is taken by the current level within its window - When a level’s window expires - Then the next level is notified immediately with Approve, Cap & Continue, Request Quote, and Reassign actions - And the expired level can no longer act on the job - And if any level acts, all downstream timers and notifications cancel - And notifications include delta over cap, reason summary, photos, and ETA - And every transition is audit‑logged with actor, timestamp, and prior→next state
Business/quiet hours‑aware scheduling
- Given business hours Mon–Fri 08:00–18:00 local time and quiet hours otherwise for Owner and Backup; On‑Call is 24/7 - And an escalation or expiry would occur during quiet hours for a level not flagged 24/7 - When the current level’s window reaches quiet hours - Then the timer pauses at quiet‑hours start and resumes at 08:00 next business window with the remaining time - And escalations that would start during quiet hours defer until business hours unless the next level is 24/7 - And all countdowns and timestamps reflect the job’s configured time zone
Snooze/deferral controls
- Given an approver selects Snooze for 30 minutes while within their window - When Snooze is applied - Then the countdown pauses immediately and resumes after 30 minutes - And a maximum of 3 snoozes or 60 minutes total deferral per level is enforced (first limit hit wins) - And snooze events are shown on the job timeline and audit log with actor and duration - And if snooze would resume in quiet hours, it resumes at the next business window with remaining time
Expiry default actions policy
- Rule: If policy = Auto‑Approve up to $100 and delta over cap ≤ $100 at expiry, system auto‑approves and dispatch continues - Rule: If policy = Auto‑Approve up to $100 and delta over cap > $100 at expiry, system auto‑requests quote - Rule: If policy = Auto‑Cancel at expiry, job is canceled and all parties are notified with reason "Expiry policy" - Rule: If policy = Auto‑Request Quote at expiry, job moves to Quote Requested and vendor is notified - And all default actions are idempotent and audit‑logged with actor "system" and precise timestamp
Notification throttling across channels
- Rule: Limit to 1 notification per approver per job per channel (push/SMS/email) per 5 minutes - Rule: Collapse multiple state changes within 60 seconds into a single summary notification per channel - Rule: Delivery retries use exponential backoff (1m, 2m, 4m, 8m, 15m max) and respect throttling limits - Rule: Suppress manual reminders if an unread notification < 5 minutes old exists for that approver/job/channel - Then at least one notification is sent when a new level starts unless the approver opted out of that channel
Real‑time timeline status and transparency
- Given an escalation window starts, pauses, resumes, escalates, or expires - When the state changes - Then the job timeline updates within 5 seconds to show: current approver, level name/number, absolute deadline timestamp, live countdown, next approver, and configured default action at expiry - And each change appends a timeline event with actor, action, and timestamp; previous entries remain immutable - And state is consistent after app refresh or across devices within 5 seconds
Resilience, recovery, and idempotency
- Given an in‑flight escalation when services experience an outage up to 10 minutes - When services restart - Then all pending timers are reconstructed from durable storage and corrected for elapsed wall‑clock time - And maximum timer drift after recovery is ≤ 60 seconds - And duplicate notifications are prevented via idempotency keys (≤1 per event per channel) - And replaying a previously completed action returns success without state change and is logged as a no‑op
End‑to‑End Audit Logging
"As an owner, I want a complete audit record of over‑cap decisions and evidence so that I can resolve responsibility disputes confidently."
Description

Capture an immutable audit trail of all Exception Pulse events: detection triggers, notification deliveries and opens, action attempts and outcomes, cap changes, comments, and escalations. Each record includes timestamp, actor, channel, device/IP where available, and diffs of state changes. Link artifacts (photos, quotes) into FixFlow’s annotated photo‑timeline for a single source of truth. Provide export/search APIs and retention controls to satisfy compliance and resolve responsibility disputes quickly.

Acceptance Criteria
Immutable Hash‑Chained Audit Trail
Given an Exception Pulse event is persisted When the audit system writes the record Then the record includes audit_id (UUIDv4), prev_hash, content_hash (SHA‑256 of canonical JSON), and created_at in UTC ISO‑8601 Given a sequence of audit records for a job When a hash‑chain verification is executed Then 100% of records validate with no gaps and the terminal hash matches the latest record Given a client attempts to update or delete an audit record via API When the request is processed Then the API returns 405 Method Not Allowed (or 403 Forbidden) and zero records are modified Given direct data store protections are configured When an unauthorized write/update/delete is attempted Then storage enforces append‑only/WORM semantics and the attempt is logged as a security event Given server clocks may drift When audit records are created Then timestamps are sourced from NTP‑synced servers and are monotonically non‑decreasing per job context
Comprehensive Exception Pulse Event Coverage
Given any of the following occurs: detection_triggered, notification_delivered, notification_opened, action_attempted, action_completed, cap_changed, comment_added, escalation_started, escalation_expired, reassigned, approve_tapped, cap_and_continue_tapped, request_quote_tapped When the event occurs Then an audit record is created within 3 seconds including: timestamp (UTC), actor_id or "system", event_type, job_id, exception_id, channel (if applicable), device_id (if available), ip_address (if available), outcome (success|failure) with reason_code Given multi‑channel notifications are sent (email/SMS/push/in‑app) When deliveries and opens happen Then separate audit entries exist per channel with message_id, delivery_status, and open events tied to user_id and channel Given auto‑escalation or expiry timers fire When escalation/expiry occurs Then audit records include prior assignee/level, new assignee/level (if any), trigger reason, and next‑step ETA Given a vendor or assignee is reassigned When the reassignment is saved Then an audit record contains from_assignee, to_assignee, and justification text or code
State Change Diff Recording
Given a cap amount changes from A to B When the change is saved Then the audit record stores a structured diff: { cap_amount: { from: A, to: B, delta: B‑A } } and the actor_id Given multiple fields change in a single operation When the operation completes Then one audit record contains atomic diffs for all fields and increments the job state version by 1 Given an action is retried with the same idempotency_key When the retry occurs Then no duplicate audit record is created; the original record reflects attempt_count increment and last_attempt_at Given a user submits a no‑op (no state difference) When processed Then no diff audit record is written
Artifact Linking to Annotated Photo‑Timeline
Given a photo, quote, or other artifact is added during an Exception Pulse action When the audit record is written Then it includes artifact_id, artifact_type, checksum, and a link; the artifact appears in the job's annotated photo‑timeline at the audit timestamp with the correct caption/context Given a timeline export is requested for a job When the export completes Then every artifact referenced by audit records is included; if purged by retention, a tombstone entry with reason and original checksum is present Given an integrity check runs When artifacts are verified Then stored artifact checksums match those recorded in associated audit records
Search and Export APIs for Audit Logs
Given a user with role "Compliance Auditor" and valid auth When they call GET /audit/search with filters (time range, actor_id, event_type, job_id, channel, outcome, ip_address, device_id) Then only in‑tenant records matching filters are returned with cursor pagination (default page_size=100, max=1000) and stable ordering by timestamp, audit_id Given a typical 30‑day filtered query over ≤10M records When executed Then p95 response time is ≤1000 ms and results are correct per filters Given an export is requested via POST /audit/export for a job or time window When processed Then a signed URL for JSONL and CSV (and optional ZIP with attachments) is available within 2 minutes for ≤1 GB; the package includes chain_verification_report and schema_version Given a client exceeds 60 requests/min on audit APIs When additional requests arrive Then the service returns 429 with a Retry‑After header Given a user without the required role calls audit APIs When the request is processed Then the response is 403 and returns no data
Retention Controls and Legal Hold
Given a tenant retention policy (e.g., 7 years) is configured When an audit record exceeds its retention period and is not on legal hold Then the purge job deletes it irreversibly, writes a purge audit entry (tenant_id, count, range, executor, timestamp), and replaces timeline references with tombstones Given a legal hold is applied for job(s) or date range When purge executes Then records under hold are not deleted until the hold is removed; creating, updating, and removing holds are themselves audit‑logged Given an admin attempts to set retention below the minimum allowed threshold (e.g., 1 year) When saving the policy Then validation fails with an error and no change is applied Given retention evaluation runs When determining eligibility Then UTC timestamps are used and policy changes apply prospectively unless retroactive=true, which is recorded in the audit log Given a purge operation fails When retries are attempted Then exponential backoff up to 5 attempts occurs; final failure emits an alert and is audit‑logged with error_code
Multi‑Channel Delivery & Failover
"As an approver, I want reliable delivery on my preferred channel with automatic fallback so that I can respond quickly wherever I am."
Description

Deliver Exception Pulse via in‑app, push, SMS, and email based on user preferences and policy. Track delivery/read receipts, retry with exponential backoff, and automatically fail over to a secondary channel when undelivered within a threshold. Support per‑channel templates, link tracking, rate limits, localization, and regulatory compliance (opt‑in/opt‑out, quiet hours). Expose delivery status to the workflow engine so escalations consider actual reachability.

Acceptance Criteria
Primary Channel Selection Honors Preferences and Policy
- Given a user with channel preferences [push, SMS, email] and a valid push token, When an Exception Pulse is generated, Then the system sends only a push notification as the primary external channel and records channel=push as attempted. - Given a user with preferences [push, SMS, email] and no valid push token, When an Exception Pulse is generated, Then the system sends via SMS and does not send email unless failover conditions occur. - Given a user opted-out of SMS but opted-in to email and lacks a valid push token, When an Exception Pulse is generated, Then the system sends via email and records SMS as ineligible due to opt-out. - Given tenant policy requires in-app delivery for all Exception Pulse, When an Exception Pulse is generated, Then an in-app notification is always created in addition to the selected external channel. - Given a user has quiet hours active for push, When an Exception Pulse is generated during quiet hours and policy does not override, Then push is excluded from eligibility for initial delivery.
Exponential Backoff Retry and Timed Failover Between Channels
- Given a push notification attempt returns no delivery confirmation, When retries are scheduled, Then the system retries on push with exponential backoff at 1m, 2m, and 4m up to a maximum of 3 retries. - Given push remains undelivered after 3 retries or 7 minutes (whichever comes first), When evaluating failover, Then the system fails over to the next eligible channel per user preference and policy. - Given any channel returns a definitive failure (e.g., permanent bounce or invalid token), When processing retries, Then further retries on that channel are canceled and failover is evaluated immediately. - Given a delivery or read receipt is received on any channel, When processing scheduled retries/failovers, Then all pending retries and failovers for that notification are canceled. - Given failover occurred to SMS, When SMS is delivered, Then the system does not attempt email unless SMS later fails or is undelivered within the defined threshold.
Delivery and Read Receipts Recorded and Surfaced to Workflow Engine
- Given provider webhooks for push, SMS, email, and in-app events are received, When a delivery or read/open event occurs, Then the system updates the message state within 5 seconds and persists a timestamped audit record including channel, provider status, and correlation ID. - Given the workflow engine queries delivery state for a job, When reachability is evaluated, Then it receives aggregated status per channel (Pending, Delivered, Read, Failed, Undeliverable) and a computed overall reachability state (Reachable, Not Reachable, Partially Reachable). - Given an escalation rule requires "no Delivered on any channel within 10 minutes," When no channel reaches Delivered within 10 minutes, Then the workflow engine triggers escalation; When any channel reaches Delivered within 10 minutes, Then escalation is suppressed. - Given a read event occurs after escalation, When evaluating subsequent escalations, Then rules can reference "read_at" to decide whether to continue or halt escalation.
Per-Channel, Localized Templates Render Correctly with Fallbacks
- Given per-channel templates for in-app, push, SMS, and email with placeholders {delta_over_cap}, {reason_summary}, {ETA}, {actions}, When rendering for locale 'es-ES', Then the content is localized to Spanish, variables are populated, and date/time formats match the locale. - Given a user's locale is unsupported, When rendering, Then the system falls back to 'en-US' templates and records the fallback in the audit log. - Given the template includes action buttons/links (Approve, Cap & Continue, Request Quote, Reassign), When delivered via SMS, Then SMS includes a single secure short link to an action hub that exposes all actions. - Given a template version update occurs, When sending new notifications, Then new messages render with the new version while previously sent messages remain unchanged. - Given right-to-left locales (e.g., 'ar'), When rendering push and email, Then layout and punctuation are RTL-compliant.
Secure Link Tracking and Deep Linking Across Channels
- Given any action link is generated, When the message is sent, Then each link is signed with a per-recipient token that expires in 24 hours and encodes job ID, channel, and recipient ID. - Given a recipient clicks a link, When redirect service processes the request, Then the system records click timestamp, channel, and action, and forwards to the deep link (app) if installed or responsive web fallback otherwise. - Given email messages, When links are generated, Then UTM parameters are appended for source attribution without exposing PII. - Given SMS character limits, When generating link(s), Then links are short-coded to <= 23 characters using the approved domain and remain resolvable for at least 30 days.
Regulatory Compliance: Opt-In/Opt-Out and Quiet Hours Enforcement
- Given per-channel consent records exist with timestamp and source, When sending, Then the system sends only to channels with active opt-in and suppresses opted-out channels; email includes functional unsubscribe; SMS supports STOP/UNSTOP. - Given quiet hours are configured for a user (e.g., 22:00–07:00 local time), When an Exception Pulse is generated during quiet hours and no override is set, Then push and SMS are queued for delivery at the end of quiet hours while in-app and email follow policy settings. - Given an override policy "Always notify for safety-critical exceptions" is flagged on the job, When in quiet hours, Then push/SMS may be sent immediately and the audit log records the override reason. - Given regional requirements (e.g., US 10DLC compliance for SMS), When determining sender IDs, Then the system selects a compliant sender profile for the recipient’s country and blocks sends where compliance prerequisites are unmet, recording the block as 'Regulatory Blocked'.
Adaptive Rate Limiting and Provider Throttling Protection
- Given per-tenant rate limits of 60 SMS/min, 120 emails/min, and 120 push/minute, When Exception Pulses are burst-generated, Then the system schedules sends to stay within limits using token-bucket with jitter and preserves per-recipient chronological order. - Given per-recipient limits of 3 external notifications in 10 minutes, When the limit would be exceeded, Then subsequent sends are deferred until the window resets and the workflow engine is notified of the deferred state. - Given provider returns 429 (throttled), When retrying, Then the system backs off per provider-recommended Retry-After or doubles the backoff up to a max of 15 minutes. - Given messages are deferred due to rate limiting, When capacity is available, Then deferred messages are automatically resumed without manual intervention, preserving escalation SLAs where possible and flagging any SLA breaches.

Reason Tags

Standardized, customizable line‑item reason codes vendors must select when proposing over‑cap work (e.g., code violation, hidden damage, warranty void). Evidence requirements (photo/notes) are enforced per tag. This creates clear, auditable justification and surfaces patterns to optimize policies and vendor coaching.

Requirements

Reason Tag Library Management
"As a property manager, I want to define and maintain a standardized set of reason tags so that vendors provide consistent, comparable justifications for over‑cap proposals."
Description

Provide a centralized library where admins can create, edit, organize, and deactivate standardized reason tags used when vendors propose work that exceeds spend caps. Each tag includes a human‑readable name, short code, description, category, and status, and can be grouped for easy discovery. Tags can be set at account or portfolio level with inheritance and local overrides. The library supports search and sorting for quick maintenance, and exposes the active set to vendor flows via API so vendors always see the current, approved tags. Changes are tracked in an activity log to ensure auditability and historical context across work orders.

Acceptance Criteria
Create Tag with Required Fields and Uniqueness
Given I am an admin in the Reason Tag Library at the Account or Portfolio scope When I create a tag providing name, shortCode, description, category, and status=Active Then the tag is saved with a unique system id and timestamps And name, shortCode, category, and status are required and validated And shortCode is unique within the selected scope And the new tag appears in the library list filtered to its scope
Edit Tag and Activity Log Entry
Given an existing tag in the library When I update any of its fields (name, shortCode, description, category, status) Then the tag reflects the new values And an activity log entry records who changed what and when, including before and after values And the activity log is accessible from the tag detail and the global audit view
Deactivate Tag Removes It From Vendor Selection
Given a tag is Active and exposed to vendor flows When I change its status to Inactive Then the tag no longer appears in API responses used by vendor selection And existing work orders that referenced the tag continue to display it as read-only for audit history And an activity log entry records the status change
Account-to-Portfolio Inheritance and Local Overrides
Given an Account-level tag exists When a Portfolio is linked to the Account Then the Portfolio inherits the tag by default When a Portfolio admin creates a local override of the inherited tag Then the override’s values take precedence for that Portfolio’s UI and API And the Account-level tag remains unchanged And the library prevents duplicate shortCodes within the effective set for the Portfolio And the UI labels overridden vs inherited tags
Grouping and Categorization for Discovery
Given groups exist in the library When I assign tags to a group and set their category Then the library UI can filter tags by group and by category And removing a group does not delete its tags; their group becomes unset And group membership and category appear in list and detail views
Search and Sort Across the Library
Given a library with many tags When I search by keyword across name, shortCode, and description Then only matching tags are returned And I can sort results by name, category, status, or lastUpdated And search and sort respect the selected scope (Account or a specific Portfolio)
Vendor API Returns Active, Scoped Tags
Given a vendor session is associated to Portfolio P When the vendor fetches the reason tags via the API Then the response contains only Active tags effective for P (Portfolio overrides plus non-overridden Account tags) And each tag includes id, name, shortCode, description, category, status, sourceScope, and updatedAt And tags are returned in alphabetical order by name And changes in the library are reflected in API responses without manual cache invalidation
Evidence Enforcement Engine
"As a landlord, I want tags to require specific evidence so that I can quickly verify the legitimacy of over‑cap requests without back‑and‑forth."
Description

Enable per‑tag evidence requirements that are enforced at submission time, ensuring vendors attach the correct proof for their selected reasons. For each tag, admins can configure required evidence types (photos, annotated photos, notes, documents), minimum counts, note length, and specific prompts. The engine validates evidence both client‑side and server‑side, blocks submission until requirements are met, and stores evidence with timestamps and provenance linked to the work order’s photo‑timeline. Clear, actionable error messages guide vendors to resolve gaps, while APIs enforce the same rules for third‑party integrations.

Acceptance Criteria
Client-Side Submission Block for Tag-Specific Evidence
Given a vendor selects reason tag "Code Violation" configured to require 2 photos and a note of at least 150 characters When the vendor attempts to submit with 1 photo and an 80-character note Then the submission button remains disabled and inline errors list: "Code Violation: add 1 more photo" and "Code Violation: note must be at least 150 characters" And when the vendor adds 1 additional photo and expands the note to 150+ characters Then the errors clear in real time and the submission button becomes enabled
Server-Side and API Validation Parity
Given a proposal is submitted via API with reason tag "Hidden Damage" configured to require 1 annotated photo and 1 document When the payload lacks an annotated photo and document Then the API responds with HTTP 422 and a machine-readable error payload containing entries for tag "Hidden Damage" enumerating missing types "annotated_photo" (missing_count=1) and "document" (missing_count=1) And when a valid payload including 1 annotated photo (with annotation metadata) and 1 document is submitted Then the API responds with HTTP 201 and the created evidence records are persisted and linked to the proposal
Evidence Stored with Timestamps, Provenance, and Photo-Timeline Linking
Given a successful submission containing photos, annotated photos, notes, and documents across selected tags Then each evidence record is persisted with: server-side timestamp (UTC), tag_id, work_order_id, submitting_user_id or integration_id, source ("web","mobile","api"), and checksum And the work order's photo-timeline shows entries for each photo and annotated photo in chronological order by server timestamp with annotation overlays rendered for annotated photos And evidence records and timeline entries are immutable after submission; any later edits create new versions with new timestamps and preserve original records
Multi-Tag Validation Requires Per-Tag Completion and Assignment
Given the vendor selects tags "Warranty Void" (requires 1 document) and "Hidden Damage" (requires 2 photos) And the vendor uploads 2 photos and 1 document without assigning them to tags When the vendor attempts submission Then submission is blocked with errors indicating both tags are incomplete and prompting assignment of evidence to each tag And when the vendor assigns the 2 photos to "Hidden Damage" and the document to "Warranty Void" Then submission succeeds And evidence counts only toward the tag to which each item is explicitly assigned
Annotated Photo Requirement Enforcement
Given a tag "Code Violation" configured to require 1 annotated photo When the vendor uploads a standard photo without any annotations Then the engine does not count it toward the requirement and displays an error prompting to add at least one annotation And when the vendor adds an annotation overlay to the photo Then the requirement is satisfied and the error clears
Admin Configures Per-Tag Evidence Rules and Prompts
Given an admin opens the Reason Tag configuration for "Hidden Damage" When the admin sets required types to Photos: min=2 and Notes: min_length=120, and sets a vendor prompt "Describe how the damage was concealed" And saves the configuration Then the configuration persists and is retrievable via admin UI and configuration API And new vendor sessions reflect the updated rules And vendor submission flows (UI and API) enforce the new rules and display the configured prompt for "Hidden Damage"
Over‑Cap Proposal Tagging Flow
"As a vendor, I want a clear, guided way to select reasons and attach the required proof when proposing over‑cap work so that my submission is approved faster."
Description

Integrate reason tag selection directly into the vendor over‑cap proposal workflow. When a vendor adds a line item exceeding the cap, the UI prompts them to select one or more tags, displays tag descriptions for clarity, and dynamically requests the evidence specified by those tags. Submission is disabled until all tag requirements are satisfied. The flow supports multi‑select, inline guidance, and mobile‑friendly capture of photos and annotations. Configuration allows enabling an Other option with mandatory free‑text justification when permitted by policy.

Acceptance Criteria
Prompting Vendor to Tag Over‑Cap Line Item
Given a vendor adds or edits a line item whose total exceeds the configured cap When the line item total is saved or focus leaves the amount field Then the tagging UI is displayed inline for that line item And the list of reason tags is loaded from the property's active policy And each tag shows a short description on hover (desktop) or tap (mobile) And multiple tags can be selected And the "Other" tag is only shown when enabled by policy And if the line item total is reduced to at or below the cap, the tagging UI hides and any unsatisfied tag requirements are cleared without blocking submission
Enforcing Tag‑Specific Evidence Requirements
Given one or more tags are selected When evidence requirements are evaluated Then the system derives the union of required evidence across all selected tags And duplicate requirements are deduplicated And each requirement displays as a checklist with completion state And for photo requirements, the minimum count per tag is enforced; for notes requirements, a notes field is required and validated per configuration And the Submit Proposal action remains disabled until all required evidence items are satisfied And removing a tag immediately re‑evaluates and updates required evidence
Mobile‑Friendly Photo Capture and Annotation
Given a vendor uses a mobile device When the vendor adds required photos Then they can capture via device camera or upload from gallery And the app supports annotating photos with arrows and text boxes And each photo stores a timestamp and line item association And minimum resolution of 1024x768 is enforced via client‑side validation And the UI remains usable on 360px wide screens without horizontal scrolling
"Other" Tag Free‑Text Justification
Given policy enables the Other tag When the vendor selects Other Then a free‑text justification field is displayed and required And submission is blocked until at least 20 non‑whitespace characters are entered And the justification is saved with the line item and included in the proposal payload and audit trail
Submission Gate and Error Handling
Given required tags or evidence are incomplete When the vendor attempts to submit the proposal Then submission is prevented and inline validation messages identify missing items And the first incomplete requirement is scrolled into view and focused And when a network error occurs during photo upload, the UI shows a retry option and preserves form state And a progress indicator shows upload progress per photo
Data Persistence and Audit Trail
Given a proposal is saved as draft or submitted When the data is persisted Then each line item stores selected tag IDs, evidence metadata, and any justification text And all photos are linked to the line item and included in the annotated timeline And the API payload includes tag IDs, evidence satisfaction details, and justification text per line item And audit exports display tags and evidence per line item
Property Policy Scoping and Defaults
Given a vendor opens the over‑cap tagging UI for a line item on a property When the system loads configuration Then only tags enabled for the property's active policy are displayed And tag descriptions reflect the policy language configured for that property And if no tags are configured, a safe default set is displayed and a configuration warning is logged for admins And the visibility of the "Other" tag respects the property's enablement setting
Owner Review and Audit Trail
"As an owner, I want to review over‑cap requests with clearly labeled reasons and linked evidence so that I can make confident, defensible decisions quickly."
Description

Present selected tags and their attached evidence prominently in the owner approval screen and persist them as an immutable part of the work order record. Evidence is embedded in the photo‑timeline and linked to the exact proposal line items, with timestamps and submitter identity. Reviewers can quickly scan reasons, open evidence, and approve, reject, or request changes. All actions are logged and included in exports and shareable reports to create an auditable trail that reduces disputes and supports compliance documentation.

Acceptance Criteria
Owner Approval Screen Shows Reason Tags and Evidence
Given a work order has at least one over-cap proposal line item with selected reason tags and required evidence attached by a vendor When an owner or delegated approver opens the approval screen for that work order Then each affected line item displays its selected reason tags as badges in the line item header And each tag badge shows an evidence count by type (photos, notes) And the first three photo thumbnails render inline beneath the line item within 2 seconds on a standard broadband connection And a View all evidence action opens a panel with full-size media and notes without page navigation And selecting a tag filters the evidence list to only items attached to that tag
Evidence Embedded in Photo-Timeline and Linked to Line Items
Given evidence items are attached to tags on proposal line items When the photo-timeline is viewed for the associated work order Then each evidence item appears in chronological order with an annotation containing line item ID, tag name, UTC timestamp to the second, and submitter identity (name and role) And clicking a timeline entry navigates to the corresponding proposal line item and highlights it for at least 3 seconds And returning to the timeline preserves the previous scroll position
Approve, Reject, or Request Changes with Inline Summary
Given the owner is on the approval screen with line items and their reason tags visible When the owner chooses Approve, Reject, or Request Changes for a specific line item or the entire proposal Then a confirmation summary displays the selected tags and evidence counts for the scope of the decision And the owner can add an optional comment between 0 and 1000 characters And on confirmation, the decision is recorded with scope (line item or proposal), actor identity, and UTC timestamp And the UI updates the status labels in place within 1 second to reflect the decision
Immutable Reason Tags and Evidence Snapshot After Submission
Given a vendor has submitted a proposal containing reason tags and attached evidence When any user attempts to edit or delete a submitted tag or its evidence in that proposal revision Then the system blocks the modification and prompts the user to create a new revision And the prior revision remains read-only and accessible And the audit log records the attempted edit with actor, UTC timestamp, action, and outcome blocked
Comprehensive Audit Log Captures Review and Evidence Context
Given any approval action (approve, reject, request changes) or proposal revision occurs on a work order When the audit log is viewed or exported Then a corresponding entry exists including fields: work order ID, line item ID or All, action, actor name and role, UTC timestamp, related tag names, evidence IDs, previous status, new status, and optional comment And audit entries are immutable and strictly ordered by timestamp
Exports and Shareable Reports Include Tags, Evidence, and Decisions
Given a work order has proposal line items with reason tags, attached evidence, and recorded review decisions When a user generates the audit CSV export and the shareable report (PDF or web) Then the CSV contains one row per audit event with the fields defined in the audit log acceptance criteria And the report includes per-line-item sections showing tags, evidence thumbnails with captions, submitter identity, and UTC timestamps, with links to full-size media where applicable And the generated artifacts display the work order ID and a generated-on UTC timestamp on the cover or header
Reason Tag Analytics and Insights
"As an operations lead, I want analytics on reason tag usage and outcomes so that I can refine policies and coach vendors where issues recur."
Description

Provide reporting that surfaces patterns in over‑cap justifications to inform policy and vendor coaching. Dashboards show tag frequency, approval rates, average over‑cap deltas, vendor and property breakdowns, and trends over time. Filters support portfolio, property, vendor, tag, and date ranges. Data can be exported for further analysis. Insights help identify training opportunities, recurring issues like hidden damage, and potential policy adjustments to reduce delays and costs.

Acceptance Criteria
Tag Frequency and Approval Rate Dashboard Visibility
Given a user with Analytics access and data exists for the selected date range When the user opens Analytics > Reason Tags Then the dashboard displays: total over-cap proposals, a tag frequency table (Tag, Count, % of total), approval rate per tag (% approved of proposals), overall approval rate, average over-cap delta per tag, and last data refresh timestamp And values reflect only data within the active filters And percentages are rounded to one decimal and sums are consistent within ±0.1% due to rounding
Over‑Cap Delta Calculation and Aggregation
Given a proposal with proposed_total = $1,200 and cap_at_request = $1,000 When calculating over-cap delta Then delta = $200 and it is included in averages and distributions for the selected tag and period Given a proposal with proposed_total = $950 and cap_at_request = $1,000 When calculating over-cap delta Then delta = -$50 and it is included in averages and distributions And average delta per tag = arithmetic mean of all proposal deltas within filters, displayed with 2 decimal places And totals/averages shown in UI match the exported dataset calculations exactly
Vendor and Property Breakdown with Drill‑Through
Given the dashboard shows a breakdown by vendor and by property When the user clicks a vendor name Then a drill-through view opens filtered to that vendor, preserving all other active filters, showing: tag frequency, approval rate, average delta, count of proposals, and a table of underlying proposals with IDs and timestamps When the user navigates back Then the original aggregate view and filters are preserved And counts in breakdown totals equal the parent totals under the same filters
Trend Analysis Over Time (Weekly/Monthly)
Given at least 6 months of data exists When the user switches the trend granularity from Monthly to Weekly Then the time-series for tag frequency, approval rate, and average delta recalculates using ISO week boundaries and matches the aggregate totals for the period within ±0.1% And users can toggle a prior-period comparison which overlays values for the previous equal-length period And the trend chart renders first contentful paint within 4 seconds for up to 100k proposals in the selected range
Filter Application and Combinability
Given filters for Portfolio, Property, Vendor, Tag (multi-select), and Date Range (Last 7/30/90/365 days, Custom) When the user applies any combination of these filters Then all widgets update consistently within 2 seconds for up to 50k proposals And a filter summary shows active filters as removable chips And clearing all filters resets to default (Last 90 days) and full dataset visibility And when filters yield zero results, an empty state appears with a prompt to adjust filters and an Export action is disabled
Data Export with Filter Fidelity
Given an analytics view with active filters When the user exports data as CSV or XLSX Then the exported file contains a header section listing applied filters, export timestamp (UTC), and column definitions And the dataset includes one row per proposal with at least: proposal_id, proposal_timestamp, property_id/name, vendor_id/name, tag, approval_status, proposed_total, cap_at_request, over_cap_delta, approved_amount (if applicable), evidence_compliance (true/false) And the number of exported rows equals the UI total for the same filters And exports up to 100k rows complete within 60 seconds and file encodings open without warnings in Excel and common spreadsheet tools
Insight Flags for Coaching and Policy Adjustment
Given data exists for at least 90 days and minimum counts are met When automated insight rules execute nightly Then insight cards are generated for: (a) Vendor approval rate outliers (≥2 SD below portfolio mean with ≥30 proposals), (b) Tags with rising trend (≥30% increase over prior period with ≥20 proposals), (c) High average delta tags (avg delta ≥ portfolio 75th percentile with ≥20 proposals), (d) Properties with recurring hidden-damage justifications (≥3 occurrences in 60 days) And each card shows the rule, affected entities, metric values, time window, and a deep link to a pre-filtered drill-down And users can Dismiss or Snooze (7/30/90 days) an insight, which is recorded with user, timestamp, and reason And in controlled test datasets meeting these thresholds, the expected cards appear; when thresholds are not met, no cards appear
Tag‑Based Policy Automation
"As a property manager, I want rules that act on specific reason tags so that routine, low‑risk over‑cap requests are handled automatically and I can focus on exceptions."
Description

Allow admins to define workflow rules that trigger based on selected tags and proposal attributes. Policies can auto‑approve within thresholds, route for escalation, require a second quote, adjust spend caps for specific tags, or notify stakeholders. The rules engine evaluates tags, amounts, property type, vendor history, and evidence completeness to automate decisions and reduce manual review time, while maintaining safeguards for high‑risk scenarios.

Acceptance Criteria
Auto-Approve Low-Risk Tag Within Spend Threshold
Given a proposal marked over-cap with Reason Tag 'Hidden Damage' categorized as Low Risk And the proposal amount is less than or equal to the configured auto-approve threshold for 'Hidden Damage' for the property's type And all evidence requirements for 'Hidden Damage' are satisfied (min photos, notes) When the rules engine evaluates the proposal Then the proposal is auto-approved without human review And the decision record includes ruleId, evaluated thresholds, and tagId And the vendor and assigned property manager are notified immediately And a timeline entry is created summarizing the decision and attached evidence
Escalate High-Risk Code Violation Above Cap
Given tag 'Code Violation' categorized as High Risk And the adjusted cap (after tag/property modifiers) is less than the proposal amount And all required evidence is present When the rules engine evaluates Then the proposal is routed to the 'Compliance Review' queue And the owner and property manager receive notifications within 5 minutes And vendor sees status 'Pending Escalation' And no auto-approval occurs and spend is not committed
Require Second Quote for Warranty Void with Low Vendor Reliability
Given tag 'Warranty Void' And vendor reliabilityScore < configured threshold OR vendorOverCapRate(90d) > configured threshold And proposal amount is within the second-quote range for this tag and property type When the rules engine evaluates Then the system flags 'Second Quote Required' and blocks approval And sends second-quote request to the vendor with due date 48 hours from request And creates a task for the property manager And auto-escalates if the second quote is not received by the due date
Adjust Spend Caps Based on Property Type and Tag
Given property type is 'Multi-Family' And tag 'Code Violation' has a +20% cap modifier for Multi-Family When evaluating the effective spend cap Then the effective cap equals baseCap(property) * 1.20 And this effective cap is used for all comparisons in the same evaluation And the computed cap is stored in the decision record
Evidence Completeness Blocks Decision
Given tag 'Hidden Damage' requires 2 photos and 1 note And the proposal provides fewer than 2 photos OR no note When the rules engine evaluates Then the decision returned is 'Insufficient Evidence' And the vendor is presented with a checklist of missing items And no escalation or approval actions are triggered And the proposal cannot be submitted for review until evidence is complete
Decision Precedence and Conflict Resolution
Given multiple rules apply producing conflicting outcomes When the rules engine evaluates Then decision precedence is applied in this order: High-Risk Escalation > Second Quote Required > Auto-Approve > Notify Only And exactly one final decision state is recorded And suppressed rules and their ruleIds are captured in the audit log
Audit Logging and Timeline Annotation
Given any rule evaluation completes When a decision is produced Then an audit record is written including ruleIds applied, suppressed ruleIds, tags, inputs (amount, propertyType, vendorScore, evidenceStatus), outcome, and timestamp And the audit record is retrievable via API within 2 seconds And a timeline note is added linking the decision to the proposal and evidence
Permissions and Versioning Controls
"As an account admin, I want controlled access and version history for tags and rules so that changes are traceable and past records remain consistent."
Description

Introduce fine‑grained permissions for creating, editing, and deactivating tags and policies, plus versioning to preserve historical context on existing work orders. Role‑based access ensures only authorized users modify tags and automation rules. Each change creates a new version with timestamp, author, and change summary. Work orders retain references to the exact tag definitions used at submission time to guarantee consistent auditability over time.

Acceptance Criteria
RBAC: Manage Tags and Policies
- Given a user with role Account Owner or Tag Admin, When they create, edit, or deactivate a tag or policy, Then the action succeeds and a new version is recorded. - Given a user with role Vendor, Viewer, or Manager without Tag Admin permission, When they attempt to create, edit, or deactivate a tag or policy, Then the system blocks the action with a 403 permission error and no changes are saved. - Given role assignments are changed, When the user re-attempts the action, Then the updated permissions apply immediately to the next request.
Versioning: Metadata Capture on Change
- Given any create, edit, or deactivate operation on a tag or policy, When the change is saved, Then an immutable version is created with fields: versionId, parentId, authorUserId, ISO-8601 UTC timestamp, changeSummary, and changeType (CREATE/UPDATE/DEACTIVATE). - Given a user attempts to save without a non-empty changeSummary, When they submit, Then the save is rejected with a validation error and no version is created. - Given prior versions exist, When viewed, Then they are read-only and display a diff of changed fields versus the previous version.
Immutability: Work Orders Preserve Tag Version
- Given a work order submitted using tag version V, When that tag or policy is later updated or deactivated, Then the work order continues to reference version V for display, evidence validation, and reporting. - Given an auditor views the work order, When inspecting metadata, Then the tag name, versionId, and version timestamp used at submission are visible and immutable.
Deactivation: Safe Sunsetting of Tags and Policies
- Given a tag or policy is deactivated effective immediately, When a vendor initiates a new over-cap proposal, Then the deactivated item is not selectable in the UI or via API. - Given an authorized user views the tag list, When filters are default, Then deactivated items are hidden; When "Include deactivated" is enabled, Then they appear with a Deactivated badge and effective end date. - Given a deactivated tag is referenced by at least one work order, When a user attempts permanent deletion, Then the system prevents deletion and displays that it is in use.
Concurrency: Optimistic Locking on Edits
- Given two authorized users open the same tag or policy for editing, When User A saves creating version V+1, Then User B's subsequent save is rejected with a 409 Conflict and guidance to refresh. - Given a 409 Conflict occurs, When the client receives the response, Then the latest version metadata (versionId, timestamp, author) is returned and no partial or duplicate version is created.
Evidence Rules Version Consistency
- Given the evidence requirements for a tag are changed in a new version, When a new work order is created after the change, Then evidence validation uses the latest tag version's rules. - Given an existing work order was created before the change, When a vendor adds information or resubmits, Then validation continues to use the evidence rules from the tag version stored on that work order. - Given a vendor attempts to submit without the required evidence per the applicable tag version, When they submit, Then the system rejects the submission and lists the missing evidence items.

Invoice Guard

OCR + line‑item matching compares submitted invoices against pre‑approved amounts and Reason Tags. Variances within tolerance auto‑approve; mismatches are flagged, blocked from payment, and returned to the vendor with precise fix requests. This stops invoice creep and eliminates end‑of‑month reconciliation drama.

Requirements

OCR Extraction & Normalization
"As an owner-operator, I want invoice data auto-extracted and standardized so that I don’t rekey fields and can reliably compare charges against what was pre-approved."
Description

Implement an OCR pipeline that ingests invoices from PDFs, images, email attachments, and vendor portal uploads; extracts header fields (vendor, invoice #, date, PO/work order, currency, tax IDs), line items (description, quantity, unit, unit price), and totals; and normalizes all data into a canonical invoice schema. Include confidence scoring with threshold-based routing to manual review, multi-page handling, multi-currency/tax detection, duplicate detection (vendor + invoice # + amount), and secure storage. Integrate with FixFlow vendor profiles and associated work orders to pre-link invoices to the correct job for downstream matching.

Acceptance Criteria
Multi-Source Invoice Ingestion and Source Attribution
Given a vendor submits an invoice file of type PDF, JPEG, PNG, TIFF, or HEIC via the Vendor Portal upload, when the file size is ≤ 50 MB and the document has ≤ 30 pages, then the system stores the raw file in secure storage, creates an ingestion record with channel=portal, and associates the submission to the authenticated vendor profile. Given a vendor emails invoices to the designated intake alias with 1–10 attachments (PDF/JPEG/PNG/TIFF/HEIC), when the email is processed, then each supported attachment is ingested as a separate invoice, the channel=email is recorded, unsupported attachments are ignored and logged, and the sender address is matched to a known vendor profile or flagged for manual association. Given an API client posts an invoice file to the ingestion endpoint with a valid vendor_id, when the request is authenticated and the payload is valid, then the system ingests the file, records channel=api, and links the submission to the provided vendor_id. Given a corrupted or password-protected PDF is received, when ingestion is attempted, then the system rejects the file, records an error with reason, notifies the submitter (portal UI message or email bounce reply), and no OCR is attempted. Given a file of an unsupported type or exceeding size/page limits is received, when validation runs, then the system rejects the file with a clear error detailing allowed types and limits and logs the rejection.
Canonical Schema Extraction & Normalization (Headers, Lines, Totals, Currency/Tax)
Given a successfully ingested invoice, when OCR/extraction completes, then the system outputs a canonical JSON with required header fields: vendor_id, vendor_name, invoice_number, invoice_date (ISO 8601 YYYY-MM-DD), currency_code (ISO 4217), tax_ids[], po_number, work_order_ref (if present). Given line items are present, when extraction runs, then each line includes: description (string), quantity (float), unit (from canonical unit set), unit_price (decimal), line_total (decimal), and the system computes line_total=quantity×unit_price within a tolerance of max(0.01, 0.5% of computed) per line. Given totals region is present, when normalization runs, then subtotal, tax_amount, discount_amount (if any), and total_amount are populated such that subtotal + tax_amount − discount_amount equals total_amount within max(0.01, 0.5% of total_amount); discrepancies are flagged. Given dates, numbers, and currencies are extracted, when normalization runs, then dates are ISO 8601, decimals use dot separator, thousands separators are removed, and currency_code is set using explicit code/symbol heuristics or falls back to vendor default if ambiguous (and marked with ambiguity flag). Given tax identifiers are detected (e.g., US EIN, EU VAT, CA GST/HST, AU ABN), when normalization runs, then each tax_id is validated against format rules per country and stored as {country_code, type, value}. Given units are extracted in varied forms (e.g., pcs, piece, EA), when normalization runs, then units are mapped to canonical enumerations (e.g., EA) with the original preserved in metadata.
Confidence Scoring and Manual Review Routing
Given field-level OCR confidences are produced (0.0–1.0), when normalization completes, then the system calculates a document_score as the weighted average of required fields (headers 60%, totals 20%, critical line columns 20%). Given the document_score ≥ 0.85 and all required header fields have confidence ≥ 0.90, when routing is evaluated, then the invoice is marked auto-extracted and proceeds without manual review. Given any required header field confidence < 0.90 or document_score < 0.85, when routing is evaluated, then the invoice is placed in the manual review queue with low-confidence fields highlighted and reasons enumerated. Given manual review is completed by an authorized user, when edits are saved, then the final canonical JSON reflects corrections, the routing status updates to reviewed, and an audit entry records original vs corrected values and reviewer identity.
Multi-Page Document Handling
Given a multi-page invoice (2–30 pages) is ingested, when OCR runs, then page order is preserved and stored, and text blocks are associated to their page indices. Given line items span multiple pages, when line-item extraction runs, then the system aggregates contiguous line tables across pages without duplicating header rows and preserves item order. Given totals appear only on the last page, when totals extraction runs, then subtotal/tax/total are correctly captured from the last page and associated to the document-level totals. Given page footers or repeated headers are present, when extraction runs, then those repeated elements are not misclassified as line items (≤ 1 false positive per document).
Duplicate Invoice Detection and Blocking
Given a newly extracted invoice with vendor_id, invoice_number, currency_code, and total_amount, when an existing invoice with the same vendor_id and invoice_number exists and the absolute difference in total_amount ≤ 0.01 in the same currency, then the new invoice is marked Duplicate=True, blocked from further processing, and the submitter is notified with the reference to the existing invoice. Given invoice_number is missing or differs by minor formatting, when fuzzy duplicate checks run, then if a match score ≥ 0.95 based on vendor_id + total_amount + invoice_date (±3 days) + po/work_order_ref, the invoice is blocked as a probable duplicate; if 0.80–0.94, it is flagged for review with duplicate candidates listed. Given a duplicate is detected, when the system responds, then no payment or downstream matching is initiated for the duplicate, and an audit entry records the duplicate detection criteria and matched invoice IDs.
Work Order Auto-Linking via Vendor Profiles
Given the vendor is identified and a work order or PO number is present on the invoice, when matching runs, then the invoice is automatically linked to the single open work order for that vendor with the same identifier; the link is recorded on the invoice and work order timelines. Given multiple candidate work orders are found (e.g., similar numbers or multiple open), when matching runs, then the top 3 candidates are attached with confidence scores; if the top score ≥ 0.90 and unique, auto-link; otherwise, require reviewer selection. Given no explicit identifier is found, when heuristics run, then the system may suggest candidates using property address, service date, and vendor history with a confidence score; suggestions are informational only unless ≥ 0.90. Given an invoice is linked, when the work order is closed, then the linkage remains and is immutable except by authorized users with changes audited.
Secure Storage and Audit Logging
Given any invoice file is ingested, when it is written to storage, then the raw file is encrypted at rest using AES-256 with per-tenant keys, and access is controlled by role-based permissions; all accesses are logged with user, action, timestamp, and IP. Given canonical JSON and extracted text are persisted, when data is stored or retrieved, then transport uses TLS 1.2+ and sensitive fields (tax_ids, bank details if present) are redacted in logs and masked in UI by default. Given backups occur, when backup jobs run, then backups are encrypted and restorable within the defined RTO/RPO; restore actions are audited. Given any create/update/delete of invoice data occurs, when auditing runs, then an immutable audit trail entry is created capturing before/after values, actor, timestamp, and reason code.
Line-Item Catalog Matching
"As a property manager, I want invoice line items matched to the pre-approved work order so that any overbilling or out-of-scope charges are caught immediately."
Description

Build a matcher that aligns extracted invoice line items to the associated work order’s pre-approved line items and Reason Tags using fuzzy text matching, synonym libraries, abbreviation expansion, and unit-conversion logic. Map lines to the FixFlow service catalog/SKUs, detect extra or missing items, consolidate duplicates, and support partial invoicing and multi-visit splits. Output a structured match result with per-line variance (qty, unit price, total) and unmatched-item reasons for the rules engine and feedback loop.

Acceptance Criteria
Exact match: SKU + Reason Tag + pricing equality
Given a work order with a pre-approved line item for catalog SKU FF-123 "Garbage Disposal Replacement" with Reason Tag "WearAndTear", qty 1, unit price $200 And an invoice OCR line "Garbage Disposal Replacement" with qty 1 and unit price $200 When the line-item matcher runs Then the invoice line maps to SKU FF-123 on the work order And the associated Reason Tag is "WearAndTear" And qtyVariance = 0, unitPriceVariance = 0, totalVariance = 0 And the line is marked as matched in the structured result
Fuzzy/synonym match to catalog SKU within configured threshold
Given a synonyms/abbreviation library containing {"HWT":"Water Heater", "WH":"Water Heater"} And the catalog contains SKU FF-456 "Water Heater Replacement" And the work order has a pre-approved line item for SKU FF-456, qty 1, unit price $900, Reason Tag "Emergency" And the invoice OCR line description is "Replace HWT", qty 1, unit price $900 And the fuzzy match threshold is configured to 0.80 similarity When the matcher evaluates the invoice line Then the description matches SKU FF-456 using synonym expansion and fuzzy text with similarity >= 0.80 And the line maps to SKU FF-456 on the work order And totalVariance = 0 And if the Reason Tag does not align to an approved tag, the line is flagged with unmatchedItemReason = "ReasonTagMismatch"
Unit conversion and UOM normalization used for variance
Given a pre-approved line item for SKU FF-789 "Copper Pipe Replacement" with qty 10 ft at $5/ft And an invoice OCR line "Replace copper pipe" with qty 3.048 m at a unit price equivalent to $5/ft When the matcher normalizes units using the conversion 1 m = 3.28084 ft Then the normalized invoice qty = 10 ft And qtyVariance = 0 and totalVariance = 0 And the structured result records the normalized UOM and values used for variance calculations
Duplicate line consolidation within a single visit
Given a work order with a pre-approved line item for SKU FF-321 "Electrical Labor" up to 2 hr at $100/hr And an invoice contains two OCR lines both describing "Electrical Labor" with quantities 1.5 hr and 0.5 hr at $100/hr each When the matcher processes the invoice Then the two invoice lines are consolidated into a single mapped line for SKU FF-321 with qty 2 hr and total $200 And qtyVariance = 0 and totalVariance = 0 against the pre-approval And the structured result preserves references to the source line IDs included in the consolidation
Partial invoicing and multi-visit split handling
Given a work order with a pre-approved line item for SKU FF-654 "HVAC Tune-Up" for 2 visits at $150 per visit And an invoice includes only 1 visit at $150 When the matcher runs Then the invoice line maps to SKU FF-654 with qty 1 visit and total $150 And the structured result records remainingApprovedQty = 1 visit and remainingApprovedTotal = $150 And no missing-item error is raised for the outstanding visit And subsequent invoices can map remaining qty without double-counting
Per-line variance computation and tolerance classification
Rule: For each matched line, compute qtyVariance = invoiceQty - approvedQtyUsed, unitPriceVariance = invoiceUnitPrice - approvedUnitPrice, totalVariance = invoiceTotal - approvedTotalUsed Rule: A line is withinTolerance = true iff abs(totalVariance) <= max(config.totalToleranceAmount, config.totalTolerancePercent * approvedTotalUsed) Given approvedTotalUsed = $150 and config = {totalToleranceAmount: $10, totalTolerancePercent: 0.05} When invoiceTotal = $155 Then totalVariance = $5 and withinTolerance = true When invoiceTotal = $170 Then totalVariance = $20 and withinTolerance = false
Unmatched items and missing approvals flagged with reason codes
Rule: If no catalog SKU meets the configured similarity threshold, mark the line unmatched with reasonCode = "NoCatalogMatch" and include top 3 candidate SKUs with similarity scores Rule: If multiple SKUs are within the ambiguity delta (e.g., <= 0.03 similarity difference), mark reasonCode = "AmbiguousMatch" and list candidates Rule: If description matches but the item is not pre-approved for the work order, mark reasonCode = "ExtraLineNotInScope" Rule: If UOM cannot be normalized to the catalog UOM, mark reasonCode = "UnsupportedUOM" Rule: If Reason Tag does not align to the approved Reason Tag(s), mark reasonCode = "ReasonTagMismatch" Rule: After matching, any pre-approved items without mapped invoice coverage are listed under missingApprovedItems with remaining qty and amount for downstream processing
Tolerance Rules Engine
"As a property manager, I want fine-grained tolerance rules so that small, acceptable variances pass automatically while meaningful discrepancies are blocked."
Description

Provide configurable tolerance rules that determine auto-approval vs. flagging by vendor, property, portfolio, service category, and Reason Tag. Support absolute and percentage thresholds, separate treatment of taxes/fees, caps on materials markup, after-hours/emergency surcharges, and effective-dated rule versions. Evaluate per-line and invoice-level variances in the context of currency and tax settings, and produce a decision payload (approve, hold, or reject with reasons) for workflow routing.

Acceptance Criteria
Rule Selection by Context and Effective Date
Given active tolerance rules exist at vendor, property, portfolio, service category, and Reason Tag scopes with effective date ranges And an invoice line contains vendor_id, property_id, portfolio_id, service_category_id, reason_tag_id, date_of_service, and invoice_date When the engine selects a tolerance rule for evaluation Then it chooses a single rule version whose effective date range covers date_of_service (or invoice_date if date_of_service is absent) And among all effective candidates, the rule with the greatest number of matching attributes to the invoice context is selected And ties are broken by scope precedence: Vendor > Property > Portfolio > Service Category > Reason Tag > Global default And if still tied, the candidate with the most recent effective_start is selected And if no candidate exists, the Global default rule is applied And the decision payload records rule_id and rule_version_id used
Per-Line Variance Evaluation (Absolute and Percentage)
Given a line item with pre_approved_amount and submitted_amount in currency_code C And the selected rule defines line_absolute_tolerance_amount and line_percentage_tolerance_rate And the rule optionally defines hard_reject_absolute and hard_reject_percentage thresholds When the engine computes variance_abs = |submitted_amount - pre_approved_amount| and variance_pct = variance_abs / pre_approved_amount Then if hard_reject thresholds are defined and (variance_abs > hard_reject_absolute OR variance_pct > hard_reject_percentage), the line_decision = reject with reason "LINE_VARIANCE_HARD_REJECT" And else if (variance_abs <= line_absolute_tolerance_amount OR variance_pct <= line_percentage_tolerance_rate), the line_decision = approve And else the line_decision = hold with reason "LINE_VARIANCE_EXCEEDS_TOLERANCE" And all amounts are rounded to the minor units defined for currency C before comparison
Invoice-Level Variance and Aggregate Decision
Given an invoice with N evaluated line items and a rule with invoice_absolute_tolerance_amount and invoice_percentage_tolerance_rate And taxes and fees are excluded from invoice variance if separate_taxes_fees = true in the rule When the engine computes invoice_pre_approved_total and invoice_submitted_total (after exclusions as configured) And computes invoice_variance_abs and invoice_variance_pct Then if any line_decision = reject, invoice_decision = reject and reasons include all reject reasons And else if all line_decisions = approve AND (invoice_variance_abs <= invoice_absolute_tolerance_amount OR invoice_variance_pct <= invoice_percentage_tolerance_rate), invoice_decision = approve And else invoice_decision = hold and reasons include violating conditions
Separate Treatment of Taxes and Fees
Given the invoice contains tax and fee items identifiable by type codes And the rule sets separate_taxes_fees = true with tax_tolerance_rate and fee_tolerance_amount per fee_type When evaluating variances Then tax and fee items are excluded from line and invoice variance calculations And tax_amount is validated against tax_tolerance_rate relative to taxable_subtotal; if exceeded, decision = hold and reason "TAX_OUT_OF_TOLERANCE" is added And each fee_type amount is validated against its fee_tolerance_amount cap; if exceeded, decision = hold and reason "FEE_OUT_OF_TOLERANCE" is added
Materials Markup Cap Enforcement
Given a materials line with cost_basis and submitted_amount and an optional receipt_attachment And the rule defines materials_markup_cap_rate and optionally materials_markup_cap_amount and receipts_required_for_materials When the engine computes allowed_markup = min(cost_basis * materials_markup_cap_rate, materials_markup_cap_amount if defined) Then if receipts_required_for_materials = true and receipt_attachment is missing, line_decision = hold with reason "MATERIALS_RECEIPT_MISSING" And else if submitted_amount - cost_basis <= allowed_markup, the markup portion is approved And else line_decision = hold with reason "MATERIALS_MARKUP_EXCEEDS_CAP"
After-Hours and Emergency Surcharge Validation
Given a labor line with a reason_tag of after_hours or emergency and a service timestamp in the property timezone And the rule defines after_hours_time_windows and surcharge_cap_rate and optionally surcharge_cap_amount When the timestamp falls within an after_hours_time_window or the emergency flag is permitted by the rule Then if surcharge_amount <= min(subtotal * surcharge_cap_rate, surcharge_cap_amount if defined), the surcharge portion is approved And else line_decision = hold with reason "SURCHARGE_EXCEEDS_CAP" And if the timestamp is outside allowed windows and no emergency override applies, line_decision = hold with reason "SURCHARGE_INVALID_WINDOW"
Decision Payload for Workflow Routing with Currency Context
Given evaluation has completed for all lines under a selected rule When the engine produces the decision payload Then the payload includes: invoice_decision in [approve, hold, reject], per_line decisions with reasons, rule_id, rule_version_id, currency_code, rounding_precision, tax_handling_mode, pre_approved and submitted totals (line and invoice), variance values, and next_action in [auto_approve, queue_review, return_to_vendor] And approve decisions set block_payment = false; hold or reject decisions set block_payment = true And all reason codes are machine-readable from a controlled vocabulary And all numeric amounts are rounded to the minor units defined by the invoice currency settings
Auto-Approve & Payment Hold Workflow
"As a property manager, I want within-tolerance invoices to auto-approve and out-of-tolerance ones to be held from payment so that I maintain cash flow while preventing overpayment."
Description

Orchestrate end-to-end workflow transitions based on match and rules decisions: auto-approve invoices within tolerance, set invoices out of tolerance to payment hold, and move hard mismatches to Needs Vendor Correction. Ensure idempotent payment readiness updates, duplicate prevention, and manual override with justification. Integrate with FixFlow’s payment/export layer (e.g., accounting sync or ACH partner) and owner notifications to keep cash flow moving without leakage.

Acceptance Criteria
Auto-Approve Within Tolerance
Given an invoice is linked to a work order with a pre-approved amount and tolerance rules per Reason Tag When OCR-extracted line items align to the approved scope and the net variance is within both the configured percentage and absolute thresholds (e.g., <=5% and <=$20) Then the invoice status is set to Approved, payment_readiness=true, payment_hold=false, and a decision record (DecisionType=AutoApprove, RuleId, Timestamp) is created And the invoice is enqueued exactly once to the payment/export layer with a deterministic idempotency key and external_id And an owner notification is sent containing invoice_id, vendor, total, and rule matched; duplicate notifications for the same decision are suppressed
Payment Hold for Out-of-Tolerance Variance
Given tolerance rules exist for the invoice’s Reason Tag and pre-approved amount When the invoice line items match the approved scope but the variance exceeds either the percentage or absolute threshold Then the invoice status is set to Payment Hold with reason_codes=["VarianceExceeded"], payment_readiness=false, and export/payment are blocked And a decision record is created with the computed variance and thresholds evaluated And no vendor correction request is sent automatically; an internal reviewer is notified
Needs Vendor Correction for Hard Mismatch
Given an invoice contains scope or line-level mismatches (e.g., extra line not in approval, missing required line, unit price change on fixed-price item) When the invoice is evaluated Then the invoice status is set to Needs Vendor Correction, payment_readiness=false, and export/payment are blocked And the vendor is notified with a structured correction request listing line-level issues, expected fixes, and a resubmission link And the system records reason_codes per mismatch (e.g., "LineNotApproved", "MissingLine", "UnitPriceMismatch") and attaches annotated evidence (e.g., line refs, amounts)
Idempotent Decisioning and Payment Readiness Updates
Given the same invoice is ingested or evaluated multiple times with identical inputs When decisioning runs repeatedly Then the invoice state, payment_readiness flag, decision record, and export queue entries remain unchanged after the first decision And no duplicate notifications (owner or vendor) are sent; prior notification ids are reused And idempotency is verifiable via a stable decision_hash over inputs and rules
Duplicate Invoice Prevention
Given an existing invoice for the same vendor_id and invoice_number OR a matching file_hash OR (same work_order_id and total within $1) exists within the last 90 days When a new invoice is submitted Then the new invoice is not approved nor exported; it is set to Payment Hold with reason_codes=["DuplicateDetected"], payment_readiness=false And the hold references the suspected duplicate invoice_id(s) And an internal alert is sent to the reviewer; no vendor notification is sent automatically And only one hold record is created even if the invoice is resubmitted multiple times
Manual Override with Justification and Audit Trail
Given a user with Approver role opens an invoice in Payment Hold or Needs Vendor Correction When the user selects an override action (Approve, Keep Hold, Request Correction) and provides a justification of at least 20 characters Then the override is applied, capturing user_id, timestamp, previous_state, new_state, justification, and reason_codes in the audit log And if overridden to Approved, payment_readiness=true and the invoice is enqueued to the export layer with the same idempotency key semantics And owner notification includes an "Override Applied" marker and justification summary And overrides without justification are rejected with a validation error
Payment/Export Integration Success and Failure Handling
Given an invoice is Approved and payment_readiness=true When the payment/export dispatcher attempts delivery to the accounting/ACH partner Then on HTTP 2xx, export_status=Succeeded, external_payment_id is stored, and no duplicate export attempts occur And on non-2xx or timeout, export_status=RetryPending, the invoice remains Approved, and retries are scheduled with exponential backoff and a maximum of 5 attempts using the same idempotency key And when retries are exhausted, owner is notified with failure details and no payment is issued twice
Vendor Feedback Loop with Precise Fix Requests
"As a vendor, I want clear, actionable fix requests when my invoice is rejected so that I can correct and resubmit quickly without guesswork."
Description

Automatically generate structured discrepancy reports for rejected invoices, including line-by-line diffs (expected vs. billed), required corrections, and suggested Reason Tags. Deliver via email and vendor portal with deep links to a resubmission form that preserves version history. Include SLA timers, reminder cadence, and message templates by variance reason to reduce back-and-forth and accelerate clean resubmissions.

Acceptance Criteria
Rejected invoice triggers structured discrepancy report generation
Given an invoice is rejected by Invoice Guard due to variance outside tolerance or a mismatched line item When the rejection event is saved Then a structured discrepancy report is generated within 30 seconds And the report includes invoice ID, vendor ID, work order/reference, rejection reason(s), and creation timestamp And the report contains line-by-line diffs showing expected vs billed values for description, quantity, unit price, tax/fees, and totals And each discrepant line item lists required corrections and up to 3 suggested Reason Tags And the report computes total variance (amount and percentage) and highlights blocking discrepancies And the report is stored and associated to the invoice record for retrieval via the vendor portal
Discrepancy report delivery via email and vendor portal with secure deep link
Given a discrepancy report is generated When the vendor has a deliverable email on file Then an email is sent using the appropriate variance-reason template with subject "Action needed: Fix invoice {invoice_number}" And the email includes a deep link token to the resubmission form And the token is valid for 7 days, single-invoice scoped, and revocable by admins And if email bounces, a portal notification is created and the vendor is prompted to log in to view the report And accessing the deep link authenticates the vendor via token or prompts login if expired, then redirects to the resubmission form
Vendor resubmission via prefilled form preserves version history
Given a vendor opens the deep link for a rejected invoice When the resubmission form loads Then it is prefilled with the previously submitted invoice data and shows the discrepancy diffs inline And the vendor must resolve or acknowledge each required correction before submit And Reason Tag selection is required per discrepant line (preselected from suggested tags but editable) And the vendor can attach supporting documents/photos And upon submit, a new immutable invoice version is created and prior versions remain read-only and viewable with timestamps and submitter And the invoice remains payment-blocked until the latest version passes automated validation
SLA timers and reminder cadence for vendor corrections
Given a discrepancy report is created When SLA settings use the account defaults Then the response SLA is set to 5 business days from report creation in the property manager’s timezone And reminders are sent at 48 hours and 96 hours if no resubmission is received And if the SLA is breached, an escalation email is sent to the property manager and the ticket is marked Overdue And if the vendor requests clarification, the SLA timer pauses until the property manager replies And SLA and reminder cadence are configurable at account level and per-vendor override, applying to newly created reports
Variance reason–based message template selection
Given a discrepancy report contains one or more variance reasons When preparing outbound communication Then the system selects the highest-priority matching template (Unauthorized Work > Overcharge > Missing Documentation > Duplicate > Tax/Fees) And merges placeholders including vendor name, invoice number, due date, top discrepancy summary, and deep link URL And the chosen template language and formatting match the vendor’s preferred locale if configured And administrators can preview and update templates; published changes apply to communications generated after publication time
Line-by-line diff accuracy and coverage for multi-item invoices
Given an invoice with multiple line items is rejected When the discrepancy report is generated Then every discrepant line item shows expected vs billed for description, quantity, unit price, line total, tax, discounts, and notes And items not present on the work order are flagged as Unauthorized Work with required correction guidance And rounding tolerance is applied at min($1, 0.5%) per line; items within tolerance are not listed as discrepancies And the report shows a grand total variance equal to the sum of line variances plus tax/fees differences And line numbering and SKU/identifier references are preserved for traceability
Audit trail and payment block until clean resubmission approval
Given a discrepancy report exists for an invoice When any communication is sent or the vendor views, comments, or resubmits Then an audit log entry is recorded with actor, channel, timestamp, and payload reference And the invoice payment state is set to On Hold - Invoice Guard until a passing validation status is recorded And attempts to schedule payment while On Hold are blocked with a user-facing reason And the audit trail shows email delivery/bounce status and portal notification read receipts And authorized users can export the discrepancy history and all versions as a single PDF/ZIP bundle
Audit Trail & Photo-Timeline Linking
"As an owner, I want a complete, searchable audit trail tied to job photos so that I can resolve invoice disputes confidently and pass audits."
Description

Create an immutable, timestamped audit trail that records OCR outputs, line-item matches, rule evaluations, workflow changes, overrides (with reasons), and all vendor communications. Link each invoice to the job’s annotated photo-timeline and artifacts for evidentiary support. Provide export (PDF/CSV) and search capabilities to resolve disputes, satisfy owner audits, and reduce end-of-month reconciliation effort.

Acceptance Criteria
Immutable Audit Log Recording for Invoice Events
Given an invoice is processed via OCR When OCR completes Then an audit entry is appended capturing UTC ISO-8601 timestamp, invoice ID, job ID, OCR raw text, extracted fields with per-field confidence, actor=system, and a content hash Given line-item matching runs When each line is evaluated Then the audit log records matched pre-approved item ID, variance amount and percent, Reason Tag, rule IDs fired, and decision per line Given a workflow state changes When a state transition occurs (e.g., Auto-Approved, Flagged, Returned to Vendor, Paid) Then the audit log records prior state, new state, actor, reason, and correlation ID as a new entry Given any attempt to modify an existing audit entry When a write is attempted on an existing record Then the system rejects the operation as immutable and no log mutation occurs Given the audit log stream When chain verification is requested Then each entry exposes prev_hash and hash and the verification endpoint returns Pass for unaltered logs
Override Actions With Mandatory Reason Capture
Given a user with Approver role views a flagged invoice When they attempt to override a line-item decision or workflow state Then the UI requires a non-empty reason (minimum 10 characters) and a Reason Tag selection before allowing submission Given an override is submitted When it is saved Then the audit log entry includes approver user ID, role, timestamp, reason text, Reason Tag, affected items, prior decision, and new decision linked to the invoice ID Given an invoice with overrides When generating an export Then the export displays override details with clear before/after values for each affected field
Vendor Communication Logging and Loopback
Given an invoice is flagged and returned to vendor When a notification is sent Then the exact message body, recipient, channel (email/SMS/portal), and attachments are stored as an audit entry and shown on the invoice timeline Given the vendor replies via a supported channel When the reply is received Then the system threads it to the same invoice/job, stores message and attachments with timestamps, and updates status via a new entry without altering past entries Given a corrected invoice is resubmitted When received Then the audit links the new version to the prior submission with version numbers and reason for resubmission
Photo-Timeline and Artifacts Linking
Given an invoice is associated with a job When the invoice detail page loads Then a link to the job’s photo-timeline is displayed with a count of related photos/artifacts and first/last capture timestamps Given a photo has annotations in the timeline When viewed from the invoice context Then annotations, author, and timestamps are visible and the photo is read-only in this context Given an export is generated with photo references included When PDF is produced Then it contains thumbnails with captions and links; CSV contains artifact IDs and URLs; missing artifacts are reported as placeholders with IDs
Audit Log Search and Filter
Given a user searches audit logs When filters are applied (date range, invoice ID, job ID, vendor, decision, Reason Tag, user, channel, export status) Then results are paginated and sortable by timestamp, returning only matching entries Given a search result entry is opened When the entry details load Then all captured fields render within 2 seconds for the 95th percentile on datasets up to 1,000,000 entries Given an invalid filter value is provided When the search is executed Then the system returns a validation error describing the invalid parameter and does not execute the query
PDF/CSV Export for Owner Audit
Given a user selects an invoice and requests a PDF export When the export completes Then the PDF includes invoice metadata, OCR outputs, line-item matches/variances, rule evaluations, state transitions, overrides, vendor communications, and links to photo-timeline, each section timestamped and labeled Given a user requests CSV export When generated Then each row represents an audit entry with columns: timestamp, invoice_id, job_id, entry_type, actor, details_json, prev_hash, hash; multi-line details are JSON-escaped Given an export is requested When processing invoices with up to 500 audit entries Then the export completes within 60 seconds and provides a download link valid for 7 days Given a bulk export of 100 invoices is requested When complete Then a zipped archive is produced with one PDF per invoice and a consolidated CSV, with visible progress status
Access Control and PII Redaction in Audit Exports
Given a user without Owner or Auditor role attempts an export When the action is initiated Then the system denies with 403 and records the attempt in the audit log Given audit entries contain PII (e.g., tenant phone/email) When a user selects Redact PII or lacks PII permission Then the PDF masks PII and the CSV replaces PII with redacted tokens; the export metadata records that redaction was applied Given a redacted export is generated When integrity is verified Then the hash chain is validated against the canonical unredacted log and a signed redaction map is included for verification
Exceptions Queue & Resolution Dashboard
"As a property manager, I want an exceptions dashboard with bulk actions and insights so that I can resolve flagged invoices efficiently and refine our rules over time."
Description

Deliver a unified dashboard for flagged invoices with side-by-side invoice vs. work order views, variance highlights, filters (reason, vendor, property, age, amount), and bulk actions (approve within small variance, request correction, create rule from pattern). Surface SLA aging, auto-approve rate, leakage prevented, and cycle-time metrics to help teams triage faster and continuously improve controls.

Acceptance Criteria
Side-by-side variance view for flagged invoices
Given a user opens a flagged invoice from the Exceptions Queue, When the detail view loads, Then the invoice and related work order display side-by-side with aligned line items and totals. Given mismatches exist, When the view renders, Then variance amounts and percentages are highlighted per line item and in totals with distinct color coding and tooltips. Given the detail view opens, Then it loads in ≤2.0 seconds at P95 for invoices up to 20 line items and attachments totaling ≤10 MB. Given the document has more line items than the visible area, When the user scrolls one panel, Then the corresponding row in the other panel remains visible via row anchoring. Given a field has no OCR value or no work order value, Then the row displays a "missing value" badge and is included in the mismatch tally.
Filter and sort exceptions by reason, vendor, property, age, and amount
Given the Exceptions Queue is loaded, When the user applies any combination of filters (Reason, Vendor, Property, Age range, Amount range), Then the list updates within 1 second P95 and displays only matching items. Given filters are applied, Then active filter chips are shown and persist across navigation within the session until cleared. Given no items match the current filters, Then a zero-state appears with a "Clear filters" control and the item count shows 0. Given the user sorts by Age or Amount, Then results sort ascending/descending correctly and the sort indicator reflects the current sort. Given 5,000 exceptions exist, Then the queue paginates or virtualizes to maintain smooth scrolling and filter updates within 1 second P95.
Bulk actions: approve small variance, request correction, create rule from pattern
Given the user selects multiple exceptions, When "Approve within tolerance" is executed, Then only items with variance ≤ the configured tolerance are approved; others remain unapproved with an inline reason; all approvals are logged with user, timestamp, and variance. Given selected items include mismatches, When "Request correction" is executed, Then each vendor receives a notification with itemized discrepancies and required edits; each invoice state changes to "Awaiting Vendor" and payment is blocked. Given a recurring mismatch pattern is detected across selected items, When the user chooses "Create rule from pattern," Then the user can define conditions and tolerance, preview impact on the last 90 days (count approved/blocked), and confirm; the rule is saved, versioned, and applied prospectively. Given any bulk action completes, Then the queue refreshes and affected counters/metrics update within 5 seconds.
SLA aging and operational metrics visibility
Given exceptions are displayed, Then each item shows time since flag and SLA target; items exceeding SLA are visually escalated and sortable by age. Given a date range and filters, When viewing the dashboard header, Then it shows auto-approve rate (%), leakage prevented ($ and % vs submitted), and median and P90 cycle time from flag to resolution, computed over the filtered set. Given a user action changes item states (approve, request correction), Then the metrics refresh within 5 seconds to reflect the new data. Given the user hovers a metric, Then a tooltip shows the definition and formula used.
Vendor correction loop and re-evaluation
Given an invoice is flagged and "Request correction" is sent, Then the system sends the vendor a notification containing the line-item discrepancies, variance amounts, and a link to resubmit; the invoice is marked "Awaiting Vendor" and blocked from payment. Given the vendor resubmits a corrected invoice, When OCR and line-item matching complete, Then the system re-evaluates against the work order, updates variance highlights, and transitions the status to Approved if within tolerance or back to Exception if not. Given a resubmission occurs, Then all prior and new documents and messages are appended to the invoice timeline with timestamps and actor identity. Given duplicate resubmissions are received, Then the system deduplicates by invoice ID and hash and retains only the latest version while keeping an audit of prior versions.
Permissions and audit trail for exception handling
Given a user without Approver role accesses the dashboard, Then bulk approve and rule creation actions are hidden/disabled and attempting them returns a 403 error. Given any action is taken on an exception (approve, request correction, create rule, edit tolerance), Then an audit log entry records who, what, when, previous value, new value, and affected IDs, and is viewable in the timeline. Given portfolio-based access controls are configured, Then users can see and act only on exceptions for properties they have access to; items outside their scope are not returned by filters. Given audit logs are queried for a specific invoice, Then the system returns results within 2 seconds P95 for up to 200 log entries.

SplitCharge Rules

Automate tenant vs owner responsibility at the line‑item level using lease clauses, issue type, and evidence. Owner portions follow Cap Matrix logic; tenant‑responsible items trigger deposit capture or statement charges. Clear, pre‑communicated splits reduce disputes and shrink the owner’s out‑of‑pocket.

Requirements

Lease Clause Extraction & Responsibility Mapping
"As a property manager, I want FixFlow to extract and map maintenance responsibility clauses from leases so that split decisions reflect the signed agreement without manual lookups."
Description

Extract responsibility-related clauses from uploaded leases using OCR/NLP, normalize them to a structured schema mapped to FixFlow’s issue taxonomy, and allow manual confirmation and exceptions per unit/lease version. Persist clause citations and effective dates, support multi-tenant leases, and expose a confidence score with review queues. The output feeds triage and the SplitCharge rule engine, ensuring decisions reflect the signed agreement and are repeatable and auditable.

Acceptance Criteria
OCR and Clause Extraction from Uploaded Lease
- Given a lease file (PDF, DOCX, JPG/PNG scans) up to 50MB is uploaded, When processing completes, Then 100% of pages are OCRed and parsed without fatal errors and processing time is ≤ 2 minutes for documents ≤ 30 pages. - Given responsibility-related clauses exist (e.g., maintenance, repairs, damages, utilities, appliances, pest, HVAC filters, plumbing clogs, negligence), When extraction runs on the benchmark set, Then recall ≥ 90% and precision ≥ 90% for responsibility-related clauses. - Given clauses are extracted, When results are stored, Then each clause includes original text snippet, section identifier (e.g., §12.B or page+paragraph), page number, and a confidence score in [0,1]. - Given non-English leases in supported languages (EN/ES), When processed, Then language is auto-detected and extraction metrics meet the same thresholds.
Normalization to Schema and Issue Taxonomy Mapping
- Given extracted clauses, When normalization executes, Then each clause is transformed into the schema with fields: responsibility_party {tenant|owner|shared|conditional}, issue_category (FixFlow taxonomy), conditions, cost_share_rule, effective_start, effective_end, citation. - Given a standardized lease test set, When mapping completes, Then ≥ 95% of extracted clauses have a valid issue_category and responsibility_party; 0 orphan categories or invalid enums. - Given conflicting mappings (org default vs building vs unit/lease), When publishing, Then deterministic priority applies: lease version > unit default > building default > org default; conflicts are surfaced with a resolution summary. - Given schema validation, When errors occur, Then publish is blocked and the UI lists actionable errors per clause within 2 seconds.
Manual Review, Confirmation, and Exceptions
- Given clauses with confidence < org threshold (default 0.80), When ingestion completes, Then those clauses appear in a Review Queue with highlighted source text and proposed mapping. - Given a reviewer action (confirm/edit/reject/create new clause), When saved, Then changes are versioned with user, timestamp, reason, and original OCR text preserved. - Given an exception is added for a unit or specific lease version, When published, Then it overrides upstream defaults and is reflected in downstream rule evaluations within 5 minutes. - Given unresolved below-threshold items, When attempting to publish, Then publish is prevented and the count of outstanding items is displayed.
Multi-Tenant and Multi-Version Lease Support
- Given a lease lists multiple tenants, When responsibilities are mapped, Then tenant responsibility defaults to joint-and-several with ability to mark per-tenant exceptions; selections are persisted and auditable. - Given a unit with multiple lease versions and an incident date, When the rule engine requests mappings, Then the clauses effective on the incident date are returned. - Given a new lease version is published, When historical decisions are viewed, Then past incident decisions remain unchanged and reference the clause version used at the time. - Given effective date ranges, When overlapping ranges are detected, Then publish is blocked with guidance to resolve overlaps.
Persistence of Clause Citations and Effective Dates
- Given a lease is published, When data is persisted, Then each clause record includes lease_id, version, citation, page, normalized mapping, effective_start/end, confidence, reviewer_status, and checksum. - Given system backup/restore procedures, When a restore test is executed, Then 100% of published clause records are recoverable and queryable; durability SLO ≥ 99.9% monthly. - Given an export request, When triggered, Then CSV and JSON exports contain clause text, normalized fields, and citations and complete within 30 seconds for up to 5,000 clauses.
Integration with Triage and SplitCharge Rule Engine
- Given a maintenance issue with FixFlow taxonomy tags and a unit with a published lease, When triage runs, Then responsibility and cost share are computed from mappings and the decision includes clause citation(s) and evidence references. - Given identical inputs (issue type, evidence tags, lease version), When rules are re-executed, Then the same responsibility outcome is produced (idempotent). - Given no relevant mapping exists, When a decision is needed, Then fallback applies (Cap Matrix owner default), the case is flagged for review, and no tenant charge is auto-posted. - Given end-to-end processing, When an issue is submitted, Then decision latency is ≤ 3 seconds at P95 for workloads up to 20 concurrent requests.
Evidence-Driven Conditional Clauses
- Given a clause with conditional language (e.g., tenant responsible if damage due to misuse/negligence), When triage provides evidence tags satisfying the condition, Then the mapping resolves to tenant responsibility and records the evidence tag IDs with the decision. - Given conditional clauses, When evidence is missing or contradicts the condition, Then responsibility resolves to owner/shared per clause and the workflow requests additional evidence. - Given a conditional resolution, When logged, Then the audit trail captures condition evaluated, evidence source, clause citation, and resolver identity/time.
Evidence-Driven Triage Inputs
"As a tenant, I want the app to guide me to submit the right evidence so that charges are fair and repairs proceed without back-and-forth."
Description

Collect and validate tenant-provided evidence (annotated photos/video, guided troubleshooting responses, timestamps, meter readings) at intake. Enforce completeness checks, auto-tag indicators of tenant-caused damage versus wear-and-tear, and link artifacts to the request’s photo-timeline. Structure the data for rule evaluation and make it available to approvers and vendors without exposing PII beyond need-to-know.

Acceptance Criteria
Guided Intake Completeness Validation
Given a tenant starts a maintenance request for any issue type, When they reach the Evidence step, Then the Submit button remains disabled until all required fields for that issue type are satisfied Given issue type = water leak or clog, When the tenant proceeds, Then at least 2 photos or 1 video is required and at least 1 guided troubleshooting question must be answered Given issue type = no power or appliance not working, When the tenant proceeds, Then at least 1 photo and completion of the breaker/outlet test flow is required Given meter-dependent issues (water usage spike, gas smell, electric bill spike), When the tenant proceeds, Then a numeric meter reading with units and a timestamp is required Given media is uploaded, When validation runs, Then only jpg,png,heic,mp4 up to 100MB each are accepted and photos must be >=1024x768 and videos >=720p Given the tenant attempts to submit with missing or invalid fields, When server-side validation runs, Then the request is rejected with HTTP 422 and machine-readable error codes for each failed field Given all required inputs are valid, When the tenant submits, Then the request is accepted and a triage_intake_complete flag is set to true
Annotated Media Enforcement
Given a required photo or video is uploaded, When the tenant advances past the Evidence step, Then at least 1 visible annotation (shape or text callout) must be present on at least 1 media item Given an annotation is added, When it is saved, Then the system persists vector coordinates, label text, author, and timestamp linked to the media ID Given annotation text includes obvious PII patterns (email, phone), When the tenant attempts to save, Then the system warns and allows redaction or confirm override with reason Given annotated media is saved, When displayed in the request, Then annotations render correctly on web and mobile and are included in the photo-timeline view
Auto-Tag Indicators of Tenant-Caused vs Wear-and-Tear
Given annotated media and troubleshooting answers are present, When triage processing runs, Then the system evaluates rules/ML and assigns indicator tags with a confidence score per tag Given any tag has confidence >= 0.80, When tags are stored, Then the tag is marked decisive and includes references to the specific evidence items (media_id, annotation_id, question_id) Given tenant edits answers or adds new media, When changes are saved, Then tags are re-evaluated and versioned, preserving an audit trail of prior tags Given no indicators meet decisive threshold, When results are saved, Then the system records no decisive tags and surfaces any hint tags (0.50–0.79) as non-decisive
Artifact Linking to Immutable Photo‑Timeline
Given a request is submitted, When server-side processing completes, Then each media item, annotation, and troubleshooting answer is appended to the request timeline in chronological order with created_at in ISO‑8601 and actor role Given a media item is stored, When hashing runs, Then a SHA‑256 content hash is stored and used to detect replacements; originals remain immutable and any edits create a new version with supersedes_id Given the timeline is viewed by an approver, When filters are applied (media only, answers only, tags), Then the timeline updates without data loss and ordering remains stable Given an approver exports the evidence, When export is requested, Then a ZIP containing media, an index.json (timeline entries, hashes, metadata), and a PDF summary is generated within 60 seconds
Structured Triage Payload for Rule Evaluation
Given a request passes intake validation, When the record is saved, Then the system generates a triage_payload JSON conforming to schema version v1 with a valid $schema reference Given the payload is generated, When schema validation runs, Then the payload validates successfully and includes issue_type, sub_type, meter_readings(value,unit,timestamp), troubleshooting_answers(enum-coded), attachments(meta,hash,dimensions), annotations(labels,coords), and derived_tags Given SplitCharge engine calls the payload API, When GET /requests/{id}/triage-payload is invoked by an authorized service role, Then the API returns 200 within 300ms p95 and excludes binary data, providing signed URLs for media Given payload regeneration is triggered by updates, When new evidence is added, Then the payload version is incremented and previous versions remain retrievable by version ID
Role‑Based Access and PII Minimization for Approvers and Vendors
Given a vendor views a work order linked to a request, When evidence is displayed, Then tenant full name, email, and phone are masked, EXIF GPS is stripped, and only unit address, proxy contact, and evidence are visible Given an approver (owner/PM) views the request, When evidence is displayed, Then tenant first name and masked contact (e.g., +1‑***‑***‑1234) are visible and full contact is available only upon explicit reveal with reason logged Given any external access is granted, When media URLs are issued, Then they are time-bound signed URLs expiring in <=7 days and scoped read-only to the specific artifacts Given evidence is accessed by any role, When the event occurs, Then an access log entry is recorded with actor, role, artifact_id, timestamp, and IP, retrievable in the audit trail
Split Rule Engine with Cap Matrix Application
"As an owner, I want a transparent, rule-based split calculation so that my out-of-pocket aligns with policy and market norms."
Description

Implement a deterministic, explainable rules engine that combines lease mappings, issue classification, evidence signals, property settings, and jurisdictional constraints to decide tenant versus owner responsibility at the line-item level. Apply Cap Matrix logic for owner portions (depreciation by age/usage, per-item caps, frequency windows), compute the resulting split, and produce a human-readable rationale with cited clauses and factors. Support precedence, fallbacks, and admin overrides with change logging.

Acceptance Criteria
Priority Resolution Across Lease, Jurisdiction, Property Rules
Given a line item where lease clause L1, jurisdiction rule J1, and property policy P1 all apply and precedence is Lease > Jurisdiction > Property And no admin override exists When the rule engine evaluates responsibility Then the engine selects L1 as the governing rule for the split And J1 and P1 do not alter the resulting split And re-evaluating with identical inputs returns the same decision_id and split And the output includes the applied precedence order and the winning rule ID and version
Cap Matrix Calculation: Depreciation, Caps, Frequency Window
Given Cap Matrix parameters: linear depreciation 10% per year, owner cap $300 per 12-month window, frequency limit 1 per window And item age = 4 years And repair cost = $500 And prior owner spend in the current window = $0 When the split is calculated Then owner_portion = min(cost * (1 - 0.10 * age_years), remaining_cap) = min(500 * 0.6, 300) = 300 And tenant_portion = 200 And window_consumed increases by 300 for this item And If prior owner spend = $250 in the same window, Then remaining_cap = $50 and owner_portion = $50 and tenant_portion = $450
Evidence-Driven Liability Determination
Given issue classification = "misuse" with confidence = 0.85 And lease clause L2 assigns tenant responsibility for appliance misuse And no contradicting jurisdictional constraint prevents charging the tenant When the engine evaluates responsibility Then tenant_portion = 100% of cost subject to available deposit balance And a deposit_capture intent is created for min(cost, deposit_balance) And the rationale cites L2 and evidence_ref IDs with confidence values And If confidence < 0.80, Then the engine defers to the next applicable rule by precedence and tags the decision with evidence_status = "low_confidence"
Rationale Generation with Citations and Calculations
Given a computed split for a line item When the rationale is generated Then it includes: applied precedence sequence, winning rule ID/version, cited lease clause numbers, jurisdiction references, property setting keys, evidence_ref IDs with timestamps, and Cap Matrix parameters (age, depreciation rate, cap, window, prior_spend) with computed intermediate values And it specifies final owner_portion and tenant_portion amounts And it presents a human-readable narrative under 500 words and a structured field containing the same data And it includes a deterministic decision_id hash derived from inputs and rule versions
Admin Override and Immutable Audit Log
Given a user with role = "Owner Admin" changes owner_portion from 300 to 200 and provides an override_reason When the override is saved Then the system recalculates tenant_portion = cost - owner_portion And writes an immutable audit record with before/after values, override_reason, user_id, timestamp, decision_id, and rule_snapshot And flags the decision as overridden and updates downstream financial intents (voids prior, creates new) with linked references And subsequent auto re-evaluations preserve the override until it is explicitly cleared by an authorized user
Fallbacks for Missing or Conflicting Data
Given item_age is unknown and no lease mapping exists for the issue type And jurisdiction default for classification = "wear_and_tear" is owner 100% And classification confidence >= 0.90 When the engine evaluates the line item Then it applies the jurisdiction default and sets decision_confidence = "fallback" And the rationale lists missing_fields = ["item_age", "lease_mapping"] And If classification confidence < 0.70 or classification is absent, Then the engine returns status = "unable_to_decide" with required_inputs listed and generates no financial intents
Line-Item Isolation and Aggregated Outputs
Given a work order with three line items A, B, and C with distinct rules and costs When the engine processes the work order Then each line item emits a decision with owner_portion, tenant_portion, and rationale And sum(owner_portion, tenant_portion) per line item equals its cost And the owner statement total equals sum of owner_portion across items, respecting each item’s cap and window independently And deposit_capture intents are created per tenant-responsible line item And applying an override to item B does not change decisions for items A or C
Line-Item Split Calculation & Accounting Sync
"As a property manager, I want split amounts to post automatically to ledgers and deposits so that billing is accurate and I don’t have to reconcile manually."
Description

Calculate owner and tenant amounts for each estimate/invoice line, allocate taxes/fees proportionally, and aggregate totals. Automatically trigger tenant deposit captures or ledger charges for tenant-responsible items and create owner payables for owner portions. Synchronize with external accounting systems via API, handle updates from change orders, and reconcile partial payments, cancellations, or refunds to keep books accurate.

Acceptance Criteria
Line Split Determination per Lease and Issue Type
Given a line item with subtotal > 0, an associated lease, issue_type, and evidence tags When SplitCharge rules are evaluated Then the engine applies precedence (lease clause > property policy > issue_type default > fallback) And calculates tenant_amount and owner_amount such that tenant_amount + owner_amount = line_subtotal (± $0.00) And persists split_reason_code and rule_id used on the line And sets line.split_status = "Calculated" Given no matching rule or conflicting evidence When evaluation runs Then line.split_status = "Needs Review" And no tenant charges, deposit captures, or owner payables are created
Proportional Allocation of Taxes and Fees
Given an approved estimate/invoice with invoice_subtotal = sum(line_subtotals) and invoice_tax and invoice_fees at the document level When allocations are computed Then each payer’s share per line is allocated proportionally: payer_alloc = round_half_even(doc_amount * payer_line_subtotal / invoice_subtotal, 2) And sums of all allocated taxes equal invoice_tax and allocated fees equal invoice_fees, with any 0.01 remainder adjusted to the payer line with the largest fractional remainder And each allocation record stores basis_amount, allocation_ratio, and rounding_adjustment
Aggregate Totals by Payer and Grand Total
Given all line-level splits and allocated taxes/fees exist When totals are aggregated Then owner_total_due = sum(owner_amount + owner_tax + owner_fees across all lines) And tenant_total_due = sum(tenant_amount + tenant_tax + tenant_fees across all lines) And owner_total_due + tenant_total_due = document_grand_total (± $0.00) And totals are stored per currency with 2-decimal rounding and exposed via API and UI
Tenant Deposit Capture and Ledger Charge Trigger
Given tenant_total_due > 0 and document status = Approved When tenant collection is triggered Then if tenant_deposit_available >= tenant_total_due, the system captures tenant_total_due from deposit and records a receipt with method = "Deposit Capture" And if tenant_deposit_available < tenant_total_due, the system captures the available amount and creates a tenant ledger charge for the remainder And all collection operations use idempotency_key = document_id + version and do not create duplicates on retry And on full success, tenant_collection_status = "Collected"; on partial success, "Partially Collected"; on failure, "Pending Collection" with error_code and no duplicate captures/charges
Owner Payable Creation with Cap Matrix
Given owner_total_due > 0 and Cap Matrix rules active for the property/period When owner portion is posted Then the system computes cap_remaining for applicable categories and period And creates an owner payable for min(owner_total_due, cap_remaining) in the external accounting system with due_date per configured terms And if owner_total_due > cap_remaining, the overage is reallocated per policy (e.g., tenant responsibility or separate owner over-cap code) and reflected in recalculated totals And payable records include line-level allocation details and are idempotent on retries
External Accounting Sync with Idempotency
Given a create/update/cancel/refund event for a document or related payable/charge When sync runs Then the system maps entities to the external accounting API using stable external_ids and sends POST/PUT/PATCH as appropriate with Idempotency-Key = external_id And on HTTP 200/201/204, sync_status = "Synced" with external_reference stored And on HTTP 409 (duplicate), the system fetches and links existing record and marks as Synced And on 5xx/429, the system retries up to 3 times with exponential backoff; on continued failure, sync_status = "Retrying" And on 4xx validation errors, sync_status = "Sync Failed" with error_code/message persisted and no duplicate records created
Change Orders and Reconciliation of Partial Payments, Cancellations, and Refunds
Given a change order modifies line_subtotals, rules, or taxes on an approved or partially paid document When the change order is applied Then splits, allocations, and aggregates are recalculated and deltas are computed And if tenant or owner payments exist, the system creates adjustment entries (credits/debits) to reconcile to the new balances without losing payment history And cancellations fully reverse open payables/charges and set balances to $0.00 And refunds generate refund entries linked to original payments and are pushed to external accounting; local and external balances match post-refund And all deltas and reversals sync idempotently; an audit log stores previous vs new values with user/time stamps
Pre-Decision Transparency & Consent
"As a tenant, I want to see how charges were determined and approve them quickly so that there are no surprises on my statement."
Description

Before dispatch or spend, present tenants and owners with a clear, itemized split showing amounts, rationale, and evidence thumbnails. Enable one-tap approvals, time-boxed auto-approval thresholds, and messaging for questions. Record acceptance with identity, timestamp, and the exact decision snapshot to reduce downstream disputes and provide proof of consent.

Acceptance Criteria
Pre-Dispatch Itemized Split Display
Given a maintenance request with one or more line items and a calculated SplitCharge breakdown And the user is an authenticated tenant or owner invited to approve When the user opens the approval view before any vendor is dispatched or funds are committed Then the view displays for each line item: payer designation, amount with currency, rationale citing rule/lease clause identifier, and evidence thumbnails if present And the view displays subtotals per party and a grand total And dispatch and spending actions remain disabled until required approvals or auto-approvals are recorded for the request
One-Tap Approval by Tenant and Owner
Given the approval view is loaded and the user's identity is verified When the user taps "Approve All" once Then the system records consent for all line items requiring that user's approval and confirms with a success state within 2 seconds And if per-line approval is enabled, when the user taps "Approve" on a line item once, record consent for that item only And the request becomes eligible for dispatch only when all required parties' approvals (or auto-approvals) are present for all dispatch-blocking items
Time-Boxed Auto-Approval Thresholds
Given auto-approval is enabled with a configurable timer (e.g., N hours) and a per-party amount cap And the request is pending approval from a party When the timer elapses without a response Then the system auto-approves only the items for that party whose amounts do not exceed the configured cap And the system notifies both parties of the auto-approval event and updates the audit log And items exceeding the cap remain pending and continue to block dispatch
Contextual Messaging in Approval Flow
Given the approval view is open When a user opens the Messages panel Then the user can send a message and attach up to 5 images or files And messages are threaded to the approval request and visible to both parties with timestamps and sender identity And sending or receiving messages does not change approval status
Consent Record: Identity, Timestamp, Decision Snapshot
Given a user approves (or the system auto-approves) any items When consent is recorded Then the system stores: approver identity (user ID and role), method (tap/auto), ISO 8601 UTC timestamp, IP address, and device type if available And the system stores the exact decision snapshot including line items, payer, amounts, rationale references, and evidence thumbnail references as of approval time And the consent record is immutable, retrievable via UI and API, and verifiable by a SHA-256 hash
Re-Consent on Material Changes
Given any approved or pending item changes in payer, rationale reference, or amount by more than the configured delta (default $0 or 0%) When such a change is saved before dispatch Then prior consent for the changed items is revoked And the system generates a new decision snapshot, notifies impacted parties, and requires re-approval for changed items And unchanged items retain their approval status
Decision Receipt and Export
Given approvals (or auto-approvals) are complete for dispatch-blocking items When the user views the receipt Then the system provides a downloadable PDF and JSON containing: participants, timestamps, decision snapshot, approval method(s), and audit hash And the receipt can be shared via link with an expiring access token and is accessible from the request timeline And export is available via API endpoint with role-based access control
Dispute Handling & Auditable Rationale
"As a small property manager, I want a structured dispute process with a clear audit trail so that I can resolve conflicts quickly and defensibly."
Description

Allow either party to dispute specific line items, submit comments and additional evidence, and route for manager review with SLA timers. Place financial holds when required, re-evaluate rules upon new evidence, and capture final decisions with justifications. Maintain an immutable audit trail linking decisions to rule versions, lease excerpts, and artifacts to support chargebacks and regulatory inquiries.

Acceptance Criteria
Party submits line-item dispute with evidence
Given a maintenance order has one or more charge-split line items and is in a disputable state And the user is a Tenant or Owner on the lease When the user selects a specific line item and initiates a dispute Then the system requires a dispute reason (minimum 10 characters, maximum 2000) And allows attaching up to 10 artifacts (images/video/pdf) totaling ≤ 100 MB with capture timestamps And assigns a unique Dispute ID and sets the line item dispute status to "Under Review" And starts an SLA response timer of 48 business hours for Manager review And places a financial hold on charges related to the disputed amount without posting to the ledger And notifies the Manager via in-app and email within 5 minutes And records the action in the immutable audit trail with user ID, role, IP, and timestamp
Manager issues final decision with justification
Given a line item dispute is "Under Review" And the acting user has Manager role When the Manager opens the dispute Then the system displays the applied rule result, rule version ID, relevant lease clause excerpt, and submitted artifacts When the Manager issues a final decision of Approve Tenant, Approve Owner, or Adjust Split Then a justification (minimum 20 characters) is required And the decision is captured with timestamp, manager ID, linked rule version ID, and lease clause reference And the line item split and payable amounts are updated accordingly And holds are released or captured to match the decision and ledger entries are posted with the Dispute ID as reference And the dispute status changes to "Closed" And all parties are notified with the decision and rationale within 5 minutes And the dispute becomes read-only for all users
Rule re-evaluation on new evidence
Given a line item dispute is "Under Review" And new evidence is uploaded by either party When the upload completes Then the rules engine re-evaluates the line item and records the rule version used for the suggestion And the system produces a suggested split change with a diff from the current amounts And the Manager is notified of the suggested change within 5 minutes And no financial changes occur until the Manager confirms And the re-evaluation event and artifacts are appended to the audit trail
Immutable audit trail export for disputed line item
Given any dispute lifecycle event has occurred on a line item When an authorized user requests the audit trail export for that line item Then the export contains a chronological log including timestamps (UTC), actors, roles, IPs, actions, rule version IDs, lease clause excerpts, decisions, financial holds/releases, notifications, and artifact checksums And the export is available in PDF and JSON within 30 seconds And each log entry includes a SHA-256 hash and previous-hash to form a tamper-evident chain And attempting to edit or delete any prior audit entry is blocked with HTTP 403 and a security event is logged And the export includes the chain root hash to enable third-party verification
SLA enforcement and escalation on disputes
Given SLA thresholds are configured as Acknowledge within 4 business hours and Decision within 48 business hours When a dispute is created Then the system schedules timers for both thresholds and displays countdowns to the Manager And sends reminder notifications at T-24h and T-1h before the Decision threshold When a threshold is breached Then the dispute is flagged "SLA Breached" And an escalation notification is sent to the designated Supervisor group immediately And the breach event is recorded in the audit trail And timers continue until a decision is recorded
Financial holds and ledger updates on dispute outcomes
Given a line item has an initial rule-based split and a dispute is opened When the dispute is opened Then the system places a hold on tenant deposit or payment method up to the tenant-responsible disputed amount and pauses owner payout for the owner-responsible disputed amount, allowing partial holds to the nearest cent And no funds are moved while status is "Under Review" except holds When a final decision is recorded Then the system releases or captures held amounts to align with the decision and posts balanced ledger entries with references to Dispute ID and rule version ID And owner charges respect Cap Matrix limits, with any overage marked non-billable to the owner And idempotency keys prevent duplicate captures on retries And a receipt is issued to charged parties and a hold-release notice to refunded parties within 5 minutes And the financial outcome is visible on the line item with before/after amounts and timestamps
Compliance Profiles & Legal Overrides
"As an owner, I want the system to prevent non-compliant tenant charges in my jurisdiction so that I avoid legal risk and fines."
Description

Provide location-based compliance profiles that encode prohibited charge types, tenant protections, and notification requirements. Auto-select profiles by property address, warn or block non-compliant charges, and require justification when admin overrides are permitted. Offer a lightweight update channel for regulatory changes and apply them prospectively with version control.

Acceptance Criteria
Auto-Select Compliance Profile by Address
Given a property with a valid address and network connectivity When the address is saved or the charge creation screen loads Then the system auto-selects the most specific applicable compliance profile within 2 seconds (city > county > state > federal) And displays the selected profile name and version to the user And logs the selection with property id, profile id, version, resolver, and timestamp Given an address cannot be geocoded or maps ambiguously When the user saves the address Then the system requires manual profile selection from a filtered list And blocks charge creation until a profile is set And logs the fallback reason and user id Given a property has an assigned profile When any compliance validation runs Then that profile is consistently used for evaluation until changed
Block and Warn on Non-Compliant Charges
Given the active profile marks a charge type as Prohibited When an admin attempts to add or finalize that line item Then the system blocks save/finalize and shows an error citing rule id and profile version And no charge record is created or posted Given the profile marks a charge type as Allowed with Warning When the admin adds the line item Then a warning modal shows the rule summary and requires explicit confirmation before proceeding And the confirmation event is logged with user id and timestamp Given a rule requires conditional evidence (e.g., photo, timestamp) When evidence is missing Then the system blocks finalization and highlights required fields
Admin Override with Required Justification
Given a rule in the active profile is marked Overridable And the user has Compliance Override permission When the user attempts to bypass a block Then the system requires selecting a reason code, entering a justification of at least 20 characters, and attaching at least one evidence file And records user id, timestamp, rule id, profile version, reason code, justification hash, and attachment ids And allows the line item to proceed Given a rule is Not Overridable When the user attempts to override Then no override control is available and the block remains enforced
Enforce Tenant Notification Requirements
Given the profile requires pre-notice of N hours for a specific charge category When a matching charge is created Then the system generates the correct notice template with case fields And prevents finalization until the notice is sent and the earliest post date is >= now + N hours Given the profile requires post-notice within M hours When the charge is finalized Then the system automatically sends the notice within 15 minutes And flags the charge as non-compliant if delivery proof is not recorded within M hours Given the charge is edited after a notice was generated When an edit changes notice-relevant fields Then the system prompts to re-send or update the notice and re-validates compliance
Regulatory Updates Applied Prospectively with Version Control
Given a new profile version V+1 with effective date E exists When the current time is before E Then existing validations use version V and admins can preview diffs and schedule adoption for E When the current time is on or after E Then new charges validate against V+1 And previously posted charges and closed cases remain linked to V and are not revalidated Given an open draft charge created before E When it is finalized after E Then validation applies V+1 and the charge stores the applied profile version
Immutable Audit Trail of Compliance Decisions
Given any compliance evaluation occurs (allow, warn, block, override) When viewing the charge history Then the audit log shows profile id and version, evaluated rule ids with outcomes, user id, and UTC timestamps And includes any justification text and attachments for overrides And is exportable via API and CSV Given an admin attempts to edit or delete an audit entry When saving the change Then the system denies the modification and logs the attempted edit with user id and timestamp
Graceful Degradation and Manual Profile Selection
Given the compliance profile service is unavailable When a user opens the charge creation screen Then the system displays an outage banner And allows manual selection from the last-synced profile catalog (synced within the past 24 hours) And requires revalidation against the live service before finalization Given no cached catalog newer than 24 hours exists during an outage When the user attempts to create a new charge Then the system blocks charge creation and provides a retry control and status page link

SafeStart Checks

Built‑in safety gates confirm power, gas, and water shutoffs, surface hazard warnings, and lock steps behind simple confirmations before any action. Tenants get clear, confidence‑building prompts that reduce risk; owners avoid DIY damage and liability while still enabling quick self‑resolves.

Requirements

Utility Shutoff Confirmation
"As a tenant, I want clear prompts to safely shut off utilities before troubleshooting so that I can prevent damage and avoid personal risk."
Description

Guided, issue-specific prompts require tenants to confirm power, gas, and/or water shutoffs before proceeding. The flow offers clear, visual instructions (e.g., breaker OFF position, quarter‑turn gas valve, main water shutoff) with alternative paths if the tenant cannot locate or operate a control. Confirmations are timestamped, device-captured, and stored to the case, gating subsequent troubleshooting and dispatch steps. Content is dynamically selected based on triage inputs (appliance, location, suspected hazard) and supports quick self-resolve without compromising safety.

Acceptance Criteria
Power Shutoff Confirmation — Electric Appliance in Kitchen
Given triage selects an electric appliance in the kitchen and no hazard override is present When the safety gate loads Then the UI displays power shutoff instructions with at least one labeled image of the breaker OFF position and a 3-step checklist Given the instructions are displayed When the tenant taps "Power is OFF" and completes a secondary verification to test the appliance is unresponsive Then the system enables "Continue" and records the confirmation Given power shutoff is not confirmed When the tenant attempts to proceed Then the "Continue" button remains disabled and an inline message explains that power must be confirmed for safety Given the tenant taps "I can't find the breaker" When selected Then the flow routes to the alternative path without enabling "Continue"
Gas Shutoff Confirmation — Suspected Gas Leak
Given triage indicates gas smell or a gas appliance issue When the safety gate loads Then a hazard banner appears and gas shutoff instructions with a quarter-turn valve diagram are shown Given the tenant reports strong odor or hissing When they proceed Then the system presents an evacuation guidance modal and disables troubleshooting, allowing only "Call Gas Utility/Emergency" and "Cannot shut off" options Given the tenant confirms gas is OFF When confirmation is submitted Then the system requires a secondary verification (e.g., verify no flame/ignition) and only then enables "Continue" Given the tenant cannot operate the valve When they select "Cannot shut off" Then the system flags the case as high priority and blocks self-troubleshooting
Water Main Shutoff Confirmation — Active Leak in Bathroom
Given triage indicates an active leak in the bathroom When the safety gate loads Then the UI displays main or fixture-level water shutoff instructions with at least one labeled image and a 3-step checklist Given the tenant confirms water is OFF When confirmation is recorded Then the flow asks whether the leak has stopped and requires a Yes/No response before enabling "Continue" Given water shutoff is not confirmed When the tenant tries to schedule a vendor Then dispatch options remain disabled with an explanatory message Given the tenant selects valve stuck or cannot find valve When selected Then the alternative path is invoked and vendor triage collects damage-mitigation steps
Alternative Path — Control Not Found or Inoperable
Given the tenant selects cannot find or cannot operate for power, gas, or water When the alternative path starts Then the system displays hazard-specific mitigation tips and prompts for a photo of the control area (skippable if unsafe) Given the tenant submits the alternative path When submission completes Then the system records the reason, timestamps it, attaches any photo, marks the safety gate as "Bypassed with Mitigation," and enables vendor dispatch with high priority if gas is involved Given the tenant attempts to return to normal troubleshooting When the safety precondition is unmet Then troubleshooting steps remain locked until shutoff is confirmed or vendor dispatch is scheduled
Gating Enforcement — No Bypass of Safety Steps
Given a case with an active safety gate When the tenant refreshes, navigates back, or opens a deep link to later steps Then the app redirects to the safety gate and prevents access to troubleshooting or dispatch Given a safety gate was completed When the tenant re-enters the flow within 24 hours Then the completed state persists and later steps remain accessible Given triage inputs change to a different utility risk When the case is updated Then prior safety confirmations that no longer apply are invalidated and the relevant new safety gate is required before proceeding
Audit Trail — Timestamped, Device-Captured Confirmation
Given a tenant completes a utility shutoff confirmation When the confirmation is saved Then the case stores: UTC timestamp to the second, tenant ID, utility type (power/gas/water), step version ID, and device metadata (device type and OS) Given a confirmation is stored When a case viewer opens the audit log Then the confirmation record is visible, read-only, and includes the originating IP region and the client time offset Given an alternative path submission occurs When saved Then the case stores the reason and any uploaded photos with timestamps and links to the step that required the safety gate
Dynamic Content Selection — Based on Triage Inputs
Given triage inputs for appliance type, location, and suspected hazard When the safety gate is rendered Then the system selects the matching content pack: power for electric-only appliances, gas for gas appliances or gas-smell hazard, and water for leaks/overflows Given multiple utilities are relevant (e.g., gas range with electric ignition) When both risks are detected Then the system displays both gates in a safe order (gas first, then power) and requires completion of each Given triage inputs change mid-flow When the tenant edits appliance or hazard Then the displayed safety gate updates to the new content pack and any obsolete confirmations are cleared
Contextual Hazard Prompts
"As a tenant, I want context-aware safety warnings during intake so that I know what immediate precautions to take for my situation."
Description

Dynamic safety warnings surface automatically based on reported symptoms, location, and captured media (e.g., gas smell, water near outlets, sparking sounds). The system displays concise, plain‑language guidance and visual cues (evacuate, avoid ignition sources, keep area dry), and links to emergency actions when severity thresholds are met. Copy is localized and accessibility‑friendly, with emphasis on confidence‑building language that reduces panic and DIY errors.

Acceptance Criteria
Gas Smell Emergency Prompt Trigger
Given a tenant selects the symptom “Gas smell” or enters text containing gas-leak keywords (e.g., “gas smell,” “rotten eggs,” “propane”), When the triage flow begins or the symptom is saved, Then a critical hazard banner is displayed within 2 seconds showing plain‑language guidance: “Evacuate now,” “Avoid ignition sources,” “Do not use switches,” and a one‑tap “Call emergency services” action tied to the property’s configured emergency number, And visual cues include a red banner, hazard icon, and vibration feedback (mobile), And the flow disables self‑resolve and scheduling actions until the tenant confirms evacuation via a single confirmation step, And the system logs banner display, guidance version, trigger source, locale, and confirmation outcome with timestamp.
Water Near Outlet Detected From Photo
Given the tenant uploads a photo and the vision model detects an electrical outlet within 0.5 m of visible water with confidence ≥ 0.85, When analysis completes, Then a high‑severity water/electric hazard prompt appears within 3 seconds with guidance: “Keep area dry,” “Shut off power at breaker,” and “Do not touch outlets,” And a how‑to link for shutting off power is shown, And any troubleshooting steps involving powered devices are hidden or disabled, And the prompt requires a single acknowledgment before proceeding, And the detection, confidence score, and prompt acknowledgment are recorded in the audit log.
Sparking or Buzzing Electrical Symptom
Given the tenant selects the symptom “Sparking/Buzzing from outlet or fixture,” When the selection is saved, Then a high‑severity electrical hazard prompt displays within 2 seconds with visual cues (amber banner, hazard icon) and guidance: “Turn off the breaker for the affected area,” “Keep people away,” “Do not attempt repairs,” And a one‑tap link to breaker‑box instructions is provided, And self‑resolve steps unrelated to power are allowed only after acknowledgment; all power‑related steps remain disabled, And the event is logged with symptom ID, prompt ID, and acknowledgment timestamp.
Localization and Accessibility of Hazard Prompts
Given the tenant’s preferred language is set (e.g., es-419), When any hazard prompt is displayed, Then 100% of visible copy (titles, body, buttons, links) appears in that language with no mixed‑language strings, And screen readers announce the prompt via ARIA live region with descriptive labels for icons, And color contrast for text and key icons meets WCAG AA (≥ 4.5:1), And all interactive elements are keyboard‑navigable with visible focus states, And the reading level of the body text is ≤ grade 8 per automated readability check, And if a translation is missing, the system falls back to en-US and records a missing‑key log entry.
Severity Threshold Escalation to Emergency Actions
Given the hazard scoring engine computes a severity score for the current intake, When the score ≥ 0.80 or a critical trigger (e.g., gas smell) is present, Then an emergency banner is pinned at the top of the screen showing immediate actions and a one‑tap call to the property’s emergency number, And self‑resolve paths are hidden; only evacuation and emergency actions remain until the score drops below threshold, And the owner/manager receives an immediate alert with incident ID and severity via configured channel, And the system records the score, triggers, and escalation actions in the audit trail.
Audit Trail of Hazard Prompts and Tenant Confirmations
Given any hazard prompt is displayed, When the tenant views or interacts with the prompt, Then the system captures an immutable log entry with timestamp (UTC), user ID (hashed), incident ID, trigger source (symptom/media/location), prompt template version, locale, and confirmation outcome, And the entry is appended to the incident’s photo‑timeline as a labeled event, And logs are retained for at least 24 months and are exportable (CSV/JSON) to owners on request within 60 seconds for incidents < 1,000 events, And tamper attempts are detected and flagged if a log checksum mismatch occurs.
Gated Workflow Locks
"As an owner, I want safety checks to lock risky actions until confirmations are complete so that I reduce liability and prevent avoidable damage."
Description

Safety gates hard‑block progression to troubleshooting steps, appointment booking, or vendor dispatch until required confirmations (e.g., utility shutoff, hazard acknowledgment) are satisfied. Gates are enforced by a state machine with role‑based overrides for owners/property managers and automated re‑checks if conditions change. Clear inline reasons explain why the next action is locked and what the user must do to unlock it, ensuring consistent risk mitigation and liability control.

Acceptance Criteria
Tenant Leak Intake — Water Shutoff Gate Before Troubleshooting
Given a Tenant user starts a Water Leak report and has not confirmed Main water supply is shut off When they attempt to proceed to the first troubleshooting step Then the Continue action is disabled, booking and dispatch actions are unavailable, and a lock reason banner is displayed stating Confirm water shutoff to proceed. Given the Tenant opens the Safety Checks When they check I have shut off the main water and tap Confirm Then the system time-stamps the confirmation, records user ID, and transitions the case state from Locked.Utilities to Unlocked.Step1, enabling Continue.
Gas Smell Report — Dual Gate: Gas Shutoff and Hazard Acknowledgment
Given a Tenant reports Smell of gas and required confirmations Gas supply shut off and Hazard acknowledgment are incomplete When they attempt to request vendor dispatch or book an appointment Then the request is blocked with a lock banner listing both incomplete items and a Complete safety checks CTA. Given the user role is Tenant When they attempt to access any override endpoint or action Then the system returns 403 and no state transition occurs; override controls are not visible in the UI. Given both confirmations are completed When the Tenant retries dispatch Then dispatch submission succeeds and the vendor ticket includes gasShutoffConfirmed=true and hazardAcknowledged=true with timestamps.
Inline Lock Reason and Unlock Guidance — Clarity and Accessibility
Given any workflow is locked When the lock banner is shown Then it displays the blocked action label, a checklist of missing confirmations, and a single-button CTA Complete safety checks that opens the checklist and scrolls to the first incomplete item. Given a user activates a blocked control via keyboard or tap When focus management runs Then focus moves to the lock banner, the banner has role=alert and aria-live=assertive, and all content meets WCAG 2.2 AA contrast and is screen-reader accessible.
Owner/PM Override — Justification, E‑Sign, and Audit
Given a user with role Owner or Property Manager and permission OverrideGates When they choose Override and proceed Then a modal requires selecting an override reason from a predefined list, entering a minimum 20-character justification, and confirming an e-signature checkbox before Proceed is enabled. Given the authorized user confirms the override When the override is submitted Then the state transitions to Bypassed.RiskAccepted, downstream actions unlock, and an immutable audit record is created including caseId, userId, role, reason, note, timestamp, and IP and appears in the case timeline. Given a user without permission attempts an override When they trigger the action Then the system denies with 403 and no state change occurs.
Automated Re-check and Relock on Condition Change
Given gates are satisfied and the workflow is in Unlocked.StepN When any gating answer is changed to a non-passing value or an upstream hazard flag is set by any user Then the state machine immediately transitions to Locked.[Cause], disables Continue/booking/dispatch, and posts a timeline event Relocked due to condition change. Given the case is open in multiple sessions When a relock occurs in another session Then all active sessions reflect the locked state within 5 seconds via real-time update or on next request, and further progression is blocked.
State Machine Enforcement and URL/API Guardrails
Given a step is locked by the state machine When a user attempts to navigate directly to a future step via URL or deep link Then the server redirects to the last unlocked step and returns lockCode and lockReasons; the UI displays the lock banner. Given any API call attempts to create a booking or dispatch while locked When the server processes the request Then it responds 422 with errorCode=GATE_LOCKED and includes lockReasons[]; no booking/dispatch record is created. Given the user refreshes or starts a new session When the workflow loads Then the locked/unlocked state is sourced from server state and persists across sessions; client-side manipulation cannot bypass gates.
Evidence Capture & Verification
"As a property manager, I want visual proof of safety steps so that I can verify conditions remotely and make faster, confident decisions."
Description

The flow requests photo/video evidence of shutoff states (breaker panel, valve positions, appliance switches) and annotates images for clarity. Basic on-device/computable checks validate likely OFF states (e.g., breaker toggle orientation, valve handle alignment) and flag mismatches for manual confirmation. Media is compressed, time/location stamped, attached to the maintenance record, and available for later review, strengthening auditability and enabling faster vendor triage.

Acceptance Criteria
Electrical Shutoff Evidence Capture (Breaker Panel)
Given a tenant is in the SafeStart electrical flow for a reported power issue When the tenant captures a photo of the breaker panel after confirming power is OFF Then the app enforces minimum image resolution of 1920x1080 and rejects captures with blur score > threshold And the app provides an on-screen framing guide before capture and a retake prompt if quality checks fail And the app runs on-device OFF-orientation detection on visible breaker toggles with confidence >= 0.70 And if the user indicated OFF but detection confidence < 0.70 or detects ON, the app displays a mismatch dialog requiring manual override with a reason (>= 10 characters) And upon successful verification or manual override, the app annotates the image with arrows/labels indicating OFF/ON predictions and saves both original and annotated copies And the image is compressed to <= 1.5 MB while retaining long-edge >= 1080 px And the media is time-stamped (ISO 8601 UTC) and, if permitted, geo-stamped (accuracy <= 50 m) and attached to the maintenance record step "Electrical SafeStart"
Gas Valve Shutoff Verification
Given a tenant is in the SafeStart gas flow for a suspected gas issue When the tenant captures a photo of the appliance or supply shutoff valve after confirming gas is OFF Then the app detects quarter-turn valve handle orientation perpendicular to the pipe within ±15° and reports confidence And if confidence >= 0.70, the OFF state is auto-verified; otherwise a mismatch prompt requires manual override with a reason (>= 10 characters) And the app overlays annotations highlighting the valve and measured angle with OFF/ON labels on the annotated copy while preserving the original And the image is compressed to <= 1.5 MB, time-stamped (ISO 8601 UTC), geo-stamped if permitted (accuracy <= 50 m), and attached to the maintenance record
Water Supply Shutoff Validation
Given a tenant is in the SafeStart water flow for a leak or fixture issue When the tenant selects "Quarter-turn valve" and captures a photo of the valve Then the app detects handle orientation perpendicular to the pipe within ±15° with confidence >= 0.70; otherwise it prompts a mismatch manual override with reason (>= 10 characters) And the photo is annotated to indicate valve and detected orientation, with original preserved and annotated copy stored When the tenant selects "Wheel valve" and captures a photo of the valve Then the app skips on-device OFF detection, requires tenant manual confirmation with reason (>= 10 characters), and tags the step as "Manual verification required" And all media are compressed to <= 1.5 MB, time-stamped (ISO 8601 UTC), geo-stamped if permitted (accuracy <= 50 m), and attached to the maintenance record
Media Compression, Upload, and Offline Queueing
Given the tenant has captured required photos/videos during SafeStart When the app prepares media for upload Then images are compressed to <= 1.5 MB with long-edge >= 1080 px; videos are limited to <= 15 s, <= 720p, and <= 10 MB (~<= 1.5 Mbps) And uploads use chunked transfer with up to 5 retries using exponential backoff (2s, 4s, 8s, 16s, 32s) and resume on interruption And if offline, media are stored encrypted locally, marked as Queued, and auto-uploaded within 72 hours of next connectivity And the tenant sees real-time status (Queued/Uploading/Uploaded) and error messages with retry option And upon successful upload, the server acknowledges and links each media item to the correct maintenance record step
Annotation Review and Original Preservation
Given auto-generated annotations are available for a captured image When the tenant reviews annotations before submission Then the tenant can add, move, or delete up to 5 markers and edit text labels And saving annotations creates a separate annotated copy while preserving the immutable original And the system logs who edited annotations and when (ISO 8601 UTC) in the record timeline And once the SafeStart step is submitted to vendor triage, further annotation edits are locked for all roles
Audit Trail and Role-Based Access
Given media have been attached to a maintenance record via SafeStart When any authorized user (tenant, owner, vendor) views the record Then both original and annotated media, timestamps, and (if available) location are visible in a read-only timeline And each media item has a stored SHA-256 checksum and file metadata (type, size, resolution/duration) to support auditability And permissions enforce that only the tenant can replace media before submission; after submission, all roles have view-only access; admins can unlock with explicit action logged And all events (capture, upload, verification result, manual override, submission) are logged with actor, timestamp (ISO 8601 UTC), and outcome
Mismatch Handling and Escalation
Given a SafeStart on-device check detects an OFF-state mismatch or low confidence (< 0.70) When the tenant cannot provide confirming media or declines manual override Then the app blocks self-resolve actions for that issue type and recommends vendor dispatch And for gas/electrical hazards, the app displays a prominent safety warning and provides an emergency contact option And the mismatch flag and reason are recorded on the maintenance record to prioritize vendor triage
Emergency Escalation & Overrides
"As a tenant, I want an immediate escalation option when something seems dangerous so that I can get urgent help without guessing what to do next."
Description

When high‑risk cues are detected or the tenant cannot complete a required shutoff, the system triggers an escalation path: one‑tap emergency dialing guidance, owner notification, priority vendor dispatch with safety flags (e.g., do not energize), and suppression of self‑resolve options. Severity rules are configurable, and overrides are logged with reason codes to preserve an auditable chain of decisions.

Acceptance Criteria
Gas Leak Detected: Auto Escalation & Self‑Resolve Suppression
Given a tenant is completing SafeStart Checks for an active incident And the system detects a gas‑leak cue that matches a Critical severity rule When the tenant confirms the cue Then the incident state is set to "Emergency Escalated" within 1 second And all self‑resolve actions are hidden and disabled within 2 seconds And an emergency dialing guidance screen is displayed with 911 and configured local emergency numbers And the guidance screen prevents navigation back to self‑resolve steps And an event log entry is created with timestamp, incidentId, ruleId, hazardType="Gas", severity="Critical"
Required Shutoff Not Completed: Escalation and Guidance
Given a required shutoff step (power/gas/water) is presented during SafeStart Checks And the tenant selects "I cannot complete this shutoff" When the tenant confirms their selection twice (prompt + confirm) Then the system escalates the incident within 3 seconds And displays emergency dialing guidance with step‑by‑step safety instructions applicable to the shutoff type And records reasonCode="Shutoff_Not_Completed" with shutoffType and userId in the audit log And self‑resolve options remain suppressed for this incident
Priority Vendor Dispatch with Safety Flags
Given an incident has been escalated When vendor dispatch is triggered by escalation rules Then a vendor job is created with priority="Emergency" within 10 seconds And hazard safety flags appropriate to the incident (e.g., Do_Not_Energize, Do_Not_Relight, Do_Not_Repressurize) are attached And the job payload includes propertyId, unit, accessNotes, hazardType, flags[], and incidentId And the dispatch is sent to the configured emergency vendor pool And the vendor‑facing view surfaces the safety flags prominently on first screen
Owner Notification on Emergency Escalation
Given owner notification channels are configured When an incident is escalated Then the owner is notified via all enabled channels (push/SMS/email) within 60 seconds And the message includes incidentId, property/unit, hazardType, escalationTime, safetyFlags, and a link to the incident record And the notification is marked high priority And a delivery status (queued/sent/failed) is recorded per channel
Configurable Severity Rules Drive Escalation Behavior
Given an admin updates the severity rules to set Water_Leak volume above the configured threshold as Critical When a tenant reports a water leak above that threshold Then the system escalates the incident and suppresses self‑resolve according to the new rule And the applied ruleId and ruleVersion are recorded in the incident And if the rule is later adjusted to Non‑Critical and the same cue is reported, self‑resolve remains available and no escalation occurs
Manual Override with Reason Codes and Audit Trail
Given an incident is escalated and self‑resolve is suppressed And an authorized role (Owner, Support) views the incident When the user performs an override action (e.g., re‑enable self‑resolve or cancel escalation) Then the system requires selection of a reason code from a managed list and an optional comment And records an immutable audit entry with timestamp, actorId, role, action, previousState, newState, reasonCode, and comment And the override takes effect immediately and is visible to the tenant within 5 seconds And unauthorized roles cannot access override actions
Post‑Escalation Persistence and Clearance Controls
Given an incident has been escalated When the tenant returns to the portal in a new session Then self‑resolve options remain suppressed and the emergency guidance is shown And the vendor dispatch status is visible if a job exists And only an authorized role can mark the hazard as cleared, which restores normal options And the clearance action requires a reason code and creates an audit log entry
Audit Trail & Export
"As an owner, I want a shareable safety report for each incident so that I can prove due diligence to vendors and insurers."
Description

All SafeStart interactions—prompts shown, user responses, confirmations, media, timestamps, role overrides—are captured as immutable events appended to FixFlow’s photo‑timeline. The system generates an exportable safety report (PDF/link) for owners, insurers, and vendors, with redaction controls for PII. Retention settings follow organizational policy, supporting compliance, dispute resolution, and post‑incident analysis.

Acceptance Criteria
Immutable Event Capture for SafeStart Interactions
Given an active SafeStart flow on a maintenance ticket When a tenant or staff member views a safety prompt, submits a response, confirms a shutoff, uploads media, or completes a step Then an audit event is appended to the ticket’s photo-timeline capturing: event_type, event_id, actor_role, actor_id, timestamp (UTC ISO 8601), prompt_id (if any), response_value (if any), confirmation_flag (if any), media_id(s) (if any), and correlation_id And the event is immutable; any correction creates a new event referencing prior event_id with change_reason, leaving the original unchanged And events are strictly ordered by timestamp and monotonic sequence, with no duplicate event_ids And each event payload includes a SHA-256 hash and the timeline includes a rolling hash to verify integrity
Role Override Logging and Non-Repudiation
Given a safety gate requires confirmation before proceeding When a staff member with override permission bypasses a gate Then an override event is recorded with actor_id, role, reason (free-text up to 280 chars), timestamp, affected_gate_id, and approval_reference (if approval workflow enabled) And the UI blocks progress unless a non-empty reason is provided And the override is visibly flagged in the photo-timeline and in exports And the system prevents deletion/editing of override events; subsequent changes must be additional events
Safety Report Export (PDF and Shareable Link)
Given an authorized user requests "Export Safety Report" for a ticket When the export is generated Then a PDF is produced within 30 seconds for tickets with up to 200 events and 50 media assets And the PDF contains a summary section (ticket_id, property, unit, participants, start/end timestamps, counts by event_type) and a chronological section with event details and media thumbnails/captions And a secure shareable link can be created with a configurable expiration (default 7 days, max 90), optional one-time download, and revocation capability And the export includes the report SHA-256 checksum and a validation endpoint to verify integrity And export creation and each access are logged as audit events
PII Redaction Controls for Exports
Given the export modal is opened When the user selects a role-based template (Owner, Vendor, Insurer) or custom redaction toggles Then the generated report redacts selected PII fields (full name, email, phone, exact unit number, precise GPS, faces in images) by masking or blurring and replaces values with [REDACTED] And redaction choices, actor_id, and timestamp are recorded as an audit event; original stored data remains unmodified And redaction is applied consistently to PDF content, metadata, and link previews And face blurring has a minimum 95% detection confidence with manual include/exclude override per image
Retention Policy Enforcement and Legal Hold
Given an organization retention policy is set (e.g., 24 months after ticket close) When an event exceeds its retention age and no legal hold is active Then the system purges or anonymizes events and associated media per policy and appends a non-removable purge event with counts purged And exports generated after purge exclude purged content and indicate retention applied And when a legal hold is applied to a ticket, purging is suspended; the hold records actor_id, reason, timestamp, and review_date And retention calculations honor the policy anchor (ticket closed_at or last_activity) and respect per-organization overrides
Access Control and Export Link Governance
Given a user attempts to view the audit timeline or generate an export When the user lacks the required permission Then the request is denied with 403 and no event content is leaked in errors or timing And authorized users can access only tickets within their portfolios as per role-based access control And tokenized share links are disabled by default and require explicit creation; tokens contain expiration and scope to a single ticket And revoking a token immediately invalidates the link; subsequent hits return 410 and are logged with user_agent, IP, and timestamp

AR StepGuide

Camera‑assisted overlays highlight the exact knob, valve, or reset button and animate the motion to take (twist, press, flip). Voice and large‑text cues keep instructions accessible. Tenants fix issues faster with fewer mistakes; fewer missteps mean fewer emergency callouts.

Requirements

Cross-Platform AR Core Integration
"As a tenant, I want my phone to provide stable AR guidance regardless of my device so that I can quickly fix issues without technical hurdles."
Description

Implement device camera permissions, AR session management, and plane/feature-point tracking across iOS (ARKit) and Android (ARCore). Provide capability checks and a graceful fallback to 2D guidance when AR is unsupported. Include real-time calibration (distance, scale, and orientation), light estimation for overlay visibility, and performance safeguards to maintain >24 FPS and limit battery drain. Integrate analytics hooks for session start/stop, device model, and fallback usage to inform support and roadmap decisions. This foundation enables reliable overlays for the AR StepGuide within FixFlow across the target device landscape.

Acceptance Criteria
Camera Permission Request and Denial Handling
Given AR StepGuide is opened and camera permission is not granted, When the user selects "Start AR", Then the app displays the OS permission prompt with a rationale screen beforehand. Given the user denies camera permission, When the user reopens AR StepGuide, Then the app shows an inline explainer with an "Open Settings" deep link and offers 2D guidance without attempting to start an AR session. Given camera permission was previously granted, When AR StepGuide opens, Then the AR session initializes within 1.5 seconds and renders the camera feed. Given camera permission is set to Denied/Restricted, When initialization is attempted, Then the app bypasses AR initialization and displays 2D guidance within 1 second without crashing.
AR Session Lifecycle Across App State Changes
Given an active AR session, When the app moves to background, Then the session pauses and the camera is released within 500 ms. Given the app returns to foreground within 60 seconds, When AR StepGuide regains focus, Then the session resumes within 1 second preserving calibration state. Given the app is backgrounded >60 seconds or the OS terminates the session, When it returns to foreground, Then a clean AR session restarts within 2 seconds and previous calibration is discarded with a clear notice. Given ARKit/ARCore reports a fatal tracking error, When the error occurs, Then the app shows a recovery CTA to restart AR and logs the error without crashing.
Cross-Platform Plane and Feature Point Tracking
Given a supported device in indoor lighting (100–500 lux), When the camera is panned over a flat horizontal surface at 0.5–2 m, Then at least one horizontal plane is detected within 3 seconds. Given a supported device, When the camera is panned over a vertical surface at 0.5–2 m, Then a vertical plane is detected within 5 seconds. Given tracking is normal, When the user holds the device steady, Then the feature point cloud updates at ≥10 Hz and plane extents update at ≥5 Hz. Given iOS (ARKit) and Android (ARCore), When the same scene is scanned, Then tracking state and plane anchor events are exposed through a unified API with equivalent semantics.
Capability Check and 2D Fallback
Given a device that fails AR capability checks (missing ARKit/ARCore, unsupported OS, or lacking required sensors), When AR StepGuide is launched, Then the user is routed to 2D guidance within 1 second and informed that AR is not supported. Given a device supports AR but the provider returns "services not installed/updated", When AR StepGuide starts, Then the app prompts to install required services or offers immediate 2D fallback without crashing. Given tracking remains Limited/Unavailable for 10 seconds after start due to insufficient features or sensors, When no improvement is detected, Then the app offers a one-tap switch to 2D guidance and logs the fallback reason.
Real-Time Calibration: Distance, Scale, Orientation
Given an AR anchor is placed, When the user performs pinch, twist, or drag gestures, Then scale, rotation, and position adjust in real time with numeric readouts in metric and imperial units. Given a target at ~1 meter, When the user completes calibration, Then overlay alignment error is ≤2 cm at 1 m and ≤5 cm at 2 m as verified by test fixture. Given Reset is tapped during an AR session, When invoked, Then calibration returns to default and re-centers on the last detected plane within 500 ms. Given a new AR session begins, When calibration starts, Then a one-time distance calibration raycast initializes scale and it persists for the session duration.
Light Estimation and Overlay Visibility
Given a device with light estimation support, When ambient light decreases from >300 lux to <50 lux, Then overlay colors automatically switch to a high-contrast theme within 200 ms and maintain contrast ratio ≥4.5:1 against the camera image. Given light estimation is unavailable, When an AR session starts, Then a neutral high-contrast overlay theme is applied by default. Given ambient light is <30 lux for 10 seconds and tracking is limited by light, When the condition persists, Then the app displays a "Low light detected" prompt suggesting illumination and offers switch to 2D guidance.
Performance Safeguards and Analytics Telemetry
Given a representative QA device matrix, When running AR StepGuide for 10 minutes, Then median FPS ≥30 and 1% low FPS ≥24 with no frame stalls >100 ms at the 99th percentile. Given continuous operation for 10 minutes at room temperature (20–24°C), When measured, Then battery drain is ≤8% and app memory usage attributable to AR remains ≤400 MB. Given sustained FPS <20 for 5 seconds or device thermal state reaches serious, When detected, Then the app reduces camera/AR frame resolution or feature density to recover FPS, and auto-pauses with a message if recovery fails. Given analytics is enabled and consented, When AR StepGuide starts, stops, or shows a fallback, Then events ar_session_start, ar_session_stop, and ar_fallback_shown are emitted with payload: device_model, os_version, ar_provider, reason, duration_ms, fps_median, fps_p1; events are queued offline and flushed within 10 seconds of connectivity without PII.
Fixture & Control Recognition Model
"As a tenant, I want the app to recognize the exact control I should use so that I don’t waste time guessing or touching the wrong part."
Description

Develop an on-device computer vision pipeline to identify common household fixtures (e.g., garbage disposal, faucet, toilet fill valve, breaker panel, HVAC thermostat, water heater) and pinpoint actionable controls (knobs, valves, reset buttons, breakers). Use lightweight models optimized for mobile (e.g., quantized detection/segmentation) with confidence thresholds and a manual override list when recognition is uncertain. Support model versioning and silent updates, and log anonymized recognition outcomes for continuous improvement. This enables precise targeting of the exact control for AR overlays, minimizing tenant confusion and reducing missteps that lead to emergency callouts.

Acceptance Criteria
Under‑Sink Garbage Disposal Reset Button Recognition
Given a tenant points the camera at an under‑sink area containing a standard garbage disposal And ambient light is at least 20 lux When the on‑device model processes a 1080p frame Then it detects the fixture type "garbage_disposal" with confidence >= 0.80 within 300 ms P95 per frame And it detects the actionable control "reset_button" with confidence >= 0.75 And it returns a normalized bounding box for the reset button with center error <= 20 px at 1080p versus labeled ground truth And it exposes the control anchor to the AR overlay API within 50 ms of detection And if fixture or control confidence falls below thresholds, the manual override list for garbage disposal controls is shown within 300 ms
Breaker Panel Tripped Breaker Identification
Given the camera view includes a residential breaker panel with door open When the on‑device model analyzes the frame Then it detects the fixture type "breaker_panel" with confidence >= 0.85 within 300 ms P95 per frame And it enumerates breaker toggles and flags any toggle in mid position (tripped) with confidence >= 0.80 And it returns grid position and bounding box for the tripped breaker And the AR overlay anchor for the tripped breaker aligns within <= 15 px at 1080p compared to ground truth And if no breaker meets confidence thresholds, a manual override to select row/column is presented within 300 ms
Thermostat Mode/Reset Control Recognition
Given the camera is centered on a household HVAC thermostat When the on‑device model runs Then it detects the fixture type "thermostat" with confidence >= 0.85 within 300 ms P95 per frame And it identifies the actionable control ("mode_button" or "reset") appropriate to the detected model with confidence >= 0.75 And it returns a bounding box and control label string for the identified control And the AR overlay anchor aligns within <= 15 px at 1080p versus labeled ground truth And if the thermostat model is unknown or the top two controls are within 0.05 confidence, the manual override list for thermostat controls is shown within 300 ms
Silent Model Update and Versioning
Given the device is idle, on Wi‑Fi, and the app is in the background When a newer signed model is available Then the app downloads the model package silently and verifies both cryptographic signature and checksum And it activates the new model on the next app foreground without blocking the UI And it persists the active model_version_id and checksum for diagnostics And if load or validation fails, it rolls back to the previous model and marks the update attempt as failed And all recognition outcome records include the active model_version_id
Confidence Thresholds and Manual Override Behavior
Given detection results for a video frame When the top control confidence is < 0.75 or the top two control candidates are within 0.05 confidence of each other Then the system suppresses AR targeting for that control And it surfaces a manual override list filtered to the current fixture type within 300 ms And selecting an override option produces an AR anchor for the chosen control and continues guidance And the override reason (low_confidence or ambiguous) is recorded with the event
Anonymized Recognition Outcome Logging
Given recognition events occur during AR StepGuide usage When outcomes are logged Then only metadata is stored/transmitted: timestamp, fixture_type, control_type, confidence, decision (auto|override), device_class, OS_version, model_version_id, lighting_estimate And no raw images or video frames are stored or uploaded And records are queued offline and uploaded in batches over Wi‑Fi or on next app start if offline And when the user disables "Share Anonymized Analytics", recognition outcome logging stops immediately
On‑Device Performance and Offline Operation
Given the device has no internet connectivity When the user invokes AR StepGuide Then fixture and control recognition completes entirely on‑device with zero network calls And median per‑frame inference latency at 1080p is <= 150 ms on reference devices, with P95 <= 300 ms And the model pipeline peak memory usage is <= 150 MB and the model asset size is <= 50 MB And the AR preview maintains >= 24 FPS during recognition on reference devices
Action Overlay & Motion Animation Engine
"As a tenant, I want animated overlays showing exactly how to move or press a control so that I can complete the fix correctly on the first try."
Description

Create a rendering engine that anchors overlays to detected controls and animates the required action (twist, press, flip) with clear visual affordances, progress indicators, and re-alignment cues if tracking drifts. Support multi-step sequences, occlusion handling, and state-change checks to confirm success (e.g., noise change, visual indicator change). Provide standardized components (arrows, halos, pulse effects) and reusable animation presets to accelerate authoring. This engine converts recognition results into intuitive, confidence-building guidance that shortens time-to-fix.

Acceptance Criteria
Anchored Overlay Stability on Detected Control
Given a control is detected with a 6‑DoF pose and bounding geometry When the tenant keeps the camera 0.5–1.5 m from the control and moves at <30°/s Then the overlay remains anchored with ≤2 px image-space jitter and ≤2° rotational error at the 95th percentile And overlay response latency from pose update to render is ≤50 ms And on temporary tracking loss ≤1 s, the overlay freezes in place and resumes with ≤1 px positional jump And on tracking loss >1 s, the overlay hides and re‑acquires the target within ≤1000 ms after pose confidence ≥0.7
Correct Motion Animation for Twist/Press/Flip
Given an action type is provided (twist clockwise, twist counter‑clockwise, press, flip) When the engine renders the action overlay Then the motion glyph aligns within ≤10° of the detected control’s action axis And the directionality (e.g., clockwise vs. counter‑clockwise) matches the action definition 100% of the time And animation plays at 60 fps when available (graceful degradation ≥30 fps) with no dropped frames >1% over 10 s And progress affordance (e.g., ring fill or angle sweep) maps 1:1 to measured actuation (±10% tolerance) And the overlay uses standardized components (arrow/halo/pulse) from the registry without custom code
Drift Detection and Re‑Alignment Cues
Given the overlay is active and tracking quality degrades (reprojection error >3 px for ≥400 ms or pose confidence <0.6) When this condition is met Then the engine pauses step timers and action animations And displays re‑alignment cues (ghosted control silhouette and nudge arrows) within ≤200 ms And guidance resumes automatically within ≤300 ms after reprojection error ≤2 px for 15 consecutive frames and confidence ≥0.7 And the engine logs a drift event with timestamps for analytics
Multi‑Step Guidance with Progress and Step State
Given a multi‑step sequence (N≥2) with per‑step success checks is loaded When a step’s success condition is satisfied Then the engine marks the step complete, advances to the next step within ≤800 ms, and updates the progress indicator (e.g., 2/5) And the user can navigate back to any prior completed step and replay its animation without resetting later steps And if the app is backgrounded for ≤5 minutes, the current step and progress restore within ≤1 s on resume And partial completion and timestamps are persisted to the session record
Occlusion Handling and Overlay Legibility
Given the control region becomes occluded by the user’s hand or another object When ≥50% of the control mask is occluded for ≥300 ms Then the engine enables occlusion handling: depth‑tested rendering hides overlay fragments behind occluders when depth is available, otherwise switches to an outline/billboard indicator with a “Move to reveal” cue And overlay returns to normal mode within ≤300 ms after occlusion drops below 20% And no overlay fragment appears over occluded regions when reliable depth is available (0% bleed‑through)
State‑Change Confirmation via Visual/Audio Signals
Given a step defines success via one or more signals (visual indicator, audio change, or measured actuation) When the tenant performs the instructed action Then success is confirmed if any of the following hold: (a) indicator LED/state change detected with confidence ≥0.8 over 10 consecutive frames; (b) ambient audio level changes by ≥6 dB SPL sustained for ≥1 s; (c) measured rotation/translation reaches ≥80% of target threshold And on success, the engine displays a checkmark and locks the step as complete within ≤300 ms And on no success after 60 s or two failed attempts, the engine surfaces a retry path or escalation hint
Standardized Components and Animation Presets Registry
Given the engine is initialized with the component registry When an author requests a component/preset by ID (e.g., arrow.default, halo.pulse, progress.ring, twist.clockwise) Then the component/preset instantiates via a single API call using a JSON config that validates against the published schema And the registry exposes at least 6 presets covering twist.clockwise, twist.counter, press.tap, press.hold, flip.toggle, valve.openclose And parameter validation enforces documented ranges, returning errors for out‑of‑bounds values And rendering up to 4 components simultaneously adds ≤5 ms to average frame time on a mid‑tier device; total library assets use ≤20 MB RAM at runtime
Voice & Large-Text Accessibility Guidance
"As a tenant with accessibility needs, I want clear voice prompts and large, legible text so that I can follow the steps without strain or confusion."
Description

Add synchronized text captions and text-to-speech prompts for each step with adjustable font sizes, contrast, and color-blind-safe palettes. Support quick voice commands such as “repeat,” “next,” and “pause,” with offline fallback for core phrases. Integrate with OS accessibility settings and provide multi-language packs selectable per case. This ensures the AR StepGuide is inclusive and usable in noisy, dim, or accessibility-constrained environments, reducing instruction errors and support calls.

Acceptance Criteria
Synchronized Captions and TTS per Step
Given a step with timed instructions When the step starts Then the first caption appears within 200 ms of step start And TTS audio begins within 300 ms And caption text exactly matches the TTS script for the step And captions remain visible until the step completes or is paused And pausing the step pauses TTS within 150 ms and freezes captions
Adjustable Large-Text and High-Contrast Modes
Given the user selects text size Large (150%) or Extra Large (200%) When captions render Then text scales accordingly without truncation, overlap, or loss of essential content And line length stays <= 80 characters And scrolling is not required to read a single caption Given High Contrast is enabled When captions and overlays render Then foreground/background contrast is at least WCAG 2.2 AA (4.5:1 for normal text, 3:1 for large text) And no instruction relies on color alone; a shape/icon cue accompanies any color-coded overlay And color palettes pass color-blind-safe checks for protanopia, deuteranopia, and tritanopia simulation
Voice Command Control: Repeat, Next, Pause (Online and Offline Core)
Given AR StepGuide is active and microphone permission granted When the user says "next" or "continue" Then the next step loads within 700 ms and a visual confirmation badge appears Given the user says "repeat" or "say again" When the current step is active Then TTS restarts from the beginning within 500 ms and captions reset to the first line Given the user says "pause" or "stop" When a step is playing Then TTS pauses within 300 ms and captions remain visible with a paused indicator Given the device is offline (airplane mode) When the user says "next", "repeat", or "pause" Then the command is recognized on-device and performed with success rate >= 95% in quiet conditions and >= 85% at 70 dB ambient noise in benchmark tests Given 3 unrecognized commands occur within 30 seconds When the user remains on the step Then an on-screen tip presents tap controls for Next/Repeat/Pause
Integration with OS Accessibility Settings
Given OS text size is set to Large and Bold Text is enabled When the app launches Then caption fonts reflect OS size and weight within 200 ms and persist across screens Given OS Reduce Motion is enabled When AR animations would normally play Then animations are replaced with minimal-motion alternatives (fade/step frames) and no auto-pan/zoom is performed Given a screen reader (TalkBack/VoiceOver) is active When focusing UI elements Then captions and controls expose accessible labels, hints, and actions; focus order matches visual order; and swipe actions activate Next/Repeat/Pause Given Increased Contrast/High Contrast is enabled at OS level When captions and overlays render Then the app applies a high-contrast palette meeting WCAG 2.2 AA thresholds Given OS language differs from case language and per-case override is not set When the guide opens Then UI chrome uses OS language while step captions/TTS use case language
Per-Case Language Packs: Selection, Caching, and Fallback
Given a case language is selected When the StepGuide opens Then captions and TTS play in the selected language for all steps Given the selected language pack is not yet downloaded and network is available When the guide opens Then the pack auto-downloads and installs before step 1 completes its intro, or within 10 seconds (whichever comes first) Given the selected language pack is downloaded When the device goes offline Then captions and TTS remain fully available in that language Given the selected language pack is unavailable and the device is offline When the guide opens Then captions fall back to English with a banner indicating the fallback and a Retry button; TTS uses English voice Given the selected language requires RTL text When captions render Then layout mirrors appropriately and text is correctly shaped and ordered RTL Given pluralization or variable insertion is used in captions When rendering in supported languages Then ICU MessageFormat rules apply and unit tests pass for sample strings in each language
Low-Light and Noisy Environment Readability and Operability
Given Dark mode is selected or ambient light is low When captions and overlays render Then a dark high-contrast palette is applied with contrast meeting WCAG AA and glare-minimizing backgrounds Given ambient noise is high or device volume is muted When the user proceeds through steps Then every instruction is completable using captions and large on-screen Next/Repeat/Pause buttons without relying on audio or voice commands Given the user increases text size to Extra Large (200%) When captions render in AR view Then all critical instruction text remains within the viewport without truncation and does not obscure the highlighted target by more than 25% of its area
Safety Gate & Escalation Logic
"As a property manager, I want unsafe situations to be detected and escalated automatically so that tenants are protected and we avoid liability."
Description

Embed pre-step safety checks (e.g., water near electricity, gas odor, excessive heat) and context prompts, with automatic lockouts and vendor escalation when hazardous conditions are indicated or detected. Provide guided shutoff steps (e.g., breaker off) before proceeding on certain flows, and capture informed consent for proceeding. Implement fail timers and retry limits that trigger escalation to a vetted vendor, sending relevant context for faster diagnosis. All outcomes are logged into the FixFlow case record to reduce liability and ensure auditable decisions.

Acceptance Criteria
Pre-Step Hazard Detection Gate
Given a tenant starts any AR StepGuide flow When the pre-step safety check is presented Then the user must answer hazard prompts for water near electricity, gas odor, smoke/heat, and structural damage before any actionable step is shown And if the user indicates any hazard or the system detects a hazard via CV model with confidence ≥ 0.80, a safety lockout screen is shown within 2 seconds And progression to the next step is disabled until the hazard is cleared or escalated And the hazard type, captured frame, and detection confidence are recorded to the case record
Gas Odor Lockout and Escalation
Given the user selects “I smell gas” or the system detects a gas-odor indicator via prompt response When the response is submitted Then the AR guidance is immediately halted and a hard lockout is applied And the user is shown evacuation and do-not-operate instructions and cannot resume the flow And escalation to a gas-qualified vetted vendor is auto-initiated within 60 seconds And the dispatch packet includes: property and unit IDs, tenant contact, hazard type=gas-odor, timestamp (UTC), current flow and step IDs, last 3 captured photos/frames, user responses, and device locale And an escalation event is appended to the FixFlow case record with status “Dispatched”
Water–Electricity Safety Shutoff Gate
Given water is reported near an outlet/appliance or CV detects standing water within 1m of an electrical device (confidence ≥ 0.80) When the flow would otherwise instruct touching an electrical control or device Then the system inserts a mandatory “Power Off” subflow before any other action And the subflow provides AR overlay guidance to locate the correct breaker and shows the toggle direction animation And the user must confirm power-off via on-screen toggle plus CV verification of breaker handle position change (delta ≥ 20°) or outlet test step And only upon verified power-off is the next step unlocked; otherwise after 2 failed verifications or 5 minutes total, escalation to an electrical-qualified vendor is triggered And all confirmations, failures, and media are logged to the case timeline
Informed Consent for Non-Lethal Risk Override
Given a borderline but non-lethal condition is indicated (e.g., warm surface, minor leak) and an override path exists When the user requests to proceed despite warnings Then a risk summary modal is displayed with plain-language risks and step-specific precautions And the user must check an “I understand the risks” box and enter full name to proceed And consent capture stores: user-entered name, consent text version ID, timestamp (UTC), device ID, flow and step IDs And if consent is not provided within 90 seconds, the flow returns to the safety screen and offers vendor escalation And a consent event is written to the case record and is viewable in the audit trail
Fail Timers and Retry Limits Escalation
Given a critical step is marked time-bounded or verification-required When the user attempts the step Then a visible countdown timer starts (default 5 minutes) and a retry counter is shown (max 2 attempts) And each failed verification attempt (e.g., CV mismatch, incorrect control manipulated) decrements retries and logs the reason code And upon timer expiry or retries exhausted, the flow is locked and vendor escalation is triggered automatically And the dispatch packet includes the failure mode, attempts count, elapsed time, and last verification artifacts And the user is notified that a vendor has been contacted and given ETA once available
Comprehensive Outcome Logging and Audit Trail
Given any safety gate, lockout, consent, shutoff, or escalation event occurs When the event is committed Then a case timeline entry is created with: event type, actor (user/system), timestamp (UTC), flow/step IDs, decision path, and attached media/consent artifacts And entries are immutable (write-once) and sequentially ordered with unique event IDs And authorized roles (tenant, vendor, owner/manager) can view relevant entries per role-based access controls And an export of the safety decision log as a PDF with embedded thumbnails can be generated on demand And any failure to write an entry surfaces a non-dismissible error and blocks progression until persistence succeeds or escalation is triggered
Annotated Photo-Timeline Sync
"As an owner, I want a clear, annotated photo timeline of the repair attempt so that I can verify work done and resolve disputes quickly."
Description

Automatically capture before/after frames for key steps and render overlay annotations (arrows, labels) into images stored in the FixFlow case timeline. Perform on-device redaction of faces and sensitive documents, attach timestamps, step IDs, and success/failure flags, and allow short voice-to-text notes. Package these artifacts for vendor handoff when escalation occurs, creating an auditable, shareable record that shortens diagnosis and resolves responsibility disputes.

Acceptance Criteria
Auto Before/After Capture for Key AR Steps
Given a guided repair step is entered in AR StepGuide When the step loads Then the app captures a "before" frame within 2 seconds at >= 1080p (or device max >= 720p) and stores it to the case timeline tagged with stepId and capturedAt (UTC). Given a guided repair step is completed, failed, or the user taps "Done" When the completion event fires Then the app captures an "after" frame within 2 seconds and stores it to the case timeline linked to the matching "before" frame. Given camera permissions are denied When capture is attempted Then the user is prompted once to grant permission and the timeline records a non-blocking entry status "capture-skipped:permission-denied". Given repeated attempts of the same step When multiple captures occur within 10 seconds Then duplicate frames are de-duplicated via perceptual hash (threshold ≤ 10) and only unique images are saved. Given device orientation changes between captures When images are stored Then orientation is normalized so timeline images display upright and consistently.
Overlay Annotations Embedded in Timeline Images
Given AR overlays are visible (arrows, labels, highlights) When a frame is captured Then overlays are rasterized into the saved image at recorded coordinates with ≥ 3:1 contrast ratio and at 2× device pixel density. Given a capture contains a target marker When saved Then the step label and target name render on-image without obscuring more than 20% of the target bounding box. Given overlay vector data exists When stored Then overlayVersion and overlayChecksum are recorded in the entry metadata. Given no overlays are active When a capture occurs Then the image is saved without synthetic graphics.
On-Device PII Redaction Prior to Sync
Given a frame contains a detectable human face or document-like region When preparing to sync Then those regions are blurred on-device (Gaussian radius ≥ 12px) using a redaction mask before any network transmission. Given redaction has been applied When uploading Then no unredacted pixel data of the original frame is transmitted or persisted (verified by payload inspection in tests). Given redactions are applied When saved Then redaction mask polygons and detector confidence scores (faces confidence ≥ 0.80) are stored in metadata on the timeline entry. Given the user previews the image When reviewing Then the preview matches the redacted image exactly as uploaded.
Stamped Metadata and Tamper Evidence
Given any capture is stored When saved Then it includes ISO 8601 UTC timestamp (capturedAt), stepId, and result flag in {success, failure, skipped}. Given an entry is persisted When finalized Then a SHA-256 hash over image bytes and normalized metadata JSON is computed and stored as contentHash. Given multiple entries exist When saved sequentially Then each entry also stores prevHash referencing the prior entry to form a tamper-evident chain. Given an entry requires correction (e.g., note edit) When updated Then a new version is appended with new hashes while the original version remains immutable and viewable in history.
Voice-to-Text Notes Association
Given a capture is completed When the user taps the mic icon Then the app records up to 30 seconds of audio, transcribes on-device, and attaches the text note with languageCode to the same timeline entry. Given a transcription is generated When shown to the user Then the user can edit the text prior to sync; only the text is uploaded and the raw audio is deleted after successful sync. Given transcription fails within 5 seconds When fallback triggers Then a text field is presented for manual entry and the note is still associated to the entry.
Offline Capture and Reliable Sync
Given the device is offline When captures and notes are created Then they are stored locally encrypted using the OS keystore and queued for sync. Given connectivity resumes When the device is online Then all pending entries sync within 60 seconds, preserving original capturedAt timestamps and timeline order. Given a sync attempt fails When retrying Then the app retries up to 5 times with exponential backoff (max interval 5 minutes) and surfaces a non-blocking warning to the user. Given local storage usage exceeds 200 MB or 100 unsynced entries When additional captures are attempted Then the user is prompted to free space and new captures are blocked until available space exists to prevent data loss.
Vendor Handoff Artifact Package
Given a case is escalated to a vendor When escalation is confirmed Then the system assembles a package within 5 seconds containing redacted before/after images with embedded overlays, a metadata JSON (timestamps, stepId, result, redaction masks), and any text notes. Given the package is generated When shared Then a secure, role-restricted link is created with a 7-day default expiry and revocation capability by staff. Given a vendor accesses the link When downloading Then the package downloads successfully and the access event (vendorId, timestamp UTC, IP) is logged to the case audit trail. Given no captures exist for the case When escalated Then the package includes a zero-artifact manifest stating no timeline media available.
StepGuide Content Management & Versioning
"As an operations lead, I want to create, localize, and roll out updated AR guides without shipping a new app so that we can improve fix rates rapidly."
Description

Provide an internal CMS for authoring and updating AR step guides per issue and appliance type, including target recognition mappings, step sequences, text/voice content, and localization. Support semantic versioning, staged rollouts, instant rollback, and offline caching on devices. Include analytics (completion rate, step-level drop-off, success time) and A/B testing to continuously optimize guidance. This decouples content iteration from app releases, enabling rapid improvements without developer intervention.

Acceptance Criteria
Authoring AR StepGuide with Target Mappings and Step Sequence
Given a new AR StepGuide is created for a specific appliance model and issue type in the CMS When the author adds at least one target recognition mapping, defines a step sequence with overlays (highlight, arrow, or outline), assigns a motion animation per step (twist/press/flip), enters large-text instructions (≥18pt equivalent), and attaches voice cues (TTS or audio) Then the CMS validates all required fields and blocks publish if any are missing, allowing Save as Draft v0.1.0 And the device preview link loads the draft within 10 seconds and renders overlays aligned within ±2 cm at 1 m distance on supported devices And voice cues play without clipping and text is legible against video using accessible contrast (WCAG AA) And the draft remains invisible to tenants until published
Semantic Versioning and Publish Workflow
Given a Published StepGuide exists at version v1.2.0 When an author edits copy-only fields and selects Patch, Then the new version is v1.2.1 with required release notes When an author edits non-breaking instructional content (adds a step without changing target mappings) and selects Minor, Then the new version is v1.3.0 with required release notes When an author changes target recognition mappings or step order marked as breaking and selects Major, Then the new version is v2.0.0 with required release notes Then publishing makes the selected version available to assigned properties within 5 minutes without requiring a mobile app update And the content is served via immutable, versioned endpoints with content hashes to prevent cache collisions
Staged Rollout by Cohort and Percentage Ramp
Given a new StepGuide version v2.0.0 is ready for rollout When the product owner configures a rollout plan of 10% → 50% → 100% to eligible sessions with a 5% control holdout, optionally targeting cohorts by property, region, or OS Then observed session allocation matches configured percentages within ±2% over at least 1,000 sessions And changing the allocation takes effect for new sessions within 5 minutes And pausing the rollout prevents assignment to the new version for new sessions within 2 minutes while preserving existing session stickiness
Instant Rollback to Previous Version
Given StepGuide v2.0.0 is live to ≥50% of traffic and v1.3.0 is the previous stable version When an authorized user triggers Rollback to v1.3.0 Then 95% of new sessions receive v1.3.0 within 60 seconds and 99% within 5 minutes And devices with v2.0.0 cached fetch the v1.3.0 manifest on next launch or within 5 minutes of heartbeat And in-flight sessions continue their current version until restart, with a banner indicating a new version is available And analytics attribute post-rollback events to v1.3.0 without mixing with v2.0.0
Offline Caching and Sync on Devices
Given a tenant device is online and authenticated for a property with assigned StepGuides When the app syncs on Wi‑Fi or unmetered connection, Then it downloads the latest manifests and assets, verifies checksums, and caches ≤50 MB per property (configurable) Then a tenant can start and complete any cached StepGuide fully offline with time-to-first-step <2 seconds on a mid-tier device And when online returns, differential updates reduce download size by ≥60% vs full package for text-only changes And failed downloads retry with exponential backoff and respect device battery saver; cache eviction uses LRU while maintaining ≥500 MB free storage
Localization with Fallback for Text and Voice
Given a StepGuide has localized content for en-US and es-US including text and voice (TTS or audio) When a tenant device locale is es-US Then es-US content is used for all steps; if any step lacks es-US, that step falls back to en-US while logging a localization warning And the CMS preview allows switching locales and playing voice assets per step And TTS synthesis uses the configured voice with lexicon rules applied; audio start latency between steps is <300 ms And publishing a locale-only update increments the patch version and affects only the updated locale payload
Analytics Instrumentation and A/B Testing
Given analytics is enabled for StepGuides When a tenant starts, progresses through steps, completes, or exits a guide Then events (guide_start, step_view, step_complete, drop_off, guide_success) are captured with timestamps, version, variant, device/OS, and locale And dashboards display per-version metrics (completion rate, median time-to-success, step-level drop-off) within 15 minutes of event ingestion And raw, de-identified events are exportable via API with a data freshness SLA of ≤15 minutes; no PII is stored And an A/B test can define variants with traffic split, success metric, and minimum sample size; randomization unit is device, assignment is sticky for 30 days And when a winner is declared, the losing variant can be disabled within 2 minutes and the winner promoted without requiring an app update

QuickParts Cart

Auto‑suggests the exact consumables and low‑cost tools needed (plunger type, P‑trap gasket, AA batteries) with live pricing and delivery options. Where possible, provides tool‑free alternatives. Tenants can one‑tap order or pick up nearby, preventing stalled fixes and unnecessary dispatches.

Requirements

Contextual Parts & Tools Suggestion Engine
"As a tenant, I want the app to suggest the exact parts and small tools I need for my issue so that I can fix it quickly without guessing or buying the wrong items."
Description

Leverages FixFlow’s triage inputs, property metadata, and ticket context to automatically identify the exact consumables and low‑cost tools likely needed to resolve a reported issue (e.g., specific plunger type, P‑trap gasket size, AA batteries). Produces a ranked list of SKUs with compatibility notes, quantities, and success likelihood, prioritizing low-cost, widely available items. Incorporates lightweight image cues and user prompts to refine dimensions or variants when ambiguous. Excludes pro‑only components, focusing on safe, tenant‑actionable items. Integrates directly into the QuickParts Cart UI and writes chosen items back to the associated work order.

Acceptance Criteria
Drain Clog—Correct Plunger Type and Tool‑Free Alternatives
Given triage inputs indicate a bathroom sink slow drain and property metadata confirms a sink fixture without a garbage disposal When the suggestion engine generates the parts/tools list Then the first recommendation is a tool‑free/no‑purchase alternative if predicted success likelihood ≥ 0.40 And the list includes a cup plunger SKU (sink‑appropriate) and excludes a toilet flange plunger unless the fixture type is toilet And each suggestion includes: SKU, default quantity, success likelihood (0.00–1.00), compatibility notes, live price, and at least one fulfillment option (delivery or nearby pickup) And the response time to render the suggestions is ≤ 3 seconds at the 95th percentile And no pro‑only items appear in the list
Leaky P‑Trap—Gasket Size Disambiguation via Prompt/Image
Given triage indicates leak at the sink P‑trap and property metadata lacks trap diameter When a photo is attached or ambiguity is detected Then the engine either infers 1‑1/4 in vs 1‑1/2 in via image cues with confidence ≥ 0.70 or prompts the user with a single disambiguation question (max one prompt) And upon disambiguation the suggestions include only SKUs matching the confirmed size with explicit compatibility notes And if the user skips the prompt, both sizes are shown, clearly labeled, and Add to Cart requires selecting one size And the selected size is saved to the unit’s property metadata for future tickets
Low Battery—AA Battery Suggestion with Live Pricing & Fulfillment
Given triage indicates a low‑battery device (e.g., smart lock or smoke detector) and property metadata lists AA as the battery type When the suggestion engine runs Then it recommends an AA battery pack with a quantity matching device requirements from ticket context and a default pack size ≤ 8 And shows live pricing from at least 2 vendors with delivery ETA and nearest pickup distance And selecting Order writes line items to the work order with SKU, supplier, unit price, quantity, total, fulfillment method, and external order ID And if live pricing is unavailable, last‑known price (age ≤ 30 days) is shown with a “pricing may vary” label
Safety & Pro‑Only Exclusions
Given triage indicates a condition likely requiring licensed work (e.g., suspected gas leak, recurring breaker trip, PRV replacement) When the suggestion engine evaluates candidate items Then no pro‑only components or hazardous chemicals are suggested And a safety advisory is displayed with an option to request vendor dispatch instead of purchase And an audit log records the exclusion decision with rationale and timestamp
Ranking and Prioritization Policy
Given a candidate set of compatible SKUs for the issue When the engine ranks the list Then items are ordered by (1) descending success likelihood, (2) ascending total cost, (3) descending availability (in‑stock local/ships today) And the top 3 suggestions each have success likelihood ≥ 0.50 And each item displays availability status (In stock/Low stock/OOS) refreshed within the last 5 minutes And ties are broken by vendor rating (desc) then price (asc) And the computed rank score is stored with each suggestion for auditability
QuickParts Cart Integration and Work Order Sync
Given suggestions are displayed in the QuickParts Cart UI When a user taps Add to Cart and proceeds to Checkout Then the cart shows accurate quantities, unit prices, subtotals, taxes, shipping, and ETA And Checkout writes selected items back to the associated work order atomically with: SKU, description, compatibility note, quantity, unit price, total, supplier, taxes, shipping, fulfillment method, ETA, selected by (user ID), and timestamp And duplicate taps are idempotent (no duplicate line items created) And success is confirmed in the UI and the work order timeline logs an entry; on failure, no partial write occurs and a retryable error is shown
Live Pricing & Fulfillment Aggregation
"As a tenant, I want to see live prices and delivery or pickup times from nearby stores so that I can choose the fastest or cheapest option to get my repair moving."
Description

Aggregates real‑time pricing, stock, and fulfillment options across connected retailers (delivery and in‑store pickup), displaying total cost with taxes/fees and ETA per option. Uses the property’s geolocation to surface nearby pickup choices and fastest delivery windows. Handles retailer API rate limits and outages with graceful fallbacks and caching. Normalizes different vendors’ product data into a consistent display and flags unreliable listings. Updates availability dynamically until checkout to minimize stock surprises.

Acceptance Criteria
Show Real-Time Prices, Fees, and ETA per Retailer Option
Given a selected product and at least one connected retailer supports the SKU And the property address and tax jurisdiction are known When the tenant opens the QuickParts Cart Then each retailer option displays item price, taxes/fees, total cost, and an ETA labeled by fulfillment type (Delivery or Pickup) And totals use tax rates computed for the property location And ETAs use the most recent retailer-provided delivery or pickup windows And options with missing price or ETA are excluded from display and logged for monitoring
Surface Nearby Pickup and Fastest Delivery Using Property Geolocation
Given the property geolocation is available And at least one retailer offers in-store pickup within 25 miles When fulfillment options are presented Then pickup options are sorted by earliest ready-for-pickup time, then by distance And each pickup option shows store distance (miles/km), earliest pickup time, and store hours And delivery options are sorted by earliest delivery ETA, then by lowest total cost And if geolocation is unavailable, the system falls back to the property address; if neither is available, pickup options are hidden
Graceful Degradation on Retailer API Rate Limits or Outages
Given one or more retailer APIs return 429 or 5xx responses or time out When the system aggregates pricing and availability Then the system serves cached results not older than 10 minutes for affected retailers with a "May be outdated" label And implements exponential backoff with jitter and a maximum of 2 retries per retailer within 30 seconds And excludes unavailable retailers from "Best option" ranking while still showing available ones And displays a non-blocking banner: "Some retailers are temporarily unavailable" And records the incident in monitoring with retailer ID, error code, and duration
Normalize and Deduplicate Product Data Across Vendors
Given multiple retailers return offers for the same underlying product When offers are displayed Then each offer renders a consistent schema: Title, Brand, Unit Size, Pack Quantity, Condition, Fulfillment Type, Price, Taxes/Fees, Total, ETA And units are normalized (e.g., fl oz, lb, count) and currency is unified to the tenant’s billing currency And duplicate offers (same GTIN/UPC or normalized Title+Brand+Unit Size) are merged and shown once per retailer And retailer-specific attributes (SKU, return policy) remain accessible in details And variations (e.g., 2-pack vs 1-pack) are clearly labeled and not merged
Flag and Deprioritize Unreliable Listings
Given the system computes a reliability score per listing using signals (missing GTIN, frequent stock flips in last 7 days, retailer rating < 3.5/5, price outlier vs median) When listings are ranked Then listings with reliability score < 0.6 are badged "Low reliability" and excluded from default ranking unless the user opts to include them And a price outlier is defined as > 40% above or below the median price for the same GTIN within the last 24 hours across retailers And all flags and scores are persisted to an audit log with timestamp and inputs used
Continuous Availability Revalidation Until Checkout
Given a tenant has selected a retailer option When the QuickParts Cart remains open Then the system revalidates stock status and ETA every 60 seconds without disrupting the user’s selection And upon Add to Cart or Checkout, the system revalidates the selected option within 2 seconds And if the item is out of stock or ETA degrades by > 30 minutes, the checkout is blocked and the user is presented with the next-best alternatives sorted by total cost then ETA And if the selection remains valid, checkout proceeds without additional prompts
Performance and Scalability Targets for Aggregation Endpoint
Given up to 6 connected retailers for a query When aggregating offers Then p95 end-to-end response time is ≤ 2.5 seconds and p99 is ≤ 4.0 seconds under normal load (≤ 20 RPS) And per-retailer requests run in parallel with a per-retailer timeout of 1.5 seconds so one slow retailer does not block others And partial results are returned when one or more retailers exceed their timeout, with a UI indicator per affected retailer And the endpoint maintains ≥ 99.0% success rate over a 30-day window excluding third-party outages
One‑Tap Checkout & Pickup
"As a tenant, I want to complete my purchase in one tap with my saved payment and address so that I can get parts without a complicated checkout."
Description

Provides a frictionless purchase flow with saved payment methods (tokenized via PSP), Apple Pay/Google Pay, and prefilled shipping addresses tied to the unit. Supports one‑tap order confirmation, pickup barcodes where applicable, and automatic inclusion of unit/access notes for delivery. Sends confirmations and receipts to the work order, and supports cancellation/refund triggers when orders change. Ensures PCI compliance by never storing raw card data and logging order IDs for reconciliation and support.

Acceptance Criteria
One‑Tap Delivery Checkout with Saved Payment
Given an authenticated tenant with at least one PSP‑tokenized payment method on file and a default unit shipping address, When the tenant taps "Buy Now" for delivery in the QuickParts Cart, Then the order is placed without additional forms, payment is authorized via token, the prefilled unit shipping address is used, and a unique Order ID is returned within 5 seconds. And the UI displays an in‑app confirmation with Order ID and delivery ETA. And an itemized receipt and confirmation are posted to the associated work order within 30 seconds and sent via the tenant’s configured notification channels (email/SMS/push).
Apple/Google Pay Express Checkout
Given the tenant’s device supports Apple Pay or Google Pay and a valid wallet is available, When the tenant taps the corresponding express pay button and completes device authentication, Then the PSP returns a payment token and masked card details; FixFlow stores only the token and masked last4/brand, never raw PAN/CVV/expiry. And the order is created and confirmed within 5 seconds, with shipping/contact data provided by the wallet if no unit override is specified. And the work order is updated with Order ID, payment method = ApplePay|GooglePay, and a receipt within 30 seconds.
Automatic Inclusion of Unit and Access Notes for Delivery
Given a work order exists with unit‑level access/delivery notes, When the tenant places a delivery order via one‑tap checkout, Then the order payload includes the unit/access notes in the delivery instructions field (up to 500 characters, truncated with ellipsis if longer). And the notes appear in the carrier/vendor view and in the work order audit trail. And only necessary PII is transmitted per least‑privilege policy (e.g., no tenant phone if building call box code is present).
Store Pickup with Scannable Barcode
Given the tenant selects store pickup and chooses a supported retailer location, When checkout completes successfully, Then a scannable QR/barcode containing the retailer reference and FixFlow Order ID is generated, displayed, and delivered to the tenant and work order. And an offline‑available pass is saved (barcode plus fallback alphanumeric code) valid through the retailer’s pickup window. And scanning the code at the retailer confirms order retrieval status back to FixFlow within 60 seconds of retailer callback.
Cancellations and Refunds Sync to Work Order
Given an order is in Placed or Fulfillment state, When the work order is cancelled, the item is resolved without need, or the tenant initiates cancel, Then FixFlow requests cancellation via vendor API if within the cancellable window and records the outcome with timestamp and actor. And if a refund (full or partial) occurs, the refund amount, currency, reason, and PSP reference are posted to the work order within 60 seconds of PSP callback. And the order state is updated in‑app to Cancelled or Refunded accordingly, with notifications sent to the tenant.
PCI Compliance and Payment/Order Logging
Rule: FixFlow never stores or logs raw cardholder data (PAN, CVV, full expiry, track data) at any point in checkout. Rule: All payment entry uses PSP hosted fields/SDK; FixFlow stores only PSP tokens plus masked last4 and brand. Rule: Logs/work orders mask sensitive data; PSP payloads are redacted per PCI DSS. Rule: Automated tests scan logs for PAN‑like patterns and fail the build on violation. Rule: Each order writes a unique Order ID and PSP charge/transaction ID to the work order for reconciliation and support.
Tool‑Free Alternatives Recommendations
"As a tenant, I want tool‑free alternatives when possible so that I can resolve simple issues quickly without buying tools I may not use again."
Description

Detects opportunities to avoid tool purchases by recommending safe, tool‑free methods and pre‑assembled consumables (e.g., enzyme drain packs, hand‑tighten fittings, adhesive hooks) with simple step‑by‑step micro‑guides. Presents comparative cost/time and likelihood of success to help tenants choose confidently. Surfaces cautions for scenarios where a tool‑free attempt is not recommended. Integrates with triage outcomes and records selected guidance in the work order timeline.

Acceptance Criteria
Suggest tool-free alternative for minor sink clog
Given a triage outcome of "Slow drain" or "Minor clog" for a sink, when the QuickParts Cart loads, then a tool‑free alternative card is displayed above tool purchase suggestions within 1.5 seconds on a 4G connection. Given tool‑free alternatives exist with predicted success ≥ 50%, when ranking suggestions, then tool‑free appears as the top recommendation. Given a tool‑free card is shown, then it includes at least one consumable or action requiring no tools (e.g., enzyme drain pack, hand‑tighten) with price, delivery ETA, and nearest pickup availability within 10 miles. Given live inventory/pricing is unavailable, then the card displays an "N/A" badge without blocking other content and logs a recoverable error.
Provide step-by-step micro-guide for tool-free method
Given a tool‑free alternative card, when the tenant taps "How‑to", then a micro‑guide opens with 3–7 ordered steps, each step ≤ 160 characters. Given the guide is shown, then at least one illustration or annotated image is displayed and each step has a checkbox to mark completion. Given the guide content is rendered, then safety callouts (e.g., gloves, ventilation) appear before the first risky step. Given copy guidelines, then the guide reading level is ≤ 8th grade per automated check. Given the tenant marks all steps complete, when they tap "Mark as done", then completion is recorded and the guide closes or offers follow‑up options.
Display comparative cost/time and success likelihood
Given a tool‑free alternative and a next‑best tool purchase option are available, then the UI displays for each: estimated total cost (USD), time to attempt (minutes), and success likelihood (%), side‑by‑side in one component. Given success likelihood is computed, then a confidence band (Low/Med/High) is shown and the numeric % is rounded to the nearest 5%. Given any metric is unavailable, then show "N/A" with an info tooltip; do not hide the comparison component. Given both options have metrics, then the delta savings (cost and minutes) is calculated and highlighted. Given values are fetched from backend, then displayed numbers match backend within ±1% or ±1 minute.
Gate unsafe tool-free attempts with caution
Given the triage outcome is tagged as Electrical, Gas, Structural, or Active water leak, when the QuickParts Cart opens, then no tool‑free alternatives are displayed. Given an unsafe tag is present, then a caution banner shows "Tool‑free not recommended" with the rule reason and the required next action (e.g., shutoff and dispatch). Given the caution banner is shown, then all "Try tool‑free" actions are disabled and not tappable. Given the tenant proceeds, then they must acknowledge the caution before dispatch or tool purchase. Given a caution is shown, then the event (rule ID, time, user) is recorded to the work order timeline.
One-tap order or local pickup for consumables
Given a tool‑free alternative requires a consumable, when the tenant taps "Order", then a cart is created with exact SKU and quantity defaulted from the guide. Given the cart is created, then taxes/fees and final price are visible before confirmation. Given nearby inventory exists, then at least 3 closest in‑stock pickup locations within 15 miles are listed, sorted by distance with ETAs. Given delivery is available, then delivery ETA windows and shipping cost are shown; one‑tap checkout with saved payment returns confirmation within 2 seconds or shows an error state. Given an order is confirmed, then order details (SKU, qty, price, ETA) are posted to the work order timeline.
Record selected guidance to work order timeline
Given the tenant opens a tool‑free guide, when they tap "Start", then a timeline entry is created with timestamp, triage outcome ID, guide ID and version, and user ID. Given the tenant chooses an option, then the recommendation offered, success likelihood %, and the choice made (Guide, Tool purchase, Dispatch) are recorded in the same entry. Given the tenant marks the guide as done or abandons it, then the result, duration, and any uploaded photos are appended to the entry. Given timeline APIs are queried for the work order, then the new entry is retrievable within 200 ms and is immutable. Given default permissions, then the entry is visible to Tenant, Landlord, and Vendor roles.
Owner Spend Guardrails & Approvals
"As an owner, I want spending limits and approval controls on tenant part orders so that costs stay within budget without blocking urgent low‑cost fixes."
Description

Allows owners/managers to set per‑ticket and per‑property spending caps, disallowed item categories, and auto‑approval rules. Automatically approves orders under the cap and routes over‑cap carts for owner approval with a concise summary of cost, ETA, and impact on dispatch avoidance. Captures decisions in an auditable log and notifies tenants of approval status to prevent stalled fixes. Provides configurable notifications and escalation windows to keep repairs moving.

Acceptance Criteria
Auto-Approve Under Cap
Given an owner has set a per-ticket cap of $75 and a per-property monthly cap of $300 and the cart contains only allowed items When a tenant proceeds to checkout and the cart total (items + taxes + delivery + fees) is <= $75 and the property's approved month-to-date spend + this cart total is <= $300 Then the order is auto-approved within 5 seconds of checkout submission And the tenant sees an in-app "Approved" confirmation immediately and receives notifications on all enabled channels within 30 seconds And no owner approval request is generated
Route Over-Cap for Owner Approval
Given per-ticket and per-property caps are configured for the property When a tenant's cart total exceeds the per-ticket cap OR approving it would exceed the remaining monthly property cap Then auto-approval is prevented and an owner approval request is created within 5 seconds And the tenant is shown a "Pending owner approval" status with the configured decision window And the owner is notified on all enabled channels within 30 seconds And no payment is captured and no vendor dispatch/fulfillment is initiated until a decision is recorded
Disallowed Item Categories Enforcement
Given the owner has configured one or more disallowed categories (e.g., Power Tools, Hazardous Chemicals) When a tenant adds a disallowed item to the cart or attempts checkout with such an item present Then checkout is blocked and the item is flagged as disallowed And up to 3 allowed alternatives are suggested where available And the disallowed item remains ineligible for approval until the category is removed from the disallowed list And an audit event is recorded noting the disallowed category and item
Owner Approval Summary Completeness
Given an over-cap cart triggers an owner approval request When the owner opens the approval request Then the summary includes: itemized list with per-item price, subtotal, taxes, delivery/fees, total; configured per-ticket cap and remaining headroom; property month-to-date approved spend and remaining headroom; delivery options with ETAs; predicted dispatch-avoidance impact score (0–100%) with a one-sentence rationale; escalation and expiration timestamps And all monetary values reflect the latest live pricing at request time and sum to the displayed total within ±$0.01 And all timestamps display in the owner's local timezone with UTC offset
Decision Capture & Auditability
Given an approval request is pending When an owner approves or rejects the request Then the decision is recorded immutably with: requestId, ticketId, propertyId, actorId, actorRole, decision (Approve/Reject), optional reason/comment, timestamp (UTC), decision channel, evaluated caps and rule identifiers, and previous state And the log entry is visible in the ticket timeline and property history And the decision cannot be edited; only append-only notes are allowed And the tenant is notified of the decision within 30 seconds
Notifications & Escalation Workflow
Given the owner has configured notification channels and escalation windows (e.g., initial 0 minutes, reminder 60 minutes, escalate at 4 hours) When an owner approval request is created Then initial notifications are sent to primary contacts on all enabled channels immediately and delivery status is tracked And reminders are sent at the configured intervals until a decision or escalation And at the escalation threshold, the request is sent to the configured escalation contacts with high priority And if no decision by the final SLA cutoff, the configured fallback action is applied (e.g., auto-approve up to emergency threshold or auto-cancel), and both owner and tenant are notified of the outcome
Concurrent Spend Cap Enforcement
Given two tenants submit carts for the same property such that each cart individually fits under the remaining monthly cap but together they would exceed it When both checkouts occur within 1 second of each other Then the system enforces the monthly cap atomically so that at most one cart is auto-approved based on first-committed transaction And the other cart is routed for owner approval due to cap exhaustion And no double-approval occurs And the audit log records the sequencing/locking decision for traceability
Order‑to‑Work‑Order Sync & Audit Trail
"As a property manager, I want orders and delivery status to sync to the work order so that everyone has a clear, auditable timeline of the repair."
Description

Synchronizes selected items, order confirmations, tracking updates, and pickup status directly into the maintenance ticket timeline. Automatically updates ticket states (e.g., “Parts Ordered”, “Ready for Attempt”) and prompts tenants to upload before/after photos, creating an auditable, time‑stamped record. Exposes order details to owners and vendors to reduce disputes and coordinate follow‑ups if parts fail to resolve the issue.

Acceptance Criteria
Sync Order Items to Ticket Timeline
Given a maintenance ticket with a QuickParts order is placed When the order is confirmed by the supplier or a pickup reservation is created Then a timeline entry is created within 10 seconds containing item name, SKU, quantity, unit price, subtotal, taxes/fees, supplier, order ID, ETA, delivery/pickup method, and a link to the confirmation And the entry is time-stamped to the second (UTC) and attributed to System: QuickParts And duplicate callbacks do not create duplicate entries (idempotency key enforced) And transient failures are retried with exponential backoff up to 5 attempts; on final failure, a timeline error entry is recorded with reason
Auto State Transitions Based on Order Lifecycle
Given a ticket has no open parts orders When an order confirmation is received for any item Then the ticket state updates to Parts Ordered and a timeline state-change entry is recorded And when all items are Delivered or Picked Up Then the ticket state updates to Ready for Attempt and a prompt is queued to the tenant And when at least one item is Backordered and none are Delivered Then the ticket state updates to Awaiting Parts And all transitions are idempotent and logged with previous and new state
Track Shipment/Pickup and Append Updates
Given tracking webhooks or polling at up to 15-minute intervals are enabled When a carrier status changes (e.g., Shipped, Out for Delivery, Delivered) Then a timeline entry is appended with status, carrier, tracking number, scan timestamp, and updated ETA And Out for Delivery triggers notifications to tenant and assigned vendor And Delivered captures and stores proof-of-delivery link when provided by carrier And for pickup orders, Ready for Pickup and Collected statuses are recorded with store location and pickup code (masked)
Tenant Photo Prompts and Upload Enforcement
Given a ticket transitions to Ready for Attempt When the tenant opens the ticket in the portal Then the UI requires at least one Before photo upload prior to starting work (owner/vendor override requires reason) And after the tenant marks Attempted Fix Then the UI prompts for at least one After photo before ticket can be resolved And uploads are time-stamped, tied to the ticket ID, and stored with checksum; location metadata is captured only if permission granted And if photos are missing 24 hours after Ready for Attempt, a reminder is sent; after 48 hours, an escalation is sent to the owner
Owner and Vendor Visibility to Order Details
Given an owner or assigned vendor views the ticket When the order details panel is opened Then owners can view itemized costs, taxes/fees, order documents, and tracking/pickup info And vendors can view items, quantities, ETA, tracking/pickup info and pickup code (masked), but not tenant PII or payment method details And access is limited to property owner and assigned vendor; all views are logged with user, time, and IP And a shareable read-only link (time-bound, signed) can be generated by the owner to resolve disputes
Audit Trail Immutability and Export
Given any order event or ticket state change occurs When the system writes to the timeline Then entries are append-only (no edits/deletes); corrections create a new entry referencing the prior entry And each entry contains actor, event type, UTC timestamp, and normalized payload summary And the ticket timeline can be exported to PDF and JSON including all order-related entries, preserving chronological order with sequence numbers
Exception Handling for Cancellations, Returns, and Partial Fills
Given an order is canceled, partially fulfilled, or a return/refund is issued When the event is received from the supplier or user action Then a timeline entry is appended with event type, reason code, and affected items And ticket state updates accordingly: Canceled→Needs Parts; Partial→Awaiting Parts; Returned-Unresolved→Parts Issue - Follow-up Required And role-appropriate notifications are sent to tenant, owner, and assigned vendor And a follow-up task is auto-created for Returned-Unresolved with next business day due date and link to reorder And refund amount and reference number are captured when provided
Smart Substitution & Compatibility Checks
"As a tenant, I want compatible substitutes suggested when something is out of stock so that I can still complete the repair without waiting."
Description

When selected items are out of stock or delayed, proposes compatible substitutes based on dimensions, thread/type, voltage/battery, and material constraints, highlighting any trade‑offs. Performs basic compatibility validation using structured attributes and prompts the user to confirm fit with quick questions when needed. Clearly labels risky substitutions and offers to defer to vendor dispatch if no safe alternative exists.

Acceptance Criteria
Suggest Safe Substitutes When Item Is Out of Stock or Delayed
Given a selected item has structured attributes (category, dimensions, thread/type, voltage/battery, material) and availability is Out of Stock or ETA >= 3 days When the system searches the catalog for substitutes Then it returns only items that satisfy all mandatory compatibility rules: - electrical specs (voltage and battery size) exactly match - thread/type exactly match or are in the allowed mapping list - dimensions fall within the category-specific tolerance in the compatibility rules - material is permitted per the material-compatibility map And for each returned item, it displays a trade-off summary highlighting attribute differences (Same/Better/Worse) and any impacts And if no items satisfy mandatory rules, it shows “No safe alternative” and an option to dispatch a vendor
Ask Quick Fit-Check Questions When Data Is Insufficient
Given one or more required attributes for compatibility cannot be resolved from catalog data for the selected item or candidates When the user enters the substitution flow Then the system asks up to 3 multiple-choice fit-check questions targeted to the missing attributes (e.g., pipe diameter, thread direction, battery size) And updates candidate substitutes in real time based on answers And if any mandatory attribute remains unknown after the questions, the system does not mark any option as Safe and keeps vendor dispatch available
Clear Risk Labeling and Ordering Controls for Substitutions
Given a candidate substitute is conditionally compatible or has unresolved attributes When the candidate is displayed Then it is labeled “Risky substitution” with a visible rationale And “Add to Cart” is disabled until the user expands risk details and confirms acknowledgment via a checkbox And a “Dispatch a Vendor Instead” option is displayed with equal prominence
Prioritize Tool‑Free Alternatives Among Safe Substitutes
Given multiple Safe substitutes exist When the results are ranked Then tool-free alternatives (requiring no additional tools) are ranked above others and marked with a “No tools needed” badge And at least one tool-free option appears within the top 3 results when available And ranking tie-breakers respect lower total cost and faster delivery
Live Pricing and Delivery Options for Substitutes
Given Safe or Risky substitutes are shown When live pricing and delivery data is requested from vendors Then each displayed price/ETA is refreshed within 10 minutes of current time and fetched within 5 seconds total for the page load And if live data cannot be retrieved, the system shows a clear fallback message and disables one-tap order for affected items
Audit Trail for Substitution Decisions
Given the user orders a substitute or chooses to dispatch a vendor due to no safe alternative When the action is confirmed Then the system records the original item, chosen substitute (if any), attribute comparison matrix, trade-off summary, fit-check answers, risk label, timestamp, and user ID And attaches the record to the repair’s annotated timeline and order history And the record is retrievable via the case detail within 2 clicks

ProofTrack Log

Time‑stamped photo/video checkpoints verify each step was done, automatically compiling a ‘Self‑Fix Timeline.’ The log ties into responsibility rules, so completed steps and evidence reduce disputes and accelerate approvals if escalation is needed.

Requirements

Guided Checkpoint Capture
"As a tenant troubleshooting an issue, I want a simple guided flow that tells me exactly what to capture and confirms it’s saved so that I can prove I completed the steps and get faster approvals."
Description

Provide a step-by-step capture flow within FixFlow’s triage that enforces required photo/video evidence per troubleshooting step. Each checkpoint prompts for specific media, auto-applies server-side timestamps, collects metadata (step ID, user ID, device time, optional geolocation with consent, EXIF), performs basic quality checks (e.g., non-empty, minimum resolution), and queues uploads with offline support and retry. Media is compressed/transcoded client-side when possible, then stored securely and linked to the associated work order step. The UI shows progress, allows retakes, and confirms successful capture, supporting web and PWA with accessibility standards.

Acceptance Criteria
Required Media Enforcement Per Step
- Given a triage step defines required media types and counts, When the user attempts to advance without capturing all required media, Then the Continue action is disabled and an inline message lists each missing item by type and count. - Given a triage step defines required media, When exactly the required media types and counts are captured, Then the step is marked complete and the user can advance. - Given optional media is defined for the step, When optional media is not provided, Then the user can advance without error. - Given the capture UI is opened for a step, When it loads, Then it displays the step title and specific capture guidance text.
Server-Side Timestamping and Metadata Capture
- Given a media item is uploaded, When the server processes it, Then the media record is persisted with serverAssignedAt (UTC), stepId, workOrderId, userId, deviceLocalTime, timezoneOffset, mediaType, mimeType, fileSize, checksum, and exifExtracted status. - Given the user has consented to location for this capture, When the upload is processed, Then latitude, longitude, and accuracy (meters) are stored; otherwise these fields are null and no geolocation is requested for this capture. - Given multiple media items are uploaded for the same step, When the ProofTrack Log is rendered, Then items are ordered by serverAssignedAt ascending.
Client-Side Quality Validation
- Given a photo is selected or captured, When validated client-side, Then it must be non-empty and have minShortestEdge ≥ 720 px; otherwise the user is shown an error and offered Retake/Choose Another. - Given a video is recorded or selected, When validated client-side, Then it must be non-empty and have minDimension ≥ 720 px and meet any step-specified minimum duration; otherwise show error and offer Retake. - Given validation passes, When the user submits, Then the upload begins and the UI shows an Uploading state with progress feedback.
Offline Capture, Queueing, and Auto-Retry
- Given the device is offline at submit time, When the user completes capture, Then the media and its metadata are persisted to encrypted local storage with a queued status and a visible count of queued items. - Given queued uploads exist, When connectivity is restored, Then uploads auto-start in capture order with exponential backoff on failures (retry up to 5 times per item with delays of 2s, 5s, 10s, 30s, 60s). - Given an upload permanently fails with a non-retryable error (HTTP 4xx), When surfaced to the user, Then the item is marked Failed with reason and offers Retry and Retake actions. - Given the app is closed and reopened, When resuming, Then the queue persists and resumes automatically if online.
Client-Side Compression/Transcoding
- Given the browser supports required APIs, When a photo exceeds maxDimension 2048 px on the long edge or fileSize > 4 MB, Then it is compressed to JPEG quality ~0.8 with longEdge ≤ 2048 px before upload; else the original is uploaded. - Given the browser supports MediaRecorder/Transcoder, When a video exceeds 720p or bitrate > 4 Mbps, Then it is transcoded to H.264/AAC MP4 at 720p ≤ 2.5 Mbps before upload; else the original is uploaded. - Given compression/transcoding occurs, When the server receives the file, Then the SHA-256 checksum matches the client-provided checksum and the extracted EXIF/metadata is associated to the media record.
Secure Storage and Work Order Linkage
- Given a media upload completes, When stored, Then it is written to encrypted-at-rest object storage and linked to its workOrderId and stepId with a unique server-generated mediaId. - Given an authorized user views the ProofTrack Log, When media is requested, Then access is via time-limited signed URLs (expiry ≤ 15 minutes) over TLS 1.2+ and only for roles with permission on the work order. - Given an access event occurs, When logged, Then an audit record is created with mediaId, userId, action, timestamp, and IP address.
UX: Progress, Retakes, Confirmation, Accessibility (Web/PWA)
- Given the user is in the capture flow, When viewing the step list, Then a progress indicator shows X/Y steps completed and each step shows captured counts by type. - Given the user reviews a captured item before submission, When selecting Retake, Then the prior item is discarded client-side and replaced upon new capture. - Given an upload succeeds, When the server responds, Then the UI shows a success state with thumbnail/preview and serverAssignedAt within 2 seconds and enables navigation to the next step. - Given a keyboard-only or screen-reader user, When interacting with the capture flow in web or PWA, Then all interactive controls are reachable via keyboard, have accessible names, proper focus order, and meet WCAG 2.1 AA contrast (≥ 4.5:1).
Evidence Integrity & Tamper-Proofing
"As a property owner, I want assurance that the photos and videos are authentic and time-stamped so that I can approve work confidently and avoid disputes."
Description

Ensure authenticity of captured media by hashing files at capture, applying a server-verified timestamp, and generating a cryptographic seal stored with the record. Overlay non-intrusive watermarks (case ID, step ID, server timestamp) on derivatives while preserving originals in immutable storage. Maintain an append-only audit trail for all actions (capture, upload, annotation, share). Detect and flag any post-capture modifications with versioning and verification badges in the UI. Provide an API and internal tooling to verify integrity during reviews and exports.

Acceptance Criteria
Upload Seal Generation and Verification on Media Capture
Given a user captures media via FixFlow capture component When the media is saved client-side Then a SHA-256 hash is computed on-device and stored with the media metadata Given the captured media is uploaded (online or from offline queue) When the server receives the bytes and client-provided hash Then the server recomputes SHA-256 and must match the client hash; otherwise the upload is rejected with error code "HashMismatch" and no record is created Given hashes match When the server records the evidence Then a server-verified timestamp is applied and a cryptographic seal (containing mediaHash, size, mimeType, caseId, stepId, serverTimestamp, keyId, algorithm) is generated by signing with the server private key and stored with the record Given a cryptographic seal exists When the seal is verified using the published public key Then the signature validation must succeed and the seal fields must match the stored media and metadata Given an offline capture with a stale device clock When uploaded later Then the seal timestamp reflects server receipt time, and the device capture time is preserved as non-authoritative metadata
Immutable Originals with Watermarked Derivatives
Given an original media file is accepted When it is stored Then it is written to immutable storage with WORM/retention enabled and cannot be overwritten or deleted by application users; attempts return 403 and are logged Given derivatives are generated (preview, resized, transcoded) When rendering completes Then each derivative includes a non-intrusive watermark containing caseId, stepId, and serverTimestamp positioned bottom-right with 5% margin and 60% opacity, legible at all common resolutions Given derivatives exist When comparing hashes Then original bytes hash equals the sealed hash; derivative hashes differ and are versioned separately without altering the original Given a watermark template update occurs When derivatives are re-rendered Then derivative version is incremented and audit event recorded; the original remains unchanged
Append-Only Audit Trail with Cryptographic Linking
Given any action on evidence (capture, upload, annotate, share) When the action is performed Then an audit event is appended recording actorId, role, actionType, mediaId, timestamp (server), and prevEventHash, producing a hash-linked chain Given the audit log exists When attempting to edit or delete an event Then the system disallows mutation; the API returns 405 and the attempt is logged as a security event Given an integrity check is requested When the system validates the audit chain Then every event's hash and prevEventHash must form an unbroken chain ending at the latest event; failures mark the media as "Audit Chain Invalid" Given an authorized reviewer requests audit events When fetching via API Then events are returned in chronological order with pagination and signed response envelope
UI Verification Badges and Tamper Detection Workflow
Given a media record with valid seal and matching stored bytes When the record is viewed in the UI Then a "Verified" badge is displayed with tooltip showing algorithm, timestamp, and keyId Given any mismatch (hash mismatch, invalid seal signature, broken audit chain) When the record is viewed Then a "Tampered" banner and "Verification Failed" badge are shown, details are accessible, and escalation actions are enabled Given a new derivative version is generated When viewing version history Then the UI lists versions with version number, reason, timestamp, and actor; the original is labeled "Immutable Original" Given annotations or metadata are edited When verification runs Then verification status remains "Verified" (media hash unchanged) and an audit event records the metadata change
Integrity Verification API and Internal Review Tool
Given an integrity verification request via API When GET /evidence/{id}/verify is called Then the response returns 200 with fields: overallStatus, recomputedHash, sealValid, auditChainValid, issues[], and completes within 500 ms for single-item requests Given a batch verification request When POST /evidence/verify with up to 200 IDs is called Then the API processes asynchronously and provides a jobId with progress and final results downloadable within SLA Given an internal reviewer has a media file and its seal JSON When using the internal verification tool offline with the published public key Then the tool reports pass/fail for signature, hash match, and watermark presence, and outputs a signed verification report Given an invalid seal or mismatched file is provided When verification runs Then the API/tool returns deterministic error codes (e.g., SealSignatureInvalid, HashMismatch, AuditChainInvalid) suitable for automation
Exportable Evidence Package with Offline Verifiability
Given a case export is requested including ProofTrack Log When the export is generated Then a ZIP is produced containing originals, derivatives, seal JSON files, audit trail JSON, a manifest with SHA-256 checksums for all files, and the public key bundle Given the export package is created When the manifest is validated by recomputing checksums Then all files must match; otherwise the export is flagged "Verification Failed" and delivery is blocked Given a third party reviews the export offline When they run the included verification script or follow documented steps Then they can validate seal signatures, audit chain integrity, and watermark presence without contacting FixFlow services Given an export includes any item with failed verification When the export is requested Then the system prevents export or includes a clear failure report, and the UI surfaces remediation steps
Auto Timeline Builder & Annotations
"As a property manager, I want a clear, shareable timeline of each step with annotated evidence so that I can quickly review progress and communicate with owners or vendors."
Description

Automatically compile captured checkpoints into a chronological Self‑Fix Timeline that pairs each step with its media, metadata, and completion status. Enable inline annotations (arrows, highlights, text notes) and step-level comments, with versions tracked in the audit log. Provide read-only share links and exportable PDF/ZIP packages that include media thumbnails, metadata, and verification badges. Support filters by role and step type, and show timeline completeness indicators and next required actions. Integrate the timeline view into the work order detail for tenants, owners, and vendors.

Acceptance Criteria
Chronological Self‑Fix Timeline Assembly
Given a work order has multiple captured checkpoints with timestamps When the timeline is opened Then steps are ordered in ascending chronological order by capture timestamp And each step displays its completion status (Complete, Pending, Skipped) per workflow rules And each step is paired with its associated media (photo/video) and metadata (capture timestamp, uploader role, step name, file type) And the timeline loads within 2 seconds for up to 50 checkpoints on a broadband connection
Inline Media Annotations With Versioning
Given a user with annotate permission opens a step’s media When the user adds annotations (arrows, highlights, text notes) and saves Then a new non-destructive annotation version is created (v1, v2, ...) And the audit log records actor, timestamp, version number, and change summary And users can view and restore any previous annotation version And annotations render identically in the in-app view, read-only share links, and PDF exports
Step-Level Comments and Audit Trail
Given a step in the timeline When a tenant, owner, or vendor posts, edits, or deletes a comment Then each comment displays author name, role, and timestamp, and is linked to the step And create/update/delete events are recorded in the audit log with actor, timestamp, and before/after text And comments appear under the corresponding step in PDF export And commenting does not alter the step’s completion status
Read‑Only Share Link Generation
Given an authorized user selects Create Share Link on a work order timeline When the link is generated Then the link grants read-only access (no edit, annotate, or delete actions) And the link contains an unguessable token (>=128-bit entropy) And the issuer can set an expiration time and revoke the link at any time And link accesses are logged with timestamp and user agent And the shared view includes media thumbnails, metadata, and verification badges identical to the in-app view
Exportable PDF/ZIP Package With Verification
Given an authorized user selects Export on the timeline When PDF is chosen Then a single PDF is generated with chronological steps, media thumbnails, key metadata (capture timestamp, uploader role, step name, completion status), and verification badges per step And when ZIP is chosen Then a ZIP is generated containing the PDF, original-resolution media files organized by step, and a metadata manifest (JSON or CSV) And exports complete within 60 seconds for timelines up to 200 media items totaling 2 GB And exported files pass checksum validation and remain downloadable for 7 days
Role and Step‑Type Filters With Completeness Indicator
Given a timeline contains steps across roles and step types When the user applies filters by role and step type Then only matching steps are displayed without modifying underlying data And the completeness indicator updates to show percentage complete for both the filtered subset and overall timeline And the UI highlights the next required action, responsible role, and step label And clearing filters restores the full unfiltered timeline
Embedded Timeline in Work Order Detail by Role
Given a tenant, owner, or vendor opens a work order detail When the Timeline view is selected Then the timeline renders in-place without navigating away from the work order And content visibility and actions conform to role permissions (e.g., read-only for share recipients, annotate only for permitted roles) And initial render completes within 2 seconds for up to 50 checkpoints And navigation back to other work order sections preserves the timeline state on return
Responsibility Rules Engine Integration
"As a landlord, I want the system to apply responsibility rules based on completed evidence so that approvals and cost responsibility are decided consistently and quickly."
Description

Map checkpoints to configurable responsibility rules (tenant/owner/vendor/warranty) and evaluate them as evidence is completed. Block escalations that lack required proof, and auto-approve escalations when thresholds are met. Surface decision rationales in the timeline (which rules passed/failed) and update cost-responsibility flags on the work order. Provide an admin UI to define rules by property type, issue category, and jurisdiction, with test cases and versioning. Emit events for downstream billing and approvals.

Acceptance Criteria
Context-based Rule Set Selection on Work Order Creation
Given a new work order with property_type, issue_category, and jurisdiction identified When the rules engine is invoked for the work order Then it selects the highest-priority published rule set matching all three dimensions, else falls back to the default rule set And records rule_set_id and rule_set_version on the work order metadata And appends a ProofTrack timeline entry indicating the selected rule set and selection rationale
Real-Time Rule Re-evaluation on Checkpoint Completion
Given a work order with a selected rule set and outstanding required checkpoints And a user completes a checkpoint by submitting required evidence When the evidence is saved Then the rules engine re-evaluates the rule set against current evidence And updates the missing_evidence list, escalation eligibility state, and tentative responsibility outcome And appends a new ProofTrack timeline entry summarizing pass/fail deltas since the last evaluation
Blocking Escalation Without Required Evidence
Given a work order whose selected rule set defines required checkpoints for tenant self-fix And one or more required checkpoints are incomplete or lack valid media When the tenant attempts to escalate to vendor dispatch Then the escalation action is blocked And the UI displays a list of missing checkpoints with titles and acceptance notes And the ProofTrack timeline logs a failed evaluation entry with rule names and reasons
Auto-Approval of Escalation When Threshold Met
Given a work order with a selected rule set that defines auto-approval thresholds for escalation And all required checkpoints are completed with valid, time-stamped photo/video evidence linked to checkpoints And all validations defined by the rule set pass When the tenant requests escalation Then the escalation is auto-approved without manual review And vendor dispatch is triggered per routing policy And the ProofTrack timeline logs a passed evaluation entry with decision rationale
Update Cost-Responsibility Flags on Work Order
Given a rule evaluation produces a responsibility outcome (tenant, owner, vendor, warranty) When the decision is recorded Then the work order cost_responsibility field is updated to the decided party And any prior value is superseded with an audit trail including previous value, timestamp, and rule_set_version And the updated responsibility is visible via API and UI
Admin UI for Rule Authoring, Testing, and Versioning
Given an admin has permission to manage responsibility rules When they create or edit a rule set scoped by property_type, issue_category, and jurisdiction Then they can define rules and attach test cases with inputs and expected outcomes And they can run tests and view pass/fail per case before publishing And publishing creates an immutable new version and archives prior versions And new evaluations use only the latest published version from the time of publish forward
Event Emission for Billing and Approvals
Given a rule decision is made or an escalation state changes When the outcome is persisted Then an event is emitted to the event bus with payload fields: event_id, work_order_id, rule_set_id, rule_set_version, decision, responsibility_party, escalation_state, missing_evidence (if any), and timestamp And events are idempotent via event_id so downstream consumers can safely process duplicates And failures to deliver are retried with backoff and surfaced to monitoring
Role-Based Access & Privacy Controls
"As a tenant, I want control over what evidence is shared and with whom so that my privacy is protected while still resolving the issue."
Description

Implement fine-grained permissions for timeline visibility and actions by role (tenant, owner, vendor, manager). Allow redaction tools (blur faces/PII, hide room views) and removal of sensitive EXIF/location data from shared exports. Support consent prompts for location capture, configurable retention policies per role and property, and audit logs of who viewed/downloaded media. Ensure shared links have expiry, scopes, and revocation, aligning with GDPR/CCPA data subject rights.

Acceptance Criteria
Role-Based Timeline Visibility by User Type
Given a tenant is logged in and belongs to Property A and Unit 101 When they open the ProofTrack Log Then only timeline entries for Unit 101 in Property A are visible And entries from any other unit or property are not visible Given a vendor is assigned to Work Order X When the vendor opens the ProofTrack Log Then only timeline entries linked to Work Order X are visible And unrelated media is hidden Given an owner of Property C is logged in When the owner views the ProofTrack Log Then timelines for all units in Property C are visible And tenant PII fields are masked per policy by default Given a manager role with portfolio P When the manager views the ProofTrack Log Then all timelines within portfolio P are visible
Role-Based Action Permissions on Timeline
Given a tenant views their timeline When interacting with entries Then the tenant can upload media and add notes And cannot delete entries, redact media, or change step status (returns 403 and is logged) Given a vendor views an assigned work order timeline When interacting with entries Then the vendor can upload media, annotate, and mark assigned steps complete And cannot view audit logs, configure links, or alter retention (returns 403 and is logged) Given an owner views a property timeline Then the owner can view and comment And cannot redact, delete, or change step status (returns 403 and is logged) Given a manager views any managed timeline Then the manager can redact media, approve/reject steps, manage shared links, and adjust role permissions within policy
PII Redaction and Hidden Room Views Persist to Exports
Given an image contains a face and visible address text When a manager applies the blur tool to those regions and saves Then the regions appear redacted in the timeline viewer and thumbnails for all roles without override permission And the redaction is non-destructive and automatically applied to all future views and exports Given a video is redacted by frame range When exporting the timeline Then the redacted segments remain redacted in the exported file And no unredacted preview or thumbnail is served to unauthorized roles Given Hide room view is enabled for a step When a tenant or vendor without override permission views the step Then the media is replaced with a placeholder and reason label
Location Consent and EXIF Metadata Stripping
Given a user captures media via the app for the first time When the app requests location permissions Then a consent prompt explains location capture with Allow and Don't Allow options And Don't Allow is the default Given the user selects Don't Allow When media is saved Then no GPS EXIF or precise location data is stored with the media Given any export is generated When files are prepared for download or share Then all EXIF metadata and precise GPS coordinates are stripped And filenames exclude location identifiers Given location consent is granted When a manager views the internal timeline Then location is visible to manager role only per policy
Shared Link Scope, Expiry, and Revocation Enforcement
Given a manager creates a shared link for Work Order Y When scope is set to timeline items A and B, expiry to a future date, and permission to view-only Then the link grants access only to items A and B until the expiry date and time And download actions are disabled Given a shared link is expired or explicitly revoked When any recipient attempts access Then an expired or revoked page is shown And no media content or metadata is served Given a manager revokes a link When 60 seconds have elapsed Then the link no longer grants access across all devices and sessions
Comprehensive Media View/Download Audit Logging
Given any user or shared-link recipient views or downloads a media item When the request is processed Then an audit entry records actor (user ID or link ID), role (if applicable), action (view or download), item ID, timestamp (UTC), and request IP And the entry is immutable and visible to managers in the audit view Given the manager filters the audit view When applying property, date range, actor, and action filters Then the results reflect the filters and can be exported as CSV Given an unauthorized access attempt occurs When a 403 or 401 response is returned Then a failed access audit record is stored with the same fields
Data Lifecycle: Retention Policies and Data Subject Rights
Given property-level retention policies per role are configured (e.g., tenant uploads 12 months; vendor uploads 24 months) When a media item's retention period elapses Then the system queues deletion or anonymization within 24 hours And executes it and records the event in the audit log And items under legal hold are excluded until the hold is cleared Given a verified data subject access request is received for a tenant When the manager initiates export Then the system generates the subject's personal data package within 30 days And excludes other parties' PII and removes EXIF or location unless consent and policy allow Given a verified data subject deletion request is approved When the request is executed Then the subject's personal data is deleted or anonymized across primary storage, derivatives, indexes, and caches within 30 days And completion is logged with a timestamp and scope
Smart Notifications & SLA Escalations
"As a small property manager, I want automatic alerts and escalations with the compiled timeline so that I don’t have to manually coordinate and can meet SLAs."
Description

Send role-aware notifications when checkpoints are completed, when timelines reach predefined completeness thresholds, or when SLAs are at risk. Include deep links to the relevant timeline view and the compiled evidence package for vendors. Support channels (in-app, email, SMS), deduplication, quiet hours, and localization. Trigger auto-dispatch recommendations when evidence indicates on-site work is needed, attaching the timeline to reduce back-and-forth and improve first-visit resolution.

Acceptance Criteria
Role-Aware Checkpoint Completion Notifications
Given a maintenance checkpoint in a ProofTrack Log is marked Complete and persisted When the event is processed Then send notifications within 60 seconds only to configured roles for that checkpoint (tenant, owner, assigned vendor, manager) and suppress for non-configured roles Given recipients have channel preferences When delivering notifications Then use each recipient’s primary channel and record delivery metadata (channel, timestamp, message ID) Given duplicate triggers occur for the same checkpoint within a short interval When within a 5-minute deduplication window per recipient per event Then deliver at most one notification and log suppressed duplicates
Timeline Completeness Milestone Alerts
Given a job’s timeline completeness reaches a configured threshold (e.g., 50%, 75%, 100%) When the threshold state is crossed Then send a milestone alert within 60 seconds and include current percentage and remaining required checkpoints count Given a threshold is crossed, later recedes, and is crossed again When the state re-crosses the threshold Then send a new alert and mark the previous as superseded Given a milestone alert is sent When recording the event Then link to the timeline summary view via deep link and store an audit entry
SLA Risk Forecasting and Escalation Tiers
Given a job has SLA targets for response and/or resolution When elapsed time reaches 75% of any active target without completion Then trigger Level 1 warning to assigned vendor and manager via in-app and email and mark job status as “SLA Warning” Given elapsed time reaches 100% of an active target without completion When Level 2 escalation criteria are met Then notify manager and owner with SMS fallback (if consented) and mark job status as “At Risk” Given elapsed time reaches 125% without completion When Level 3 escalation criteria are met Then notify backup vendor pool and generate an auto-dispatch recommendation Given an escalated stage is completed When SLA state changes to Met Then auto-resolve active escalations and stop escalation timers
Deep Link and Evidence Package Integrity
Given a notification contains a deep link to a timeline or checkpoint When an authenticated, authorized recipient opens it Then the app opens the exact view/anchor within 3 seconds and renders associated media Given a vendor without an account opens a tokenized link When the token is valid Then provide one-time access only to the job’s evidence package; expire the token after first use or 24 hours, whichever occurs first Given an expired or unauthorized link is accessed When the request is evaluated Then return a 403 with a “Request Access” action and log the attempt Given a vendor brief is attached When generating the evidence package Then include all checkpoint photos/videos, annotations, and timestamps with a PDF summary; if package exceeds 50 MB, include a secure download manifest
Multi-Channel Delivery, Preferences, and Fallbacks
Given a notification is ready to send and recipient has channel preferences When delivering Then send via the primary channel and record delivery outcome; on failure within 2 minutes, retry via the next consented channel Given SMS consent is absent for a recipient When selecting channels Then do not send via SMS and record a compliance reason Given the same event targets a recipient across multiple channels When within a 5-minute deduplication window Then deliver at most one notification and surface the same item in the in-app notification center with synchronized read/unread state within 30 seconds of open
Quiet Hours and Snooze Controls
Given organization-level quiet hours are configured (default 21:00–08:00 local time) When a non-critical notification is generated during quiet hours Then queue it for delivery at the end of quiet hours and preserve the original event timestamp Given a user snoozes notifications for a specific job When events occur during the snooze period Then suppress non-critical notifications and mark them in-app as muted Given a Level 2 or higher SLA escalation occurs during quiet hours When sending to manager/owner Then bypass quiet hours and deliver immediately with a “Critical” label Given multiple queued notifications become deliverable after quiet hours When sending Then deliver a single digest per recipient per job containing a summary and deep links
Localization and Content Personalization
Given a recipient locale is set (e.g., en-US, es-ES) When rendering notification content Then localize templates, date/time formats, numbers, and role titles with fallback to en-US if a translation is missing Given templates include variables (property, unit, checkpoint, SLA times) When generating a message Then populate all required placeholders or fail the send and log a template error Given SMS messages have segment limits When localizing to GSM-7 or UCS-2 Then constrain content to ≤3 segments; if longer, send a shortened version preserving critical fields and a link

LiveCoach Assist

On‑demand 5‑minute video help from a vetted pro who can draw on screen to guide tricky steps. If the attempt fails, the pro leaves short diagnostic notes and a likely cause, enabling smarter, faster vendor dispatch without repeating basic troubleshooting.

Requirements

One-tap Coach Connect
"As a tenant with a broken appliance, I want to be connected to a qualified coach within seconds so that I can get immediate guidance without waiting for a vendor visit."
Description

Enables on-demand, single-tap session requests from the issue screen, runs device and network checks, matches the tenant to an available vetted coach by skill, language, and time zone, and connects within a target SLA of 30 seconds. Displays live ETA, queue status, and a visible five-minute session timer with configurable extension rules. Provides automatic fallback to a scheduled slot or assisted chat if no coach is available within SLA. Prefills session context from FixFlow intake (unit, issue category, photos, tenant notes) and logs connection metrics to support continuous optimization. Supports web and mobile experiences with push/SMS notifications for join and reconnect.

Acceptance Criteria
Single-Tap Request from Issue Screen
- Given a tenant is on an eligible issue screen with LiveCoach available, When the tenant taps "Get Live Help" once, Then a session request is created without additional confirmations and the CTA shows a loading state within 300 ms. - Given a session request is in-flight, When the tenant taps the CTA again, Then no duplicate request is created and the UI remains idempotent. - Given the tenant is not authenticated or lacks permissions, When they tap the CTA, Then the user is prompted to authenticate or receives a clear error and no session request is created. - Given feature flags or plan limits disable LiveCoach for the property, When viewing the issue screen, Then the CTA is hidden or disabled with an explanatory tooltip. - Given web and mobile views, When loading the issue screen, Then the CTA placement and accessible labels are consistent and meet WCAG 2.1 AA for focus order and screen reader announcements.
Device and Network Preflight Checks
- Given a session request begins, When preflight runs, Then OS/app version, camera/mic permissions, NAT type, bandwidth (≥300 kbps up), and latency (≤250 ms RTT) are checked within 2 seconds. - Given all checks meet minimum thresholds, When preflight completes, Then the flow proceeds to coach matching automatically. - Given one or more checks fail, When preflight completes, Then the user sees specific remediation steps with inline permission prompts where supported and a visible "Retry checks" control. - Given checks cannot pass after 2 retries or 60 seconds total, When the user continues, Then the system offers assisted chat or scheduling options without losing session context.
Coach Matching by Skill, Language, and Time Zone
- Given a valid request, When matching executes, Then a coach is selected whose skills include the issue category, language matches the tenant preference, and time zone is within ±3 hours of the tenant unless overridden by policy. - Given multiple candidates meet constraints, When selecting a coach, Then the candidate with earliest availability and highest quality score within policy is chosen. - Given no candidate meets all constraints, When constraints are relaxed, Then time zone is relaxed first, followed by secondary skill tags, before declaring no match. - Given 20 seconds of matching elapse without a confirmed coach, When the timer hits 20 seconds, Then the fallback path is prepared while matching continues until SLA expiry.
Connection SLA with Live ETA, Queue Status, and Notifications
- Given matching starts, When ETA is computed, Then the UI displays live ETA and queue position and refreshes at least every 3 seconds until connected or SLA expires. - Given a coach accepts, When connection is ready, Then the session starts within 30 seconds of the initial tap under normal service conditions, and rolling 24-hour P95 connect time is ≤30 seconds. - Given the tenant navigates away or app is backgrounded, When the session becomes ready, Then a push and/or SMS notification with a deep link to join is sent immediately, respecting user notification consents. - Given connectivity is lost during connection, When network returns within 60 seconds, Then the user sees a "Reconnect" prompt and receives a join notification if the app is backgrounded.
Five-Minute Session Timer with Extension Rules
- Given a session connects, When the video view loads, Then a visible five-minute countdown timer starts at 5:00 and is visible to both tenant and coach throughout the session. - Given 60 seconds remain, When the timer hits 1:00, Then an extension prompt appears per configuration and indicates remaining extensions available. - Given extensions are allowed and both parties consent, When "Extend" is tapped, Then the session extends by the configured increment (e.g., +3 minutes) up to the plan limit and the timer updates accordingly. - Given time expires without extension, When the timer reaches 0:00, Then the session ends automatically with a clear end state and post-session options.
Automatic Fallback to Schedule or Assisted Chat
- Given no coach is available within the 30-second SLA, When SLA expires, Then the user is offered to schedule the next available slot (show at least three options in tenant time zone) or start assisted chat; a default is auto-selected after 10 seconds with the ability to override. - Given the user selects schedule, When confirmation is made, Then a booking is created, calendar details are shown, and confirmation is sent via push/SMS/email per preferences. - Given the user selects assisted chat, When chat opens, Then prior intake details are prefilled and the user is informed a live coach was unavailable. - Given fallback is triggered, When the choice is confirmed, Then any outstanding coach invitations are canceled and the user is returned to the issue record upon completion.
Context Prefill and Connection Metrics Logging
- Given an intake exists for the issue, When a live session or fallback is initiated, Then unit ID, issue category, photos, and tenant notes are automatically attached to the session and visible to the coach. - Given the session lifecycle progresses, When events occur, Then metrics are logged: tap timestamp, preflight duration, match duration, connect time, SLA compliance flag, retries, device type, platform, locale, and error codes. - Given privacy requirements apply, When data is stored, Then PII is redacted per policy while preserving analytics fields needed for optimization. - Given the session ends, When notes are saved, Then the coach’s diagnostic notes and any annotated photo-timeline are linked to the original issue record for auditability.
Live AR On-Screen Guidance
"As a coach, I want to draw and point on the tenant’s video feed so that I can guide them through tricky steps clearly and safely."
Description

Delivers low-latency video assistance with bidirectional drawing and pointer overlays so coaches can guide tenants through precise steps. Includes freeze-frame, snapshot capture with annotations, numbered callouts, undo/clear, camera switch, flashlight toggle, and audio-only fallback with step-by-step snapshots for poor networks. Adapts quality to bandwidth, targets sub-300ms round-trip latency on 4G, and provides safety prompts for hazardous steps. Works in browser and mobile without requiring app installs, integrates with device media permissions, and saves annotated frames to the case photo-timeline for auditable records.

Acceptance Criteria
Sub‑300ms Live Video Latency on 4G
Given a LiveCoach Assist session established over a 4G network profile (10 Mbps down, 5 Mbps up, 50±30 ms RTT, 1% packet loss, 0–50 ms jitter) When continuous two‑way video, audio, and 20 draw events per minute are active for 5 minutes Then WebRTC getStats reports end‑to‑end media round‑trip latency ≤ 300 ms for ≥ 90% of samples and ≤ 400 ms at the 95th percentile, media uptime ≥ 99%, and ≤ 1 reconnection during the interval.
Real‑Time Bidirectional Drawing and Pointer Overlays
Given two participants are connected with live video When either participant draws, places numbered callouts, uses a laser pointer, taps Undo, or taps Clear Then all new strokes, callouts, and pointer updates render on the peer device with median overlay latency ≤ 150 ms and 95th percentile ≤ 300 ms; numbering increments sequentially and is consistent on both devices; Undo removes only the author's last action; Clear removes all overlays for both after confirmation; and overlays do not block essential session controls.
Freeze‑Frame and Annotated Snapshot Capture to Case Timeline
Given an active session with video When either participant taps Freeze Then the current frame pauses for both participants and becomes annotate‑able without ending the call. When Snapshot is taken from a frozen or live frame Then a still image including visible overlays is saved to the linked case photo‑timeline with metadata (caseId, participantId, UTC timestamp, step label), appears in the timeline within 3 seconds, is immutable, and renders at ≥ 720p when the source camera supports ≥ 720p.
Audio‑Only Fallback with Step‑by‑Step Snapshots on Poor Networks
Given an active session experiences degraded network (sustained uplink < 200 kbps or packet loss > 5% for ≥ 10 seconds) When fallback is offered and accepted by either participant Then the session transitions to audio‑only within 2 seconds without dropping the call, audio quality maintains MOS ≥ 3.5, and the UI enables snapshot capture with annotation and saving to the case photo‑timeline. When network recovers (sustained uplink ≥ 1 Mbps and loss ≤ 2% for 15 seconds) Then either participant can resume video within 3 seconds without creating a new session.
Browser and Mobile Web Support with Media Permissions
Given a tenant or coach opens a session join link in a supported browser (iOS Safari 16+, Android Chrome 110+, desktop Chrome/Edge/Safari/Firefox latest two versions) When permissions are requested for camera and microphone Then no app install or app store redirect is presented, prompts appear once per session, denial shows retry guidance, and granting permissions starts local media within 2 seconds. When switching cameras or toggling the flashlight Then the active camera switches within 2 seconds without ending the session, the flashlight control is shown only when the active camera supports torch and changes state within 1 second, and if unsupported the control is disabled with an explanatory tooltip.
Safety Prompts for Hazardous Steps with Auditable Acknowledgment
Given the coach selects or types a step labeled as hazardous (e.g., electricity, gas, ladder) When the step is issued to the tenant Then a safety prompt modal displays within 500 ms with clear instructions, requires explicit acknowledgment (I Understand) or Cancel, blocks proceeding until acknowledged, and logs the prompt text, responder identity, choice, and UTC timestamp to the case timeline.
Adaptive Quality to Bandwidth Changes Without Session Drop
Given bandwidth fluctuates between 0.2 Mbps and 5 Mbps during a session When conditions worsen or improve Then video bitrate, resolution, and frame rate adapt within 2 seconds of change; total rebuffering time is ≤ 2% of call duration; audio continuity is maintained for ≥ 99% of call time; the session remains connected without a hard drop; and a visible quality indicator updates within 1 second of adaptation.
Structured Diagnostic Summary
"As a property manager, I want a concise, structured diagnostic note after a failed assist so that vendors arrive prepared and don’t repeat basic troubleshooting."
Description

Adds a required post-session form for coaches capturing attempt outcome, steps completed, likely cause with confidence, equipment details when available, parts/tools likely needed, safety or risk notes, and next recommended action. Automatically attaches timestamps and annotated images to the unit’s photo-timeline and marks troubleshooting tasks as completed to prevent duplication. Enforces submission before session close, supports quick-pick templates for common issues, and exposes the summary to tenants, owners, and vendors with role-based redaction as needed.

Acceptance Criteria
Block Session Close Until Summary Submitted
Given a coach is in an active LiveCoach Assist session When the coach attempts to end the session without submitting the Diagnostic Summary Then the system blocks session closure and displays a required-summary prompt And when the coach submits a valid Diagnostic Summary Then the session ends successfully and is timestamped as closed And the summary record is linked to the session and maintenance ticket
Structured Fields Capture and Validation
Given the Diagnostic Summary form is open Then Outcome (enum: Success, Partial, Failed), Likely Cause (10–280 chars), Confidence (0–100%), Steps Completed (multi-select), and Next Recommended Action (enum: Dispatch Vendor, Order Parts, Monitor, Retry With Tenant) are required before submission And Equipment Details (make/model/serial) and Parts/Tools Likely Needed are optional but accepted if provided When Confidence is entered outside 0–100% Then inline validation prevents submission and highlights the field with an error message When the form is submitted with all required fields valid Then the submission succeeds and a summary ID is generated
Auto-Attach Timeline Artifacts
Given a Diagnostic Summary is submitted for ticket T and unit U Then within 5 seconds the system appends the summary, session start/end timestamps, and all annotated images to U's photo-timeline And each image retains its on-screen annotations and per-annotation timestamps And the timeline entry is immutable and audit-logged with coach ID, submission time, and checksum
Troubleshooting Tasks Auto-Completion
Given ticket T includes a predefined troubleshooting checklist And the coach marks steps X, Y, Z as completed in the Diagnostic Summary When the summary is submitted Then the corresponding checklist items in T are set to Done with completion timestamps and coach ID And future workflows suppress duplicate prompts for X, Y, Z for tenant, owner, and vendor portals
Quick-Pick Templates for Common Issues
Given the coach opens the Quick-Pick templates list When the coach selects a template (e.g., "No Heat - Furnace") Then the form pre-fills Steps Completed (suggested), Likely Cause (draft), Next Recommended Action (draft), and Parts/Tools (draft) And all prefilled values remain editable prior to submission And at least 10 templates are available and searchable with type-ahead returning results in <200 ms at the 90th percentile
Role-Based Redaction and Exposure
Given a Diagnostic Summary exists for a ticket When viewed by a Tenant Then the view shows Outcome, Steps Completed, Next Recommended Action, timestamps, and annotated images, and hides fields/notes flagged Internal-Only When viewed by a Vendor Then the view shows Outcome, Steps Completed, Likely Cause, Confidence, Equipment Details, Parts/Tools, Safety/Risk Notes, Next Recommended Action, and annotated images, and redacts tenant PII (name, phone, email, access codes) When viewed by an Owner Then the view shows all fields except tenant PII And redaction is enforced server-side (API omits redacted fields) and is consistent with UI rendering
Smart Escalation & Dispatch Handoff
"As a property manager, I want failed assists to auto-create a pre-filled dispatch ticket so that work orders move faster with less admin."
Description

Converts unsuccessful assists into ready-to-dispatch work orders pre-filled with diagnostics, photos, parts list, and access instructions, automatically routing to the correct trade and vendor pool using FixFlow triage rules. Applies SLAs and cost ceilings, suppresses repetitive troubleshooting in vendor instructions, and selects preferred vendors when defined. Sends notifications to stakeholders, proposes appointment windows based on tenant availability, and syncs all updates back to the case. Offers webhooks/APIs for external vendor platforms to ingest the handoff payload.

Acceptance Criteria
Auto-Conversion to Dispatchable Work Order
Given a LiveCoach Assist session is marked unsuccessful and linked to a case with tenant, property, and triage data When Smart Escalation is triggered Then a new work order with a unique workOrderId is created and linked to the originating case And the work order contains non-empty: diagnostics summary (from pro notes), annotated photo URLs with timestamps, parts list (name/description, quantity, SKU if provided), access instructions, tenant contact, property address, and safety flags And vendor instructions include the problem summary and results of attempted steps but exclude troubleshooting steps already completed during the assist And the work order status is set to Ready to Dispatch
Trade and Vendor Pool Routing with Preferred Vendor & Fallback
Given a work order is Ready to Dispatch and triage has identified a problem type When routing runs using FixFlow triage rules Then the correct trade is assigned based on the problem type and property location And the eligible vendor pool is filtered by trade, coverage area, credential status, and availability And if a preferred vendor exists for the trade/property and can meet the SLA, that vendor is selected first And if no preferred vendor is available, the system selects the next ranked vendor from the pool; if none meet criteria, the work order is flagged for manual review and ops are notified
SLA and Cost Ceiling Enforcement
Given SLA targets and a cost ceiling are defined via owner/property rules When a dispatch offer is generated Then response-time and arrival-time targets are computed from the work order creation timestamp in the property time zone And the cost ceiling is included in the vendor offer and instructions And if a pre-visit estimate exceeds the ceiling, owner approval is required before firm scheduling and the vendor is blocked from confirming beyond a tentative hold And SLA breaches trigger alerts to stakeholders and are logged on the case timeline
Appointment Window Proposal and Confirmation
Given tenant availability windows exist on the case and a vendor candidate is selected When proposing times Then up to three appointment windows are generated that intersect tenant availability and vendor service hours, displayed in the property time zone And the tenant can confirm one window or request alternatives And upon confirmation, the appointment is committed on the work order and sent to the vendor And scheduling conflicts are prevented; conflicting bookings return an error and require a new selection
Stakeholder Notifications and Case Sync
Given a work order is created or its state changes (routing, vendor accepted, appointment confirmed, job completed) When the event occurs Then notifications are sent to tenant, owner/manager, and selected vendor via configured channels (email, SMS, push) within 2 minutes And each notification includes caseId, workOrderId, current status, next required action, and a portal link And all changes, notes, photos, and appointment updates appear on the case timeline within 60 seconds with actor and timestamp metadata And notification delivery failures are retried up to 3 times with exponential backoff and surfaced as alerts on the case
Webhook/API Handoff Payload Delivery and Acknowledgment
Given an external vendor platform has registered a webhook endpoint and secret When a work order becomes Ready to Dispatch or receives material updates (status, appointment, cost ceiling) Then the system POSTs a JSON payload containing caseId, workOrderId, trade, diagnostics summary, annotated photo URLs, parts list, access instructions, SLA targets, cost ceiling, tenant/property contact, and appointment details And the request includes an HMAC SHA-256 signature header and an idempotency key And on 2xx response, delivery is marked Delivered; on 429/5xx, retry up to 5 times with exponential backoff; on 4xx, mark Failed and alert ops And a secured GET API allows retrieval of the same payload by workOrderId using OAuth 2.0 access control
Consent, Privacy & Recording Controls
"As a tenant, I want clear consent and privacy options for video and recording so that I feel safe using LiveCoach."
Description

Implements explicit consent flows for camera, microphone, and optional recording with clear explanations of data use and retention. Defaults recording to off, provides unmistakable recording indicators, and enforces role-based permissions. Applies automatic face/address blurring to snapshots, encrypts media in transit and at rest, and honors jurisdiction-specific retention and deletion policies. Maintains detailed audit logs of access and changes and surfaces privacy settings within the session UI for transparency.

Acceptance Criteria
First-Time Consent & In-Session Privacy Controls
Given a first-time participant joins a LiveCoach Assist session, When the join flow loads, Then present separate consent prompts for camera, microphone, and optional recording with plain-language data use and retention summaries, and block media streaming until required consents are granted or a non-streaming option is chosen. Given the consent prompts are displayed, When the user selects "Learn more", Then show details of purposes, storage, retention by jurisdiction, withdrawal steps, and support contact within a modal. Given the session UI is active, When the Privacy panel icon is tapped/clicked, Then open within 300 ms and display current consents and controls to revoke camera/mic immediately. Given a participant revokes camera or mic consent mid-session, When they toggle off in the Privacy panel, Then stop the respective stream within 500 ms, update UI state, and notify other participants that the stream was disabled.
Recording Opt-In, Toggle, and Indicators/Notifications
Given a new session starts, Then recording is OFF by default and the record control remains disabled until required consent is collected. Given a permitted user attempts to start recording, When they click "Start Recording", Then prompt all required participants for explicit recording consent and do not begin recording until required consents are obtained. Given recording begins, Then display a prominent red "Recording" banner with elapsed timer to all participants and play a brief start chime; When recording stops, Then play a stop chime and show "Recording stopped". Given a participant joins while recording is active, Then require recording consent before allowing them to be captured; if declined, offer to join without being recorded or leave the session.
Role-Based Permissions for Recording & Media Access
Given RBAC policies are configured, Then only roles authorized by policy (default: Coach and Property Manager) can start/stop recording. Given RBAC policies are configured, Then only authorized roles (default: Property Manager/Owner) can download media; viewing permissions respect tenant access to their own session recordings when enabled by policy. Given an unauthorized role attempts a restricted action, Then deny the action, gray out the control, and show an informative message without revealing sensitive settings. Given media endpoints are accessed, Then enforce authorization and return 403 for unauthorized requests; all downloads use signed URLs expiring within 15 minutes.
Automatic Face/Address Blurring on Snapshots
Given a snapshot is captured during a session, When processing completes, Then detected faces are blurred and printed/stickered addresses or mailbox/door numbers are redacted prior to storage or sharing. Then face detection and blurring achieve at least 95% recall on the approved test set; any failure cases can be reported in-session to trigger reprocessing and redaction. Then there is no user-facing control to disable blurring on snapshots; only compliance admins with proper authorization can access originals for lawful requests, and such access is logged.
Media Encryption In Transit and At Rest
Given a LiveCoach session streams media, Then all media/control channels use TLS 1.2+ and DTLS-SRTP; inspection with a network sniffer reveals no plaintext audio/video. Given media is stored, Then it is encrypted at rest with AES-256-GCM (or stronger) using keys in a managed KMS, with key rotation at least every 90 days and per-tenant segregation. Given media is shared or downloaded, Then access uses time-bound signed URLs (<= 15-minute expiry) and requires authorization; decryption keys are never exposed to clients.
Jurisdictional Retention and Deletion Enforcement
Given a session is associated to a property address, Then the system derives a jurisdiction code and applies the configured retention policy for snapshots, recordings, and logs. Given retention windows elapse, Then media is automatically purged within 24 hours of the configured time and removed from search indexes and CDN caches. Given a verified deletion request is submitted, Then related media is deleted within 24 hours unless a documented legal hold exists; post-deletion access attempts return 404. Given a legal hold is applied, Then deletion is suspended and the hold metadata is visible to authorized roles.
Comprehensive Audit Logging of Access and Changes
Then the system records immutable audit events for: consent granted/withdrawn, privacy panel viewed/changed, recording start/stop, snapshot capture, media view/download/export, retention policy change, deletion, and legal hold changes. Then each log entry includes: event type, UTC timestamp (ISO-8601), actor ID and role, target entity IDs (session/media), IP address and user agent, outcome, reason (if provided), and correlation/session IDs. Then audit logs are append-only and tamper-evident (e.g., WORM storage or hash chaining) and are queryable within 5 minutes of the event; export to CSV is available to authorized roles.
Coach Roster & Quality Management
"As an operations lead, I want to manage coach vetting and quality metrics so that sessions are reliable and high-quality."
Description

Provides management of vetted coach profiles with identity verification, background checks, certifications, skill tags, languages, and service regions. Supports availability scheduling, on-call toggles, and fair load balancing. Tracks quality metrics such as CSAT, first-assist resolution rate, average handle time, and compliance with documentation, and enables QA review workflows. Includes playbook and macro management for common issues and uses performance-based routing to elevate high performers.

Acceptance Criteria
Coach Profile Creation and Verification
Given an admin with "Coach Manager" role is on the Create Coach screen When the admin enters first name, last name, email, phone, languages, service regions, and uploads government ID and certifications, and submits Then the system validates required fields and format, rejecting submission with inline errors for any missing or invalid fields And the system creates the profile in status "Pending Verification" and fires identity and background checks via the configured provider within 5 seconds And certification documents are virus-scanned and stored with encryption at rest And an audit log records creator, timestamp, and submitted fields (excluding full PII images) When both identity and background checks return "Pass" and required certifications are verified Then the profile status auto-transitions to "Active" and is eligible for routing When any check returns "Fail" or expires Then the profile status becomes "Suspended" and routing eligibility is revoked, and the admin is notified
Skill Tags, Languages, and Regions Management
Given an active coach profile When an admin adds or removes skill tags, languages, or service regions and saves Then the changes are validated against the controlled vocabulary and region taxonomy; invalid values are rejected with messages And changes take effect in routing filters within 60 seconds And the coach becomes discoverable via search filter combinations for those attributes And a versioned change history entry is recorded with actor and timestamp When all attributes are cleared Then saving is blocked and an error indicates at least one language and one region are required for eligibility
Availability Scheduling and On‑Call
Given a coach with a defined timezone When the coach configures weekly availability windows and optional blackout dates and saves Then the schedule is persisted and displayed in local time and UTC And the coach can toggle "On‑Call" on/off, which updates their routing eligibility within 15 seconds And calendar conflicts imported via ICS are respected to mark the coach unavailable When current time falls within an availability window and the coach is On‑Call Then the coach is eligible for routing up to their concurrency limit When the coach toggles Off or a blackout occurs Then the coach is immediately excluded from new assignments while existing sessions remain unaffected
Fair Load Balancing Among Eligible Coaches
Given N (>=2) eligible coaches for a request with matching skills, language, region, and availability When a new LiveCoach Assist request is received Then the routing engine selects the coach with the lowest weighted assignment score over the past 24 hours, respecting per‑coach concurrency limits and cooldowns And the selection decision, inputs, and chosen coach are logged with a unique routing ID And the selected coach's weighted score is updated before the next routing evaluation When two or more coaches have equal scores Then tie‑breakers are applied in order: higher recent CSAT (30 days), higher FAR (First‑Assist Resolution), lower AHT, then random And no single eligible coach receives more than 35% of assignments among the group over any rolling window of 500 routed sessions
Quality Metrics Capture and Reporting
Given a completed LiveCoach session When the resident submits CSAT (1–5 stars) and marks resolution outcome Then CSAT and FAR are recorded and attributed to the coach and session And Average Handle Time is computed from session start/stop timestamps And documentation completeness is scored based on presence of diagnostic notes, annotated screenshots, and selected playbook or macro And metrics are visible in the dashboard, filterable by date range, coach, skill, and property, and exportable to CSV And metrics aggregates update within 5 minutes of event receipt and are retained for 24 months
QA Review Workflow and Documentation Compliance
Given a user with "QA Reviewer" role When the reviewer opens any completed session Then they can score against a configurable rubric, add comments, require rework, or mark Pass/Fail And if marked "Rework Required," the coach is notified and must update documentation within 48 hours or the session auto‑fails compliance And sessions failing compliance reduce the coach's compliance metric and can trigger auto‑suspension if three failures occur within 30 days And all QA actions are audit‑logged with actor, timestamp, and deltas When a session is marked Fail with reason "Incomplete Documentation" Then routing eligibility for that coach excludes new sessions until outstanding rework items are resolved or the suspension is lifted by an admin
Playbooks, Macros, and Performance‑Based Routing
Given an admin creates or updates a playbook or macro and publishes it When a coach applies a macro during a session Then required fields are prefilled, and usage is recorded with macro ID and timestamp And if the coach marks "Attempt Failed," the UI requires brief diagnostic notes before session close When routing is configured with performance weighting enabled Then coaches with CSAT >= 4.7 and FAR >= 70% over the last 30 days receive a 1.3x priority multiplier; coaches below CSAT 4.2 or FAR 50% receive a 0.7x multiplier; others remain neutral at 1.0x And changes in performance tier take effect within 10 minutes of metric updates And if fewer than 50 sessions exist in the lookback, routing falls back to neutral weighting for that coach
Session Billing & Approvals
"As an owner, I want session charges to follow my approval rules and appear on my ledger so that costs are controlled and transparent."
Description

Introduces per-session pricing and payout logic with owner-configurable approval rules, monthly caps, and overage handling. Posts charges to the property ledger with invoices and receipts, calculates taxes, and supports refunds or credits for failed connections under defined thresholds. Displays cost estimates prior to session start and blocks or requests approval when limits are exceeded. Integrates with FixFlow billing, payment processors, and coach payout rails for timely settlement and reporting.

Acceptance Criteria
Pre-Session Estimate & Authorization/Approval Gate
Given an owner-configured per-session price P in currency C, applicable tax rules, approval rules, and a monthly cap When a tenant initiates a LiveCoach Assist session and reaches the pre-session confirmation step Then the UI displays itemized estimate: Session Price=P, Tax=T, Total=P+T, Remaining Monthly Cap Budget=B, and an approval requirement indicator within 2 seconds And the Continue action is enabled only if rules allow without approval; otherwise the UI presents “Request Approval” or “Blocked by Cap” per policy And the estimated amounts match the final captured amounts within $0.01, unless a refund/credit policy applies
Monthly Cap Tracking & Enforcement
Given a monthly spend cap C for the property and month-to-date spend S When a new session estimate E is computed Then if S+E <= C and policy allows auto-approve, the session is marked Within Cap and may proceed Then if S+E > C and policy = Block, the session cannot start and displays message code CAP_BLOCK Then if S+E > C and policy = Require Approval, the approval workflow is initiated and the session is marked Pending Approval And monthly counters reset at 00:00 on the first day of the month in the property’s timezone
Payment Authorization, Capture, and Failover
Given a valid payment method M on file for the payer When the user confirms session start Then the system places an authorization hold for the estimated total on the payment processor and records auth_id And if authorization fails, session start is prevented, an error is shown, and no coach connection is initiated And upon session status = Completed, the authorization is captured within 5 minutes; if session is canceled prior to connect, the authorization is voided within 5 minutes And all processor responses (auth, capture, void, refund) are logged with correlation ids for reconciliation
Ledger Posting with Invoice & Receipt
Given a successfully captured session charge with amounts: Session Fee=P, Tax=T, Adjustments=A, Total=P+T+A When capture succeeds Then a ledger entry is created with unique invoice_id, line items [Session Fee=P, Tax=T, Adjustments=A], total, property/unit, payer, coach id, timestamps And an invoice PDF and a receipt are generated, stored, and linked to the ledger entry And receipt delivery (email/push/in-app) is sent per owner settings within 10 minutes And if capture fails after authorization, no ledger entry is posted and an alert is created for follow-up
Tax Calculation & Reporting
Given the property tax jurisdiction and any tax-exempt configuration When estimating and charging a session Then tax T is calculated via the tax engine using property location and exemption flags And T is displayed on the estimate and invoice with rate and jurisdiction codes And rounding uses round-half-up to 2 decimals; estimated T equals charged T within $0.01 And tax amounts are excluded from coach payout calculations and included in tax reporting exports
Failed Connection Refund/Credit Automation
Given a failed-connection threshold N seconds and a refund policy R (refund or credit) When a session ends with no bi-directional media established or total connected duration < N seconds Then the system automatically applies R for the full session total, voids any authorization or refunds the capture if already captured And a credit memo is posted to the ledger referencing the original invoice and updating balances And the session is marked Failed Connection, stakeholders are notified, and coach payout for this session is prevented
Coach Payout Calculation & Settlement
Given a completed, billable session with captured Total, taxes T, platform fee F, and a coach payout policy When payout is calculated Then coach payout = Total - T - F and is queued within 15 minutes of capture And payouts settle to the coach’s payout account per rail SLA and appear in payout reports with a payout_id and linked invoice_id And if a refund/credit occurs after capture, the payout is held or clawed back accordingly and the coach is notified

One‑Tap Escalate

At any step, convert to a work order prefilled with issue details, photos, and steps already tried. Tenants choose a window; vendors arrive informed with fewer back‑and‑forths. Owners keep costs controlled with pre‑approval ceilings carried forward.

Requirements

Instant Escalation from Any Step
"As a tenant or property manager, I want to escalate a maintenance request to a work order with one tap so that I can quickly move from troubleshooting to dispatch without re-entering information."
Description

Provide a persistent One‑Tap Escalate control across intake, triage, and messaging views that converts the current case into a Work Order in a single action. The flow must be idempotent, linking the new Work Order to the originating case and preserving all context. Support web and mobile with clear affordances and confirmation to prevent accidental escalation. Ensure sub-second UI response with asynchronous backend creation and progress indicators. Respect role-based permissions so tenants, owners, and managers see the control only when eligible and required fields are satisfied.

Acceptance Criteria
Visibility and Eligibility Across Web and Mobile
Given a user is on Intake, Triage, or Messaging for an active case on web or mobile When the user has the role and permissions to escalate and all required fields for escalation are satisfied Then a persistent One‑Tap Escalate control is visible and enabled in the primary action region Given a user lacks escalate permission for the case state or role When viewing any supported view Then the One‑Tap Escalate control is not rendered Given required escalation prerequisites (e.g., issue category, contact method, tenant scheduling window for tenant-initiated cases) are not satisfied When a tenant views the case Then the One‑Tap Escalate control is not rendered Given the control is rendered on web and mobile When inspected with accessibility tooling Then it has an accessible name "Escalate to Work Order", meets WCAG 2.1 AA contrast, and is reachable by keyboard/assistive tech
Accidental Escalation Prevention and Confirmation
Given a visible One‑Tap Escalate control When the user taps/clicks it Then a confirmation modal/sheet appears summarizing Work Order creation, selected time window (if any), and pre‑approval ceiling, with primary action "Confirm" and secondary "Cancel" Given the confirmation modal is displayed When the user clicks outside, presses Escape/Back, or selects Cancel Then the escalation is aborted and no Work Order is created Given the confirmation modal is displayed When the user selects Confirm Then the system proceeds to create a single Work Order and the control is temporarily disabled to prevent double‑submissions Given a screen reader user activates the control When the modal appears Then focus moves to the modal, is trapped until dismissal, and returns to the trigger on cancel
Asynchronous Escalation with Sub‑Second UI Feedback
Given a user confirms escalation When the request is sent Then the UI displays an immediate acknowledgement state within 500 ms (p95) with progress indicator labeled "Creating work order…" Given the backend processes the escalation asynchronously When creation completes successfully Then the UI transitions to the new Work Order detail within 10 seconds (p95) or shows a success toast with a deep link within the current view Given the backend returns an error or times out When escalation fails Then the user sees an error message explaining the failure and a Retry action; the original case remains unchanged Given intermittent connectivity on mobile When the request cannot be sent Then the user is informed and no background retry occurs without explicit user action
Prefilled Work Order With Preserved Context
Given a case contains issue title/description, category, unit/property, tenant contact, triage answers, steps tried, photos (with annotations and timestamps), and attachments When escalated Then the Work Order is created with all those fields prefilled and photo/annotation timestamps preserved Given the owner/property has a pre‑approval cost ceiling configured (amount and currency) When escalated Then that ceiling value is carried forward into the Work Order cost controls unchanged Given N photos and M attachments exist on the case When escalated Then the Work Order shows the same counts N and M and the file checksums match the source assets Given locale-specific formats When values are displayed on the Work Order Then currency, dates, and times are formatted per the user’s locale while stored in canonical formats
Bidirectional Linking and Audit Trail
Given a case is escalated When the Work Order is created Then the Work Order stores the Originating Case ID and the Case stores the Work Order ID with clickable links in both records Given the escalation completes When viewing the case timeline/audit log Then an immutable entry records actor, role, timestamp (UTC), platform (web/mobile), and idempotency key used Given reporting/export is executed When including these records Then the link fields and audit metadata are available via API and export
Idempotent Escalation Under Repeats and Concurrency
Given a user confirms escalation and taps Confirm multiple times or the client retries due to a transient error When the server receives duplicate requests with the same case idempotency key Then exactly one Work Order is created and subsequent requests return the existing Work Order reference Given two different devices attempt to escalate the same case concurrently When both requests are processed Then only one Work Order exists and both clients are routed to/view the same Work Order Given a case already has a linked Work Order When revisiting the case Then the One‑Tap Escalate control is replaced by a "View Work Order" action that deep-links to the existing Work Order
Scheduling Window and Cost Ceiling Carry‑Forward
Given a tenant has selected a valid scheduling window during intake/triage/messaging When the case is escalated Then that window is copied to the Work Order and displayed to vendors in their dispatch view Given no scheduling window is on file for a tenant-initiated escalation and a window is marked as required for tenants When viewing the case Then the One‑Tap Escalate control is not rendered until a valid window is provided Given an owner-defined pre‑approval ceiling exists at the property/portfolio level When the case is escalated Then the Work Order reflects that ceiling; if multiple ceilings apply, the most specific (unit/property) is selected per business rules and recorded in the audit log
Auto-Prefilled Work Order with Timeline
"As a property manager, I want the work order to be automatically populated with issue details, photos, and steps attempted so that vendors receive complete context and avoid redundant questions."
Description

Automatically populate the Work Order with the issue summary, structured triage outcomes, annotated photo/video timeline, location (property/unit), access instructions, hazards, and steps already attempted. Map intake fields to vendor-facing fields with sensible defaults and allow authorized users to edit before dispatch. Redact sensitive PII per role, while preserving an immutable internal audit copy. Attachments should be deduplicated and time-stamped, with captions preserved. Validate required fields (category, priority, contact method) and flag gaps before dispatch.

Acceptance Criteria
Tenant Time Window Scheduling
"As a tenant, I want to choose a preferred time window for vendor arrival so that the repair happens when I’m available and access is guaranteed."
Description

Enable tenants to choose preferred arrival windows (e.g., 2–4 hour blocks) during escalation, honoring building access constraints and quiet hours. Surface real-time availability where vendor calendars are integrated; otherwise offer suggested windows based on SLA and property rules. Confirm selections via SMS/email and calendar invites, with timezone awareness and reschedule controls prior to vendor acceptance. Lock or renegotiate windows after vendor acceptance with clear prompts. Persist chosen windows on the Work Order for dispatch logic and routing.

Acceptance Criteria
Vendor-Informed Dispatch & Acceptance
"As a vendor, I want to receive a structured job card with all relevant details and the ability to accept or propose a new time so that I can plan my schedule and arrive prepared."
Description

Generate a vendor-facing job card containing summarized issue details, annotated media, attempted fixes, access notes, hazard flags, and pre-approval limits. Support accept/decline with reason codes, propose-new-time flows, and automatic ETA updates. Provide a lightweight web link and in-app view, with secure, expiring tokens for non-logged-in vendors. On acceptance, confirm to tenant and owner and transition the Work Order to scheduled state. Capture vendor questions in a structured thread that syncs to the work order without exposing tenant PII.

Acceptance Criteria
Pre-Approval Ceiling Enforcement
"As an owner, I want my pre-approval spending ceilings to carry forward into the work order and be enforced so that costs remain controlled and exceptions require my approval."
Description

Carry forward owner-defined pre-approval spending ceilings and category rules into the Work Order and vendor job card. Enforce caps at dispatch and during job updates, prompting for owner approval when estimates or change orders exceed thresholds. Display remaining budget to vendors and managers, with warnings as costs approach limits. Log approvals with approver identity, timestamp, and scope of approval. Prevent invoice submission above approved amounts without explicit exception handling.

Acceptance Criteria
End-to-End Notifications & Audit Trail
"As a stakeholder, I want notifications and an auditable timeline of all actions so that I can track progress and resolve any disputes with evidence."
Description

Send role-aware notifications for key state changes (escalated, scheduled, accepted, rescheduled, approval requested/approved) via push, SMS, and email with user preferences and rate limiting. Append all events, attachments, and approvals to the case’s photo-timeline to create a single auditable record. Provide an exportable timeline (PDF/CSV) with tamper-evident hashes for dispute resolution. Ensure retries and fallbacks for failed notifications and surface delivery status to admins. Comply with data retention and privacy policies across all stored artifacts.

Acceptance Criteria

LoadScore

A dynamic capacity score that blends current workload, drive time, crew availability, and job complexity to surface vendors who can start soonest without risking schedule slips. Managers dispatch confidently, vendors avoid overbooking, and tenants get faster fixes.

Requirements

Real-time Vendor Capacity Ingestion
"As a vendor manager, I want my team’s current capacity to update automatically so that FixFlow can recommend jobs we can start soon without overcommitting."
Description

Continuously ingest vendor availability signals (active jobs, crew count and skills, shift calendars, blackout dates, service areas) from connected calendars, vendor app check-ins, and API/webhooks. Normalize data to a unified capacity model per vendor and per crew, updated at least every 5 minutes. Support manual overrides by managers and vendors with effective time windows. Handle missing integrations via lightweight in-app status updates and default rules. Persist snapshots for scoring and auditing. Enforce tenant/landlord separation across accounts.

Acceptance Criteria
Drive Time & Service Radius Estimation
"As a dispatcher, I want accurate travel time estimates so that I can send the nearest available vendor and reduce delays."
Description

Calculate travel time from vendor home base or current job to the tenant’s address using a mapping provider with live traffic and time-window adjustments. Respect vendor service areas, blackout zones, and parking constraints. Provide fallbacks when network or provider limits occur, using cached averages by time-of-day and corridor. Expose ETA and distance to the scoring engine and UI. Batch requests and cache results to control API cost and latency.

Acceptance Criteria
Job Complexity & Duration Estimation
"As a property manager, I want FixFlow to estimate how long a job will take so that I can choose a vendor who can realistically complete it within my SLA."
Description

Derive a complexity score and expected duration from maintenance intake details, triage outcomes, unit metadata, and historical job performance. Map problem categories to base durations and adjust for onsite constraints (access, building type, required certifications) and parts availability. Provide explainable features and confidence signals. Allow manual adjustment by managers before dispatch. Feed estimates into capacity allocation and LoadScore.

Acceptance Criteria
LoadScore Computation Engine
"As a manager, I want a single score that tells me who can start soonest without schedule risk so that I can dispatch confidently."
Description

Compute a normalized capacity score per vendor that blends current workload, remaining crew-hours, drive time, job complexity, schedule conflicts, and vendor performance against SLAs. Support configurable weighting by portfolio, category, and urgency. Provide guardrails to exclude vendors exceeding capacity thresholds or outside service windows. Return both the score and human-readable rationale for transparency. Recalculate on relevant events and stream updates to UI and APIs.

Acceptance Criteria
Dispatch UI Integration & Explanations
"As a dispatcher, I want a clear ranked list with explanations so that I can justify my choice to owners and accelerate approvals."
Description

Surface a ranked vendor list in FixFlow’s dispatch view with LoadScore, ETA, earliest start window, and capacity risk badges. Provide “why ranked here” explanations with the top contributing factors. Enable filtering by certifications, cost tiers, and preferred vendors, with real-time re-ranking. Support one-click dispatch and soft-hold reservations with expiration timers. Ensure responsive performance (<300 ms rank rendering from cached scores) and accessibility compliance.

Acceptance Criteria
Overbooking Guardrails & Vendor Commitments
"As a vendor, I want FixFlow to reserve realistic time on my calendar when I accept a job so that I don’t get double-booked."
Description

Prevent overbooking by enforcing capacity thresholds and reserving time blocks upon dispatch or vendor acceptance. Implement soft holds when a job is proposed and auto-release on timeout or decline. Sync holds back to vendor calendars. Detect and alert on conflicts arising from manual calendar changes. Provide configurable SLAs for response and arrival windows, with automatic rescore and re-route on breach risk.

Acceptance Criteria
Score Audit Trail & Performance Feedback
"As an owner, I want an auditable record of how a vendor was selected so that we can resolve disputes and improve our dispatch policy."
Description

Store LoadScore inputs, weights, and outputs per decision as immutable snapshots tied to the work order. Display a timeline of score changes with event triggers (new intake details, vendor capacity update, route change). Track outcome metrics like actual arrival, completion time, and SLA adherence to calibrate estimates and weights. Provide exportable reports and APIs for portfolio-level performance reviews and dispute resolution.

Acceptance Criteria

Radius Flex

Automatically expands or tightens each vendor’s service radius based on urgency, live traffic, weather, and payout rules. Routine jobs stay local to cut costs; emergencies widen the net to ensure coverage and on‑time arrivals.

Requirements

Dynamic Radius Calculation Engine
"As a property manager, I want vendor coverage to expand or tighten dynamically based on urgency, traffic, weather, and payout rules so that emergencies are handled on time and routine jobs minimize cost."
Description

Compute and adjust a per-job, per-vendor service radius in real time using urgency level, live ETA signals, weather impact, vendor constraints, job category, and payout rules. The engine outputs the candidate vendor set, recommended radius, and reason codes for inclusions/exclusions. It runs at key moments (job creation, escalation checkpoints, vendor acceptance/decline, data signal changes) and is idempotent with deterministic tie‑breakers to ensure consistent outcomes. Integrates with FixFlow dispatch to feed vendor ranking by combined ETA, cost, and compliance score, keeping routine jobs local to reduce spend while widening coverage for emergencies to meet arrival targets.

Acceptance Criteria
Real-time Traffic and Weather Integrations
"As a property manager, I want FixFlow to factor live traffic and weather into ETAs and coverage decisions so that arrival windows are accurate and on-time performance improves."
Description

Ingest live traffic and weather data to compute drive-time ETAs and risk modifiers per vendor-property route. Supports multiple providers with caching, rate limiting, retries, and graceful degradation to static baselines if signals are unavailable. Normalizes inputs (incidents, congestion, precipitation, temperature, severe alerts) into standardized severity scores with freshness windows and geo-bounded queries. Exposes an internal API used by the Radius Flex engine and stores snapshots for auditability, ensuring dispatch decisions reflect current road conditions and hazards.

Acceptance Criteria
Vendor Eligibility and Payout Rules Evaluator
"As an independent landlord, I want only eligible vendors within my policies and budgets to be considered so that I control costs and compliance while maintaining service quality."
Description

Evaluate vendor eligibility and expected payout for each job based on vendor profile constraints (service areas, max travel time/distance, hours, skills, insurance), job category, urgency, and compensation policies (base rates, travel surcharges, surge for emergencies, caps). Filter and score vendors by compliance and cost-to-serve, enforcing owner budget guardrails while honoring vendor opt-ins. Integrates with FixFlow vendor profiles, pricing tables, and job budgeting to ensure only compliant, economically viable vendors are considered by Radius Flex.

Acceptance Criteria
SLA-Aware Progressive Expansion
"As a property manager, I want the system to widen the vendor search automatically as the SLA clock ticks down so that urgent work is covered without me micromanaging each dispatch."
Description

Execute a staged search strategy that begins with a local radius and automatically widens coverage as the SLA countdown progresses or assignment attempts fail. Uses remaining time-to-arrival, current ETAs, and acceptance signals to calculate expansion steps and cadence, with configurable maximum radius and emergency overrides. Triggers notifications at key thresholds, pauses expansion if a viable offer is pending, and stops when an on-time arrival is assured. Integrates with dispatch workflows to re-rank candidates as conditions change, improving fill rates without manual intervention.

Acceptance Criteria
Configuration Controls and Policy UI
"As an owner, I want to set and adjust radius and payout policies per property and job type so that the automation aligns with my budget and service expectations."
Description

Provide an admin interface to configure Radius Flex policies: base radii by job category and urgency, maximum expansion limits, weather and traffic weighting, payout caps, vendor opt-in preferences, and property- or portfolio-level overrides. Support versioned policy changes with effective dates, role-based access control, and validation to prevent conflicting rules. Expose preview and test inputs to visualize how a job would route under current settings. Integrates with FixFlow settings and permissions, enabling rapid alignment of automation with owner goals and regional realities.

Acceptance Criteria
Decision Audit Trail and Explainability
"As an owner, I want a clear audit of why a vendor was selected or skipped so that I can resolve responsibility disputes and fine-tune my policies with confidence."
Description

Persist a detailed record of every radius calculation and expansion decision, including inputs (urgency, signals, vendor constraints), computed ETAs and costs, candidate lists, reasons for inclusion/exclusion, timestamps, and policy versions used. Surface this information in the job timeline and via exportable reports to support dispute resolution and continuous improvement. Provide clear, human-readable explanations alongside machine-readable reason codes so stakeholders understand why a vendor was selected, skipped, or why the radius changed.

Acceptance Criteria
Simulation and Policy A/B Testing
"As an operations lead, I want to simulate and A/B test Radius Flex policies so that we optimize cost and on-time performance before rolling changes out broadly."
Description

Enable offline simulation on historical or sandboxed jobs to compare alternative radius and payout policies against KPIs (time-to-assign, on-time arrival rate, cost per job). Provide safe rollout with cohorting or feature flags to A/B test policies in production at limited exposure. Generate dashboards and recommendations to guide tuning of weights, caps, and expansion cadence. Ensures Radius Flex evolves based on evidence while minimizing risk to live operations.

Acceptance Criteria

SLA Match

Predicts on‑time likelihood per vendor using historical SLA performance by issue type, property, and time of day. Filters and ranks vendors to hit required SLAs, boosting tenant satisfaction and reducing breach penalties.

Requirements

Dynamic SLA Target Resolver
"As a property manager, I want the system to automatically determine the correct SLA deadline for each job so that vendor selection and scheduling target the actual contractual requirement."
Description

Computes the precise SLA deadline for each work order by combining contract rules (per owner/property), issue type severity, tenant lease terms, and request timestamp/time-of-day. Normalizes heterogeneous SLA definitions (e.g., "respond in 2 business hours" vs. "onsite within 24h") into a unified target time, accounting for holidays and vendor working calendars. Exposes a consistent SLA object to downstream triage and dispatch services so vendor scoring and ranking align to the true required deadline, reducing breach risk and ensuring apples-to-apples comparisons across vendors.

Acceptance Criteria
Vendor SLA Performance Scoring
"As a dispatcher, I want each vendor to be scored on their likelihood to meet the SLA for this job so that I can choose the option most likely to avoid a breach."
Description

Generates a real-time probability of on-time completion for each eligible vendor given the specific issue type, property, and request time. Leverages historical completion times, cancellations, first-contact lag, and arrival punctuality to train a predictive model, with features for time-of-day/day-of-week, property access complexity, and seasonality. Outputs a calibrated on-time likelihood and confidence score per vendor-issue-property tuple via a low-latency scoring API to power dispatch decisions within FixFlow.

Acceptance Criteria
Eligibility Filtering and SLA-Optimized Ranking
"As a landlord, I want only qualified vendors to appear and be ranked by their chance to meet the SLA so that I can quickly assign work with confidence."
Description

Filters vendors based on coverage area, trade/certifications, insurance/compliance status, price ceilings, and owner preferences, then ranks the remaining vendors by a composite score emphasizing predicted on-time probability relative to the computed SLA. Incorporates tie-breakers such as recent responsiveness, tenant ratings, and past performance at the specific property. Produces a deterministic, explainable ranked list to the dispatch UI and APIs, enabling one-click selection of the top match.

Acceptance Criteria
Availability and Travel-Time Awareness
"As an operations coordinator, I want vendor calendars and travel time incorporated into the recommendations so that scheduled arrivals are realistic and meet the SLA."
Description

Integrates vendor availability (working hours, current bookings, blackout dates) and live or historical travel-time estimates to refine on-time predictions and ETAs. Adjusts recommendations based on earliest feasible arrival windows, buffer times, and property access constraints. Continuously re-scores when vendor capacity changes or tenant reschedules, keeping the ranking aligned with real-world constraints to maximize SLA adherence.

Acceptance Criteria
Cold-Start and Data Quality Safeguards
"As an admin, I want the system to handle new or data-sparse vendors safely so that recommendations remain trustworthy even when history is limited."
Description

Implements robust defaults for new or low-data vendors using trade-level and region-level priors, minimum sample thresholds, and conservative confidence bands. Detects anomalous or incomplete historical data, applies outlier handling, and prevents overconfident recommendations. Surfaces data completeness indicators to the UI and logs data-quality metrics for continuous improvement without blocking dispatch.

Acceptance Criteria
Explainable Recommendations and Outcome Feedback Loop
"As a property manager, I want to understand why a vendor is recommended and see the system learn from outcomes so that trust increases and SLA performance improves continuously."
Description

Provides transparent explanations for each recommendation, including top contributing factors (e.g., past on-time rate for similar jobs at this property, calendar availability, travel time) and confidence level. Captures actual outcomes (on-time vs. breach, delays, cancellations) and feeds them into monitoring dashboards, calibration checks, and periodic model retraining to improve accuracy and reduce SLA breaches over time.

Acceptance Criteria

No‑Show Shield

Identifies high no‑show or slip risk and applies safeguards—double‑confirmation prompts, backup vendor holds, and proactive reschedule paths. Tenants get timely ETA updates while managers avoid last‑minute scrambles.

Requirements

Predictive No‑Show Risk Scoring
"As a property manager, I want appointments automatically scored for no‑show risk so that safeguards trigger before issues surface and I avoid last‑minute scrambles."
Description

Compute a real‑time no‑show/slip risk score for each scheduled appointment using vendor punctuality history, tenant responsiveness, distance and traffic reliability, appointment window type, weather/holiday signals, and building access complexity. Generate probability and Low/Medium/High tiers at scheduling and refresh at T‑48h, T‑24h, and T‑3h. Expose the score and top contributing factors on the job record, trigger safeguards (double‑confirm prompts, backup holds, proactive reschedule), and log all versions for the annotated audit timeline. Integrate with FixFlow scheduling and dispatch services, respect role‑based access, and operate within data privacy and retention policies.

Acceptance Criteria
Double‑Confirmation Auto‑Prompts
"As a tenant, I want simple, timely prompts to confirm my availability so that visits happen when I’m ready and I don’t miss the appointment."
Description

Automatically send timed confirmation prompts to both tenant and primary vendor via SMS, email, and in‑app at configurable intervals (e.g., 24h and 3h before arrival). Provide one‑tap Confirm, Reschedule, or Running Late options; capture responses, timestamps, and channel used; and escalate if no response (e.g., re‑prompt, notify manager, or trigger backup vendor hold). Localize content, respect time zones and quiet hours, apply rate limits, and fail over to alternate channels. Persist outcomes to the job record and surface current confirmation state in all participant views.

Acceptance Criteria
Backup Vendor Soft‑Hold
"As a small property manager, I want a backup vendor pre‑secured for risky appointments so that I can keep repair timelines on track without scrambling."
Description

When risk exceeds threshold or confirmations fail, automatically place time‑boxed soft holds on qualified backup vendors that match trade, proximity, price ceiling, and SLA constraints. Reserve their availability without exposing tenant PII until assignment; notify selected vendors with accept‑if‑needed workflow and auto‑release holds when primary confirms or job completes. If the primary cancels or misses the window, auto‑promote the best available backup and notify all parties. Record selection rationale and hold lifecycle in the audit trail.

Acceptance Criteria
Dynamic ETA Tracking and Notifications
"As a tenant, I want accurate ETA updates as the vendor is on the way so that I can plan my time and avoid waiting around."
Description

Track vendor approach via optional GPS sharing or quick status check‑ins; compute live ETA and compare against the agreed window. Proactively notify tenant and manager of on‑time, delayed, or missed statuses with actionable links (message vendor, reschedule, building access tips). Trigger escalation rules when ETA breaches thresholds and update the job’s annotated timeline with location pings, status changes, and messages. Provide privacy‑respecting ephemeral tracking links and fallbacks for vendors without location sharing.

Acceptance Criteria
One‑Tap Smart Reschedule Flow
"As a tenant, I want to quickly pick a new time when plans change so that the repair still happens soon without calling the manager."
Description

Offer an immediate reschedule path when confirmations fail, ETAs slip, or a no‑show is detected. Present the earliest viable slots across the primary and held backups, honoring tenant preferences, building access constraints, SLAs, and vendor calendars. Carry forward all job context, notes, and photos; prevent duplicate work orders; and capture explicit consent for any fee or window change. Confirm the new slot with all parties and update downstream dispatch and audit records automatically.

Acceptance Criteria
Manager Exception Dashboard & Audit Trail
"As a property manager, I want a single view of all at‑risk appointments and actions I can take so that I can prevent no‑shows and document everything for owners."
Description

Provide a real‑time dashboard listing upcoming high‑risk jobs, pending confirmations, ETA exceptions, and active backup holds with filters, sorting, and quick actions (force confirm, extend window, promote backup, cancel). Show per‑job timelines with prompts, responses, ETA changes, and assignment decisions for dispute‑free accountability. Offer export to CSV/JSON, role‑based access, and retention controls aligned with FixFlow’s compliance policies.

Acceptance Criteria

Route Cluster

Clusters nearby tickets and proposes optimized runs with batch scheduling. Vendors accept dense routes to earn more with less drive time; managers clear more work orders per day and shrink arrival windows.

Requirements

Geospatial Ticket Clustering
"As a property manager, I want nearby tickets automatically clustered into workable groups so that I can schedule denser routes and reduce vendor drive time."
Description

Implement a geospatial clustering service that groups open maintenance tickets into proximity-based clusters using travel-time distances, tenant availability windows, estimated job durations, and vendor capability tags. The service must generate candidate clusters in near real time as new tickets arrive or ticket details change, expose tunable parameters (maximum travel minutes between stops, cluster radius, jobs per cluster), and output scored cluster proposals with rationale. It integrates with FixFlow’s triage pipeline and vendor profiles to filter by skills/equipment and building access constraints, and surfaces cluster proposals in the dispatcher UI and via API.

Acceptance Criteria
Optimized Run Builder
"As a vendor, I want proposed runs with back-to-back stops that fit my working hours so that I can earn more with less driving."
Description

Provide an optimized run builder that converts a selected cluster into a sequenced route per vendor, minimizing total travel time while respecting tenant time windows, SLA deadlines, service duration estimates, prep/cleanup buffers, vendor working hours and breaks, and start/end locations. The builder produces one or more proposed runs with start times and arrival windows, supports what‑if adjustments (move job up/down, swap vendor), and checks calendar conflicts. It integrates with FixFlow scheduling to place tentative holds until acceptance.

Acceptance Criteria
Vendor Acceptance and Locking Workflow
"As a vendor, I want to quickly review and accept or decline proposed routes so that my schedule stays efficient and under my control."
Description

Create a vendor acceptance workflow for proposed runs, enabling accept, decline, and partial-accept actions with time-limited holds and versioned route proposals. On acceptance, convert tentative holds into firm appointments and update ticket statuses; on decline or expiry, release holds and re-queue jobs. Provide push and SMS/email notifications, in-app route preview with map and stop details, and support reassignment or escalation if capacity is insufficient.

Acceptance Criteria
Tenant Notification and Arrival Window Compression
"As a tenant, I want a precise arrival window and timely updates so that I can plan my day and ensure access."
Description

After a run is accepted, compute narrow arrival windows using the optimized sequence and live traffic estimates, and communicate them to tenants and owners via preferred channels. Include confirmation prompts, easy rescheduling links, and calendar attachments, and capture special access notes. If the run changes, automatically recalculate ETAs and send updated notifications. Delivery and read receipts are tracked for audit purposes and to minimize no‑access events.

Acceptance Criteria
Real-time Route Monitoring and Re-optimization
"As a dispatcher, I want to monitor route progress and adjust plans in real time so that service stays on schedule and SLAs are met."
Description

Enable real-time route monitoring using lightweight vendor check-ins and optional location sharing (opt-in, foreground-only) to detect delays or early completions. Recompute ETAs on deviations, propose live re-optimizations (swap order, insert nearby urgent ticket), and trigger downstream notifications. Respect privacy controls, configurable ping intervals, and data retention policies; record a route-level audit trail that links to FixFlow’s annotated photo timeline.

Acceptance Criteria
Eligibility Rules and Auto-grouping Governance
"As a property manager, I want clear rules determining which tickets can be batched so that clusters are safe, feasible, and SLA-compliant."
Description

Define eligibility rules for auto-grouping: include or exclude by job type, estimated duration, parts availability, priority/SLA class, tenant availability, and access requirements; exclude emergencies unless explicitly overridden. Support building-level bundling (same property or adjacent addresses), configurable thresholds for distance or travel minutes, and manual override of group membership with a complete audit log of changes.

Acceptance Criteria
Route Performance Analytics
"As an owner-operator, I want visibility into the impact of route clustering so that I can optimize vendor utilization and prove time and cost savings."
Description

Provide analytics that compare clustered versus non-clustered operations, including jobs per day, average drive time per job, acceptance rate, on-time arrival rate, SLA compliance, first-time fix rate, and tenant satisfaction signals. Display per-vendor and per-market dashboards, support data export, and surface insights such as ideal cluster size by job type to improve future route proposals.

Acceptance Criteria

Availability Ping

One‑tap availability broadcast to preferred vendors that returns real‑time accept/decline, earliest start, and travel ETA. Temporarily holds the best slot and auto‑expires if ignored, eliminating phone tag and speeding assignment.

Requirements

One-Tap Availability Broadcast
"As a property manager, I want to send a one-tap availability request to suitable vendors so that I can quickly gauge who can take the job without manual calls."
Description

From an open work order, the user can trigger a single action that broadcasts a standardized availability request to a curated set of preferred vendors matching the job category, location, and service window. The system packages essential job context (issue summary, unit address, access instructions, time constraints, and optional budget cap) while suppressing unnecessary PII. Broadcast respects vendor preferences, business hours, and quiet hours, and uses idempotency to prevent duplicate pings for the same work order. Integrates with FixFlow’s vendor directory, triage outputs, and assignment rules so that outreach is precise, compliant, and instantly actionable.

Acceptance Criteria
Vendor Micro-Response Channels
"As a vendor, I want to respond to availability pings from my phone without logging in so that I can confirm jobs quickly while on the go."
Description

Vendors receive pings through lightweight, low-friction channels (SMS, email, push) containing a secure, expiring link that opens a micro-UI for one-tap Accept/Decline, earliest available start selection, and optional travel-from location for ETA calculation. Links are single-use, vendor-scoped, and cryptographically signed to prevent spoofing. Channel delivery honors opt-in/opt-out preferences and quiet hours, with configurable retries and alternate-channel fallback. Responses are posted to FixFlow via a secure callback gateway with rate limiting, replay protection, and clear delivery status to ensure reliable two-way communication without requiring vendor login.

Acceptance Criteria
Real-Time Response Aggregation and Ranking
"As a dispatcher, I want to see vendor responses and ETAs update in real time so that I can select the best option without waiting or refreshing."
Description

Incoming vendor responses are captured in real time and surfaced on the work order with accept/decline status, earliest start windows, and computed travel ETAs. A ranking engine scores responses using configurable criteria (earliest start, shortest ETA, vendor rating, cost tier, warranty/coverage fit) and continuously updates the top recommendation as responses change. The UI provides live updates via push (websockets) with polling fallback, shows per-vendor delivery/response states, and supports filtering by vendor cohorts or tags to streamline decision-making.

Acceptance Criteria
Temporary Slot Hold with Auto-Expiry
"As a property manager, I want the best vendor slot to be temporarily held and auto-expire if I don’t act so that I avoid losing a good time while preventing stale reservations."
Description

When a qualifying response is received, the system tentatively holds the best available slot to prevent double booking while awaiting confirmation. Holds have configurable durations, vendor-visible countdowns, and reminder nudges to the assignee. If ignored or rescinded, holds auto-expire and release the slot atomically, promoting the next-best option without race conditions. All hold transitions are reversible by authorized users and consistently reflected on vendor and manager views to keep availability accurate.

Acceptance Criteria
Auto-Assignment and Fallback Routing
"As a landlord, I want the system to auto-assign the best available vendor or escalate if none respond so that repairs proceed without my constant intervention."
Description

Based on policy and urgency, the system can auto-assign the top-ranked vendor after a grace period or immediately for critical jobs, notifying stakeholders and creating the dispatch with scheduled time, access instructions, and contact details. If no acceptable response is received within a target SLA, the system escalates by widening the vendor pool, adjusting outreach channels or timing, and proposing alternative windows to the tenant. Manual overrides are supported at each step, and all changes sync with calendars and downstream dispatch workflows to minimize coordination lag.

Acceptance Criteria
Auditable Ping History and Timeline
"As an owner, I want a clear audit trail of vendor outreach and decisions so that I can verify fairness, resolve disputes, and meet documentation needs."
Description

All broadcast events, deliveries, responses, holds, expiries, and assignments are captured as time-stamped, immutable records linked to the work order’s activity stream. The audit view shows who was contacted, via which channel, when, and the outcome, including the rationale behind the selected vendor per the active ranking criteria. Records are exportable for owner reporting and dispute resolution, and tenant-facing views are redacted to protect vendor PII. Retention follows workspace policy with secure access controls for compliance and transparency.

Acceptance Criteria

UtilitySync Feeds

Continuously ingests utility and city outage APIs, social status pages, and grid alerts to flag building- or block‑level events in real time. You stop chasing false alarms, avoid unnecessary dispatches, and get trusted outage confirmations right inside FixFlow.

Requirements

Multi-Source Utility & Outage Ingestion Connectors
"As a small property manager, I want FixFlow to continuously ingest utility and outage updates from multiple trusted sources so that I get timely, comprehensive event coverage without manual tracking."
Description

Build modular connectors that continuously ingest outage data from utility company APIs, city outage APIs, grid alert feeds, and public status/social pages. Support both webhook and scheduled polling modes with per-source configuration (auth, cadence, time zones). Implement idempotent fetch, rate limiting, retries with exponential backoff, and timeouts to ensure reliability. Validate payloads, persist raw source messages for auditability, and publish standardized messages onto FixFlow’s internal event bus. Provide connector health metrics and alerts to surface failures and degraded sources.

Acceptance Criteria
Event Normalization & Canonical Outage Model
"As a property manager, I want outage data from diverse sources normalized into a single, consistent event record so that I can trust and act on clear, de-duplicated information."
Description

Normalize heterogeneous source payloads into a canonical OutageEvent model with consistent fields (utility type, status, severity, timestamps, affected area geometry, description, source list, and attachments). Implement de-duplication and merge logic to consolidate the same incident reported by multiple sources, maintaining provenance and version history as details evolve (reported → confirmed → restored). Expose a clean, queryable interface for downstream features while ensuring tenant isolation and data retention policies.

Acceptance Criteria
Geospatial Resolution & Building/Block Matching
"As a landlord, I want outages mapped precisely to my buildings and blocks so that I know which units are affected and can communicate accurately."
Description

Resolve each outage’s affected area to FixFlow buildings and nearby blocks using geocoding, GIS overlays, and street-segment matching. Support polygon and point-radius inputs, buffer tuning, and confidence thresholds for partial overlaps. Cache geospatial lookups for performance and handle multi-building and multi-portfolio scenarios. Provide clear indicators of which buildings/units are impacted and the precision level used to determine impact.

Acceptance Criteria
Real-time Alerts, Banners & Dispatch Suppression
"As a dispatcher, I want FixFlow to alert me in real time and automatically hold or suppress dispatches for confirmed outages so that we avoid unnecessary vendor trips and costs."
Description

Trigger real-time in-app banners on building and ticket pages, plus push/email/SMS notifications to designated recipients when an outage impacts a property. Automatically place related maintenance requests on hold and suppress vendor dispatches while an outage is active, with configurable rules by utility type and severity. Provide manual override with reason capture, auto-resume on restoration, and pause/resume of SLA timers to prevent penalizing teams for utility-caused delays.

Acceptance Criteria
Confidence Scoring & False-Positive Controls
"As an operator, I want a confidence score and controls to filter possible false positives so that automated actions only occur when the signal is reliable."
Description

Calculate a confidence score per event using source reliability, cross-source corroboration, geospatial precision, and recency. Gate automated actions (holds, banners, dispatch suppression) behind configurable confidence thresholds and cooldown windows to reduce alert thrash. Allow users to confirm, downgrade, or dismiss events, capturing feedback to refine scoring over time. Expose reason codes and contributing signals for transparency.

Acceptance Criteria
Admin Configuration & Notification Routing
"As an admin, I want to configure who gets notified, when, and for which utilities so that the right people are informed without noise."
Description

Provide tenant-level settings to enable or disable feeds by utility and region, set quiet hours and digest schedules, and route notifications by role, team, or portfolio. Support escalation rules, fallback contacts, and per-channel templates. Enforce role-based access control, log configuration changes, and allow export/import of settings for multi-portfolio consistency.

Acceptance Criteria
Outage Audit Trail & Timeline Integration
"As an owner, I want outage events automatically recorded on ticket timelines so that I have an auditable record for disputes and compliance."
Description

Automatically append outage events and restorations to maintenance ticket timelines and building histories with timestamps, source links, and affected-utility badges. Include these entries in exported reports and owner statements to provide auditable context for delays, approvals, and cost disputes. Respect retention policies and allow redaction where required.

Acceptance Criteria

Hotspot Map

Real‑time clustering of tenant reports and utility signals renders an interactive outage map with building and block boundaries. Instantly see scope and impact, drill into affected units, and act with confidence instead of guessing from scattered tickets.

Requirements

Real-time Signal Ingestion & Normalization
"As a property manager, I want new tenant reports and utility signals to appear on the map within a minute so that I can assess scope and respond quickly."
Description

Implement a low-latency pipeline that ingests tenant maintenance reports from FixFlow tickets and external utility/outage signals, deduplicates related events, geocodes addresses to precise building and unit IDs, and normalizes data into a unified incident schema (type, severity, timestamp, location, building_id, unit_id, source, confidence). The system must process and surface new signals to the map within 60 seconds, handle rate limits and retries with idempotency, and tag events with portfolio ownership for access control. Provide monitoring, dead-letter handling, and a versioned contract for upstream and downstream services to ensure reliable, auditable data flow feeding the Hotspot Map.

Acceptance Criteria
Boundary-aware Spatial Clustering
"As a property manager, I want nearby reports grouped by building or block with clear impact counts so that I can judge the scope of an outage at a glance."
Description

Deliver adaptive clustering that groups incidents in real time by spatial proximity while respecting building footprints and block boundaries, producing stable hotspot clusters at varying zoom levels. Clusters should compute impact metrics (affected buildings, units, severity distribution, time window) and update incrementally as new signals arrive. The clustering engine must support tunable parameters (distance thresholds, time windows, weighting by severity/source confidence) and return deterministic cluster IDs to enable drilldowns, notifications, and auditability.

Acceptance Criteria
Interactive Outage Map UI
"As a property manager, I want an interactive map with filters and clear overlays so that I can quickly find affected areas and understand the situation without sifting through tickets."
Description

Provide a responsive, accessible map interface that renders real-time clusters with badges and color-coded severity, overlays building and block boundaries, and displays a clear legend and last-updated timestamp. Users can filter by time window, incident type (water, power, HVAC, general), source (tenant vs. utility), severity, and status (open/resolved). Clicking a cluster reveals details and links to drilldowns, with smooth transitions and skeleton loading states. The UI must function on desktop and mobile, support cross-browser compatibility, and degrade gracefully with a list view if map tiles fail.

Acceptance Criteria
Affected Units Drilldown & Batch Actions
"As a property manager, I want to message affected tenants and dispatch vendors directly from a hotspot so that I can coordinate fixes quickly and consistently."
Description

Enable a contextual drilldown panel for any hotspot that lists affected buildings and units with ticket IDs, status, timestamps, severity, and contact readiness, along with impact summaries. Provide batch actions to coordinate remediation directly from the hotspot: send broadcast tenant messages, create bulk work orders, and dispatch vetted vendors via FixFlow’s dispatch module with prefilled scopes. All actions must enforce role permissions, record audit logs, and attach to the hotspot timeline for transparent post-mortems and dispute prevention.

Acceptance Criteria
Configurable Hotspot Alerts & Thresholds
"As a property manager, I want configurable alerts when a hotspot forms so that I can act immediately without constantly monitoring the map."
Description

Introduce a rule-based alerting system that triggers notifications when hotspot thresholds are met (e.g., N reports within T minutes within a building/block or a utility feed flags an outage). Allow per-portfolio and per-property configuration of thresholds, quiet hours, and channels (in-app, email, SMS), with automatic duplicate suppression and escalation paths. Alerts should link to the exact hotspot drilldown and include concise impact summaries to minimize time-to-action.

Acceptance Criteria
Access Control & Data Privacy
"As an owner, I want hotspot insights limited to my portfolio and anonymized elsewhere so that tenant privacy and compliance are preserved."
Description

Enforce strict role- and portfolio-based access so that users only see unit-level details for properties they manage, while non-owned areas display aggregated, anonymized cluster data. Minimize exposure of PII in map tooltips and alerts, honor communication preferences and consent for messaging, and maintain complete audit trails for data access and actions. The implementation must align with FixFlow’s security controls and support future compliance needs without rework.

Acceptance Criteria
Performance, SLAs & Observability
"As a property manager, I want the map to remain fast and available during outages so that I can make decisions under pressure."
Description

Set and meet service targets for the Hotspot Map: sub-2s initial render for portfolios up to a defined unit count, smooth pan/zoom under load, and 99.9% availability during business hours. Employ server-side aggregation, caching, and pagination to handle spikes, with graceful degradation to summarized views if dependencies fail. Instrument the pipeline and UI with metrics, logs, and traces, surface health/latency dashboards, and implement alerting on ingestion lag, clustering errors, and UI error rates.

Acceptance Criteria

Dispatch Freeze

Automatically pauses and deduplicates work orders within an identified outage zone, preventing wasted vendor rollouts and cancellation fees. Holds are lifted as soon as restoration is detected, with smart auto‑rescheduling to the next best window.

Requirements

Outage Zone Ingestion & Geofencing
"As a property manager, I want FixFlow to automatically detect when my units fall within an active utility outage so that affected maintenance is paused before vendors are dispatched."
Description

Continuously ingest and normalize outage data (power, water, gas, ISP) from utility APIs, public feeds, and trusted partners; construct geospatial outage polygons and match them to properties via address geocoding and rooftop coordinates. Apply rate limiting, retries, health checks, and TTL/expiry for stale zones. Fuse secondary signals (tenant reports, vendor feedback, abnormal ticket spikes) with rules to confirm or down‑weight outages. Support multi-region providers, time-bound windows, and partial-building outages (circuits/risers). Emit internal events when zones are created/updated/expired and expose a reliable query to check if an address is within an active outage for a given service type.

Acceptance Criteria
Automatic Hold & SLA Pause
"As a vendor coordinator, I want outage-affected work orders to be automatically put on hold with clear communication so that we avoid unnecessary rollouts and cancellation fees."
Description

When an active outage zone intersects a work order’s location and relevant problem category (e.g., no power, water shutoff), automatically set status to Held – Outage, pause SLA timers, suppress dispatch/assignment, and attach a structured hold reason with the impacted service type. Send templated, localized notifications to tenants, owners, and scheduled vendors explaining the hold and expected check‑ins, while preventing cancellation fees. Ensure idempotent holds, resume logic upon restoration, and configurable exclusion rules (e.g., life‑safety categories). Update calendars to reflect the hold and hide slots blocked by the freeze.

Acceptance Criteria
Duplicate Work Order Consolidation
"As a small landlord, I want similar outage-related tickets to be grouped under one incident so that I can manage a single plan and avoid double-booking vendors."
Description

Identify and group duplicate or highly similar outage-related work orders within the same building or outage zone by matching category, symptom keywords, time proximity, and geospatial overlap. Create a parent incident record that links child tickets, centralizes communications, and enforces a single dispatch plan. Preserve individual tenant context while preventing duplicate vendor bookings. Provide reversible merge and split operations with conflict detection and a clear audit of consolidation decisions.

Acceptance Criteria
Restoration Detection & Smart Auto‑Reschedule
"As a tenant, I want my paused repair to be automatically rescheduled to the soonest convenient time after service is restored so that I don’t need to call support."
Description

Continuously monitor outage zone status and vendor/tenant calendars; upon restoration, lift holds, re-prioritize backlogs by severity and age, and auto-schedule the next best service window. Optimize scheduling using vendor availability, tenant preferences, travel proximity, service levels, and blackout periods; resolve conflicts with rule-based tie‑breakers and offer fallback windows. Send confirmations and action links to all parties, handle declines with automatic retries, and log every decision and schedule change for traceability.

Acceptance Criteria
Manual Overrides & Safety Exceptions
"As a property manager, I want to override the freeze for life-safety repairs so that critical work proceeds without delay during general outages."
Description

Provide role-based controls to override Dispatch Freeze at the ticket or zone level with mandatory justification and audit logging. Define policy rules that whitelist life‑safety categories (e.g., active leak, gas smell, fire damage) or critical sites to bypass holds. Enable temporary exemptions, per-building policies, and vendor allowlists; apply guardrails (confirmation dialogs, secondary approval for risky overrides) and propagate changes to dispatch logic, calendars, and notifications in real time.

Acceptance Criteria
Freeze Timeline & Savings Reporting
"As an owner, I want reports quantifying avoided trips and fees from Dispatch Freeze so that I can see its ROI and impact on my portfolio."
Description

Record freeze lifecycle events (zone detection, hold applied, notifications sent, dedup merges, restoration time, reschedule decisions) into each work order’s annotated timeline. Aggregate analytics that estimate avoided vendor trips and cancellation fees, hold durations, SLA impact, and incident volumes by region/provider. Provide filters, exports, and webhooks for BI tools with PII‑safe payloads and data retention controls. Surface ROI metrics in the owner dashboard and enable drill‑through to underlying tickets for auditability.

Acceptance Criteria

Outage Broadcast

Send localized, one‑to‑many status updates to tenants, owners, and vendors via SMS, email, and push. Prebuilt templates include cause, affected area, and expected restoration, reducing inbound calls and keeping everyone aligned without manual copy‑paste.

Requirements

Multi-channel Delivery & Fallback Routing
"As a property manager, I want to send one update across SMS, email, and push with automatic fallback so that all recipients receive timely information regardless of their preferred channel."
Description

Implement a delivery engine that sends a single outage update across SMS, email, and mobile push, honoring per-contact channel preferences and providing automatic fallback if a preferred channel fails. Include rate limiting, batching, retries, and delivery status webhooks to surface per-recipient outcomes (queued, sent, delivered, failed) in a broadcast dashboard. Support sender identity configuration per property/portfolio, message size constraints with smart truncation and links to a hosted status page, and attachment handling for images/maps where supported. Integrate with FixFlow’s contact directory and incident model so messages reference the active outage, and expose a simple API for internal services to publish broadcast events.

Acceptance Criteria
Audience Targeting & Geo/Property Scoping
"As a small property manager, I want to target only the affected units and relevant vendors so that I avoid spamming unaffected recipients and reduce confusion."
Description

Provide precise recipient targeting by property, building, floor/unit stack, and geofenced areas, with role-based filters (tenants, owners, vendors) and vendor specialty (e.g., electricians for power outages). Include dynamic lists that auto-exclude vacant units and deduplicate contacts across roles. Allow saved audiences and incident-driven scopes (e.g., “all units on water riser A”). Display estimated reach before sending and support exclusions (e.g., unaffected wing). Integrate with FixFlow’s property graph and unit metadata to keep targeting accurate as occupancy changes.

Acceptance Criteria
Template Library with Dynamic Fields
"As an owner-operator, I want ready-to-use outage templates that auto-fill incident details so that I can communicate quickly and consistently without manual rewriting."
Description

Offer a library of prebuilt, role-specific templates that include dynamic tokens for cause, affected area, impact, safety guidance, and expected restoration time. Enable merge from the incident record and vendor ETA, with preview for SMS, email, and push. Support versioning, approvals, and per-property custom templates, plus conditional sections (e.g., include elevator access instructions only if applicable). Ensure consistent tone and branding while reducing manual copy-paste. Store rendered content alongside the incident for future reuse and audits.

Acceptance Criteria
Scheduled & Triggered Broadcasts
"As a landlord managing multiple units, I want updates to go out automatically when status changes so that tenants stay informed without me having to micromanage each message."
Description

Allow scheduling of broadcasts for a future time, recurring updates at set intervals until resolution, and automatic sends driven by incident lifecycle events (created, ETA updated, vendor en route, resolved). Respect quiet hours with severity-based overrides, and throttle repeat sends to the same audience. Provide a countdown to next update and a one-click “post status” from the incident screen. Expose triggers in workflow settings so teams can tailor automation per property or outage type.

Acceptance Criteria
Two-way Acknowledgements, Consent, and Reply Routing
"As a tenant, I want to acknowledge I’ve received an outage message and ask a quick question so that I feel informed and can get clarification without calling."
Description

Capture recipient acknowledgements (e.g., “Got it”) and parse common replies (STOP/HELP/UNSUBSCRIBE/CONFIRM) to update consent and engagement status. Route free-text replies into the incident thread or team inbox with tags for triage and escalation, and notify the incident owner on critical replies. Maintain per-channel consent logs with timestamps and jurisdictional compliance rules; provide easy opt-in/out management and failover to permitted channels when consent is missing. Surface acknowledgement rates to help decide if another update is needed.

Acceptance Criteria
Broadcast Timeline & Auditable Records
"As an owner, I want a complete record of all outage communications so that I can verify compliance, resolve disputes, and provide documentation to insurers."
Description

Create an immutable timeline that records each broadcast: template version, final rendered content per channel, sender, targeted audience snapshot, delivery outcomes, opens/clicks where available, and acknowledgements. Link entries to the incident’s existing photo-timeline for a complete evidentiary record. Support export to PDF/CSV for owners and insurers, with permissioned access and redaction of PII as needed. Provide search and filters by property, date, incident type, and severity to quickly answer “who was told what and when.”

Acceptance Criteria
Localization & Accessibility-ready Messages
"As a tenant with limited English, I want outage updates in my preferred language and accessible formats so that I can understand what’s happening and what to do."
Description

Deliver localized content based on recipient language preferences with machine translation plus optional human review. Support right-to-left languages, plain-text fallbacks, high-contrast accessible email templates, alt text for images, and concise SMS variants within character limits. Ensure push notifications include summarized content and deep links to a mobile-friendly status page. Store language and accessibility preferences in the contact profile and apply them automatically on send.

Acceptance Criteria

Restore Predictor

Uses utility guidance, historical durations, and live tenant signals to forecast restoration windows. FixFlow adjusts SLAs, tenant time slots, and vendor scheduling to match reality—cutting no‑shows and expectation gaps.

Requirements

Outage Data Ingestion
"As a dispatcher, I want FixFlow to pull live outage and restoration guidance from relevant utilities so that my schedules and promises reflect real-world constraints."
Description

Integrate and continuously ingest guidance from utility providers (electric, gas, water), municipal outage feeds, and weather/advisory sources to enrich tickets with real-time and planned restoration signals. Normalize heterogeneous APIs, emails, and web-scraped notices into a common schema with source, timestamp, geographic coverage, and confidence. Implement rate limiting, retries, and data freshness SLAs; tag properties by service territory to scope relevant events. Provide a health dashboard and alerting on stale or degraded sources. Outcome: timely, high-quality external signals that ground Restore Predictor’s estimates in operational reality.

Acceptance Criteria
Historical Duration Warehouse
"As a product analyst, I want a trustworthy history of repair durations by segment so that forecasts can be trained and validated against reality."
Description

Build a curated data mart of historical ticket durations from intake-to-restore and segment by job type, severity, property profile, region, vendor, seasonality, and parts availability. Include feature engineering (e.g., hour-of-day, day-of-week, weather conditions) and data quality checks (missing fields, outliers). Expose performant query endpoints for model training and online lookups. Ensure retention, anonymization, and access controls to protect tenant PII. Outcome: reliable historical baselines to anchor forecasts and quantify variance by context.

Acceptance Criteria
Tenant Signal Capture & Normalization
"As a tenant, I want simple prompts to confirm when service is restored so that appointments and expectations adjust without me having to call support."
Description

Collect live restoration signals directly from tenants via the portal: quick status prompts (e.g., power back on?), photo/video confirmation, timestamped notes, and optional device readings when available. Implement lightweight nudges aligned to predicted windows, throttling to avoid notification fatigue. Normalize signals (deduplicate, geotag, verify metadata) and reconcile conflicting reports across units in the same building. Respect consent, localization, accessibility, and offline fallback. Outcome: fresh, ground-truth inputs that tighten prediction windows and reduce unnecessary truck rolls.

Acceptance Criteria
Restoration Window Prediction Engine
"As an operations manager, I want a reliable restoration window with confidence bands so that I can plan crews and set SLAs realistically."
Description

Create a hybrid forecasting service that fuses utility guidance, historical baselines, vendor capacity, travel time, and tenant signals to produce a restoration window and confidence interval per ticket. Support cold-start and data-sparse cases with rule-based fallbacks and regional priors. Provide online scoring with sub-second latency, versioned models, feature stores, and A/B toggles. Output includes best estimate, p50/p80 windows, risk flags (e.g., likely delay), and next-best-action recommendations. Outcome: accurate, explainable restoration windows that drive scheduling and communication.

Acceptance Criteria
Dynamic SLA & Scheduling Adjustments
"As a vendor coordinator, I want schedules to auto-adjust when forecasts change so that routes stay efficient and we avoid missed appointments."
Description

Automatically adjust ticket SLAs, tenant time slots, and vendor assignments when predicted windows shift. Enforce guardrails (cutoffs, maximum reschedules, tenant consent windows) to prevent churn. Integrate with calendar and dispatch systems to re-sequence jobs, fill cancellations, and surface overbooking risks. Provide what-if tools and bulk actions for managers. Outcome: fewer no-shows and tighter utilization by continuously aligning commitments with updated reality.

Acceptance Criteria
Confidence-Based Notifications & UX
"As a tenant, I want clear updates with the latest expected window and why it changed so that I can plan my day without surprise."
Description

Present predicted windows and rationale to tenants, owners, and vendors with clear language, confidence levels, and next steps. Trigger proactive notifications on material changes, respecting channel preferences (in-app, SMS, email) and quiet hours. Provide explainer snippets (e.g., utility update received) and one-tap actions to confirm availability or propose alternatives. Localize content and ensure WCAG-compliant design. Outcome: aligned expectations and reduced inbound inquiries through transparent, timely updates.

Acceptance Criteria
Prediction Audit Trail & Explainability
"As an owner, I want an auditable history of how a restoration estimate was produced so that disputes can be resolved quickly and fairly."
Description

Record a versioned audit log of each prediction, including input features, data sources, model version, produced windows, confidence, and triggered adjustments. Surface human-readable reason codes and feature contributions for support teams. Enable exportable, timestamped records that link to the ticket’s annotated photo-timeline to resolve disputes. Outcome: auditable, defensible decisions that reduce responsibility conflicts and speed issue resolution.

Acceptance Criteria

Pulse Check

Lightweight, one‑tap micro‑surveys to tenants in the zone confirm outage presence and when service returns. Responses refine the outage boundary, trigger auto‑resume on cleared buildings, and surface stragglers that need individual dispatch.

Requirements

Outage Pulse Campaign Orchestrator
"As a property manager, I want to launch a Pulse Check to tenants in an impacted area so that I can verify outage scope and track restoration without manual call trees."
Description

Creates and manages Pulse Check campaigns tied to a FixFlow incident or outage record, defining target zone (buildings, units, geofence), message templates, cadence, quiet hours, and stop conditions. Supports manual and API-triggered launch, automatic deduplication of recipients across overlapping campaigns, and idempotent resends for non-responders. Persists campaign configuration and state, tracks per-tenant delivery and response status, and emits events for downstream systems. Integrates with FixFlow’s property, unit, and contact directories and writes full campaign metadata to the audit trail.

Acceptance Criteria
One‑Tap Multi‑Channel Survey Delivery
"As a tenant, I want to answer a one‑tap survey on my preferred channel so that I can quickly report whether service is out or restored."
Description

Delivers lightweight micro‑surveys over push notifications, SMS, and email using tenant contact preferences and verification status. Messages contain localized, accessible one‑tap actions (e.g., “Still Out” / “Back On”) implemented as signed, expiring links and deep links that securely identify the tenant, unit, and campaign. Handles fallbacks across channels, retries with exponential backoff, delivery/bounce tracking, and opt‑out compliance. Integrates with messaging providers (e.g., APNS/FCM, Twilio, SES) and FixFlow’s notification service, and records message telemetry for analytics and auditing.

Acceptance Criteria
Boundary Refinement Engine
"As an operations analyst, I want the system to refine the outage boundary from tenant responses so that communications and actions stay targeted and accurate."
Description

Ingests survey responses in real time and updates an outage model at building and unit granularity. Applies clustering and confidence thresholds to refine the affected boundary, weighting recent signals more heavily and filtering noise and duplicates. Produces zone change events (additions/removals) and exposes current state via API and store. Optionally correlates with external telemetry (e.g., utility/vendor updates) to increase confidence. Integrates with FixFlow incidents to drive workflow transitions and reporting.

Acceptance Criteria
Auto‑Resume and Ticket Unhold
"As a property manager, I want tickets to auto‑resume when a building is confirmed restored so that vendors and tenants are updated without manual intervention."
Description

Automatically resumes paused work orders and vendor dispatch for buildings flagged as restored by the Boundary Refinement Engine. Enforces hysteresis and minimum confirmation counts to prevent churn, and supports rollback if subsequent responses indicate continued outages. Updates SLA timers, notifies managers, vendors, and tenants of status changes, and records all transitions in the audit log. Integrates with FixFlow’s ticketing, vendor assignment, and notification subsystems.

Acceptance Criteria
Straggler Detection and Individual Dispatch
"As a dispatcher, I want stragglers to be automatically surfaced and routed for individual dispatch so that lingering unit‑level issues are resolved quickly."
Description

Identifies units still reporting outages after a building is marked restored and escalates them for individual attention. Validates responses to reduce false positives, opens or updates tickets with prefilled context (timeline, prior outage, contact), prioritizes by risk (e.g., no heat, elderly occupants), and routes to the appropriate vendor. Sends confirmations to tenants, monitors progress, and closes the loop upon resolution while rate‑limiting to avoid vendor overload. Integrates with FixFlow dispatch, SLAs, and communications.

Acceptance Criteria
Live Ops Dashboard and Audit Trail
"As an owner or auditor, I want a live dashboard and auditable timeline of Pulse Checks and actions so that I can track decisions and demonstrate due diligence."
Description

Provides a real‑time dashboard showing campaign status, response rates, building/unit‑level heat maps, inferred boundaries over time, and resulting actions (auto‑resumes, escalations). Supports filtering by property, incident, time window, and channel, and provides exports and an API for reporting. Maintains a comprehensive, immutable audit trail of messages sent, deliveries, responses, inferences, and workflow transitions to support accountability and owner disputes. Enforces role‑based access and adheres to privacy controls.

Acceptance Criteria

Outage ProofPack

Auto‑compiles an audit‑ready record of the event: feed snapshots, cluster map, broadcast messages, paused dispatches, and resume logic. Export for owners and regulators to resolve responsibility disputes and document SLA exceptions with evidence.

Requirements

Outage Event Detection & Timeline Capture
"As an operations manager handling multiple properties, I want the system to automatically detect outages and create a precise start-to-end timeline so that I can coordinate responses and justify SLA pauses with confidence."
Description

Continuously monitors incident signals (tenant ticket spikes, vendor/utility APIs, inbound comms keywords, and regional alerts) to automatically recognize an outage affecting one or more units. Opens an outage record with precise start markers, updates with interim milestones, and closes with verified end markers. Merges duplicate detections, captures reason codes, and associates all affected tickets and units. Integrates with FixFlow’s ticketing to flag SLA clock pauses and links to annotated photo timelines for any related incidents.

Acceptance Criteria
Source Feed Snapshotting
"As a landlord, I want time-stamped snapshots of all relevant sources during an outage so that I have immutable evidence to resolve responsibility disputes later."
Description

At detection and on a configurable cadence, captures normalized data and visual snapshots of relevant sources (utility outage dashboards, vendor portals, weather/regional alerts, tenant reports, and emails/SMS). Stores raw JSON, rendered screenshots, and metadata (source, timestamp, request IDs, geo tags) in an immutable audit store. Handles retries, rate limits, and source authentication. Tags each artifact to the outage record and related tickets while enforcing PII redaction policies aligned with FixFlow’s privacy controls.

Acceptance Criteria
Geo Cluster Map & Impact Radius
"As a property manager, I want a cluster map showing which units are affected so that I can visualize impact, inform stakeholders, and prioritize actions geographically."
Description

Generates geospatial clusters of impacted units/buildings using addresses and lat/long, overlays utility service zones and vendor coverage, and stores a time-lapse GeoJSON of spread/containment. Produces static map images and embeddable tiles for the outage record and export. Supports filtering by property, vendor, and severity. Integrates with FixFlow’s unit registry and vendor routing to drive dispatch decisions and document the scope for auditors.

Acceptance Criteria
Broadcast Message Log & Templates
"As a small property manager, I want to send consistent outage updates and retain a verifiable log so that I can keep everyone informed and prove due diligence."
Description

Provides pre-approved outage templates (tenant, owner, vendor, regulator) with dynamic tokens (property, ETA, safety notes). Logs every outbound broadcast across channels (email, SMS, in-app), including content hash, recipients, delivery status, opens, and replies. Supports throttling, quiet hours, and opt-out compliance. Automatically associates all communications with the outage record and tickets to create a complete messaging audit trail.

Acceptance Criteria
Dispatch Pause & Resume Rules Engine
"As a coordinator, I want affected work orders automatically paused and cleanly resumed when the outage ends so that I avoid wasted vendor trips and maintain fair SLAs."
Description

When an outage is recognized, applies configurable rules to pause non-critical dispatches in the affected area, add clear reason codes, and notify vendors and tenants. Exempts life-safety and time-sensitive work. Resumes dispatches automatically upon verified recovery signals or manual override, recalculating SLAs with paused intervals. Integrates with FixFlow’s scheduling, vendor assignments, and ticket states, ensuring downstream workflows and messaging are updated in real time.

Acceptance Criteria
Audit-Ready Export Bundle
"As a compliance officer, I want a single export that compiles all outage evidence so that I can satisfy regulators and resolve disputes efficiently."
Description

Generates a shareable, audit-ready package (PDF and machine-readable JSON) containing the outage timeline, feed snapshots, cluster maps, broadcast logs, paused/resumed dispatch details, and SLA exception rationale. Includes cover summary, table of contents, cryptographic hashes, and configurable redaction. Provides expiring public links for owners and regulators and stores a copy in the outage record for future reference.

Acceptance Criteria
Evidence Integrity & Chain of Custody
"As an owner, I want confidence that the outage evidence hasn’t been altered so that it stands up to scrutiny in disputes or regulatory reviews."
Description

Applies tamper-evident hashing and trusted timestamps to all artifacts, writes events to an append-only audit log, and records access history for each export and snapshot. Supports integrity verification on demand and optional WORM storage for regulated clients. Respects data retention policies and regional privacy requirements while preserving evidentiary value for responsibility and SLA disputes.

Acceptance Criteria

Angle Assist

On-screen silhouettes guide required angles based on issue type (e.g., leak source, wide room context, fixture close-up). Live alignment cues (edge lines, leveler, and haptic confirmation) ensure the shot meets compliance before capture. Result: fewer retakes, faster approvals, and less tenant/vendor frustration.

Requirements

Issue-Type Angle Presets
"As a tenant reporting a maintenance issue, I want angle guidance tailored to my selected issue type so that I know exactly which photos to take and reduce back-and-forth."
Description

Define a configurable library of angle presets mapped to FixFlow issue categories (e.g., leak, appliance failure, structural damage). Each preset specifies required shot list entries (wide context, suspected source, close-up, serial/plate) and per-shot acceptance criteria (distance range, field-of-view silhouette, orientation, and minimum lighting). Expose admin tooling to manage presets and localize copy. During maintenance intake, the selected issue type auto-loads its preset, driving the on-screen silhouettes and acceptance thresholds to standardize evidence quality and reduce retakes. The presets integrate with the existing intake form and photo-timeline, ensuring consistent capture across tenants and properties.

Acceptance Criteria
Real-time Alignment Cues & Haptic Confirmation
"As a tenant capturing photos, I want clear visual and haptic cues in real time so that I can tell when my shot meets the requirements without guesswork."
Description

Render live overlays (silhouettes, edge alignment lines, and a horizon level) using the device camera feed and sensors (accelerometer/gyroscope) to guide framing. Provide visual convergence indicators (color/state change) and a short haptic pulse when the frame meets preset thresholds for angle, level, and distance. Include accessibility options for high-contrast overlays, adjustable cue intensity, and reduced-motion mode. This module is reusable across all presets and seamlessly plugs into the existing capture screen, minimizing cognitive load and improving first-pass photo quality.

Acceptance Criteria
Compliance Gate with Smart Override
"As a tenant in a constrained space, I want the option to override the angle requirement with a reason so that I can still submit usable evidence when perfect alignment is impossible."
Description

Block capture submission until each required shot reaches preset compliance thresholds, displaying real-time tips for correction (move closer, tilt up, improve lighting). Provide a guided override path when conditions prevent compliance (tight space, obstruction, safety), requiring a brief reason and extra optional notes. Flag overridden shots in metadata and notify reviewers, ensuring quality control without blocking progress in edge cases. Integrates with intake validation and vendor dispatch workflows to reduce rework while preserving flexibility.

Acceptance Criteria
Guided Multi‑Shot Checklist & Progress
"As a tenant following instructions, I want a clear checklist of required shots with progress indicators so that I don’t miss anything and can finish quickly."
Description

Present a sequenced checklist of required shots derived from the active preset, with per-shot instructions, visual examples, and progress tracking (e.g., 2/4 complete). Enable retake and reorder controls while preserving required dependencies (e.g., wide context before close‑up). Show per-shot compliance state before allowing completion. On finish, package the photos in order into the annotated photo-timeline, labeling each with its shot type for faster reviewer scanning and approvals.

Acceptance Criteria
Offline Capture & Deferred Sync
"As a tenant with poor reception, I want to capture guided photos offline and have them upload automatically later so that I can complete my report without waiting for a signal."
Description

Support full Angle Assist guidance without network connectivity by bundling presets and overlays locally and caching captured media plus compliance metadata on device storage. Queue uploads with retry and conflict handling, encrypting data at rest, and resume synchronization when connectivity returns. Provide user feedback on sync status and partial submission handling so that intake can proceed in low-signal buildings. Integrates with existing media pipeline and respects tenant privacy and storage limits.

Acceptance Criteria
Compliance Metadata & Audit Trail
"As a property manager reviewing a case, I want to see compliance details for each photo so that I can trust the evidence quality and approve work orders faster."
Description

Attach structured metadata to each captured photo, including preset ID, shot type, alignment score, level variance, distance estimate, lighting score, and whether an override was used with reason. Persist this data alongside timestamps in the photo-timeline to create an auditable record for owners and vendors. Expose metadata badges in review UIs and via API for downstream systems, enabling faster approvals, training improvements, and dispute resolution with objective capture quality evidence.

Acceptance Criteria

RegPack Templates

Prebuilt, jurisdiction-aware evidence packs map local code and inspection requirements to each issue type. FixFlow auto-selects the right template and updates as regulations change, so teams capture exactly what auditors expect without memorizing rules. Consistent, audit-ready submissions every time.

Requirements

Auto Jurisdiction Detection
"As a property manager, I want FixFlow to automatically identify the correct jurisdiction for each unit so that the correct regulatory template is applied without manual research or mistakes."
Description

Automatically determines the governing jurisdiction and applicable regulatory bodies for each property and unit based on verified address and geospatial boundaries, then maps those to the correct RegPack template set. Supports fallbacks to manual override, multi-jurisdiction edge cases (e.g., city vs. county precedence), and periodic revalidation to catch boundary or ordinance changes. Integrates with property profiles, caching and auditing the detected jurisdiction, and exposes a clear indicator of the active jurisdiction on each case. Ensures the correct evidence requirements load by default without end-user research.

Acceptance Criteria
Template Versioning & Auto-Update
"As a compliance lead, I want template versions to update automatically with a clear changelog so that we always meet current rules while preserving auditability of existing cases."
Description

Maintains versioned, jurisdiction-aware evidence templates for each issue type with atomic updates, detailed change logs, and safe-rollout controls. Cases lock to a specific template version upon creation for auditability, while newly created cases use the latest approved version. Includes automated feeds and monitoring for regulation updates, admin approval workflow, and notifications to stakeholders when material changes occur. Provides backward compatibility and migration tooling to reconcile in-progress cases if changes are legally required.

Acceptance Criteria
Jurisdiction-Aware Evidence Checklists
"As a field technician, I want a clear checklist that adapts to local rules so that I capture exactly the evidence needed the first time."
Description

Generates dynamic, step-by-step evidence checklists tailored to the issue type and local code requirements, including required photos, measurements, forms, timestamps, and metadata. Enforces conditional logic (e.g., severity thresholds, occupancy status) and validates inputs in real time to ensure completeness before submission. Presents plain-language guidance and examples to reduce errors, supports offline capture, and stores captured items directly into the annotated photo-timeline for a single source of truth.

Acceptance Criteria
Intake-Orchestrated Evidence Capture
"As a tenant submitting a maintenance request, I want guided prompts that tell me exactly what to provide so that my request is processed faster without back-and-forth."
Description

Integrates RegPack templates into the maintenance intake flow to auto-select the relevant template and drive data collection from tenants, techs, and vendors. Dynamically prompts for required photos, videos, annotations, and structured fields, blocking submission until minimum regulatory criteria are met. Leverages device capabilities (camera, geotag, timestamp), supports draft saves, and minimizes duplicate entry by reusing existing case data. Provides mobile-first UI with progress indicators to reduce abandonment and ensure compliant intake.

Acceptance Criteria
Audit-Ready Pack Builder
"As an operations manager, I want to export a complete, audit-ready packet so that I can submit to inspectors or insurers with confidence and minimal manual work."
Description

Assembles an auditable evidence pack per case that includes the completed checklist, annotated media, metadata (timestamps, location, user, device), signatures, and a change history. Exports to standardized formats (PDF, ZIP) with bookmarks and indexes, supports redaction of PII, applies watermarks and checksums, and stores an immutable copy linked to the case timeline. Enables secure sharing via expiring links and supports e-filing or SFTP/API submission to common municipal or insurance portals.

Acceptance Criteria
Compliance Rule Engine & Authoring Console
"As a compliance administrator, I want a rules authoring and testing console so that I can update templates quickly and safely when regulations change."
Description

Provides a declarative rules engine to encode jurisdictional requirements, deadlines, conditional evidence logic, and validation rules. Includes an admin console for authoring, testing, and publishing templates with role-based permissions, review workflows, and a staging environment. Offers a simulation mode to validate sample cases, unit tests for rules, telemetry on rule coverage, and feature flags to roll out changes by jurisdiction. Ensures transparency with rule IDs referenced in exported packs for traceability to source regulations.

Acceptance Criteria

Clarity Gate

Real-time quality checks flag blur, low light, glare, and obstructions, then suggest instant fixes (turn flash, step back, steady). Submissions are blocked until minimum clarity is met, preventing costly reinspections. Clear, defensible photos on the first try.

Requirements

Real-time Image Quality Scoring
"As a tenant capturing a maintenance issue, I want real-time feedback on my photo’s clarity so that I can correct issues before submitting and avoid rework or delays."
Description

Continuously evaluate camera frames for blur, low light, glare, and obstructions, producing a normalized per-dimension score and overall pass/fail in under 100ms per frame. Runs on-device/in-browser (WebGL/WebAssembly or native), with a server-side fallback when hardware acceleration is unavailable. Exposes an event stream and API consumed by the capture UI, submission gate, and logging services. Calibrated thresholds ensure consistent results across devices while minimizing false blocks. Improves first-pass photo quality, reducing reinspections and coordination overhead, and fits seamlessly into FixFlow’s maintenance intake flow.

Acceptance Criteria
Guided Capture Overlay
"As a tenant taking photos, I want clear, instant suggestions on how to improve my shot so that I can meet the required clarity on the first try."
Description

Display actionable, context-aware prompts and visual aids (e.g., "turn on flash," "step back," "steady your hand," glare angle hints) driven by the current quality scores. Provide lightweight overlays such as horizon lines, target boxes, and exposure/glare indicators, with haptic/audio cues where supported. Update guidance at interactive rates without blocking camera preview. Fully localized and accessible (WCAG-compliant text size, color contrast, and screen reader hints). Integrates with the scoring engine and respects admin-configured policies.

Acceptance Criteria
Submission Gate with Emergency Override
"As a tenant reporting an urgent issue, I want the app to prevent unclear submissions but allow a justified emergency override so that critical repairs aren’t delayed."
Description

Block submission until minimum clarity thresholds are met per dimension, showing pass/fail reasons and guidance to reach compliance. Provide an emergency override path for critical situations that captures a required justification (text/voice), timestamps, and auto-flags the case for review. Respect role-based permissions for who can override and configure thresholds. Log all gate outcomes and overrides for auditability and reporting. Seamlessly integrates with FixFlow’s ticket submission flow and vendor dispatch logic.

Acceptance Criteria
Smart Burst Best Frame Selection
"As a tenant with unsteady hands, I want the app to auto-select the clearest frame from a quick burst so that I don’t need multiple retakes."
Description

On shutter press, capture a short burst (e.g., 5–10 frames) and automatically select the highest-quality frame using the clarity scores, with optional slight exposure bracketing to mitigate low light and glare. Favor the clearest, least obstructed, and properly exposed frame without materially altering evidentiary content. Present the selected frame for confirmation and allow manual override. Optimize for low memory/CPU usage and ensure consistent performance on mid-tier devices. Integrates with the capture UI and timeline storage.

Acceptance Criteria
Audit-grade Metadata and Timeline Integration
"As a property owner or vendor, I want each accepted photo to include an auditable quality record so that we can resolve disputes quickly and confidently."
Description

Attach per-photo quality metrics, device and capture metadata (timestamp, exposure, flash state), and gate outcome to the FixFlow photo timeline as an immutable record. Surface these details in owner, tenant, and vendor views to support defensibility and reduce responsibility disputes. Provide optional watermarks or overlays (timestamp, location where permitted) and ensure metadata is tamper-evident. Comply with privacy settings and data retention policies, excluding failed pre-capture frames from storage.

Acceptance Criteria
Configurable Quality Thresholds and Policies
"As a property manager, I want to configure clarity standards and override rules so that submissions meet our quality bar without creating unnecessary friction."
Description

Offer an admin UI and API to configure clarity thresholds per category (e.g., plumbing, electrical), allowed override conditions, and guidance behaviors (e.g., enforce flash suggestion). Support environment-aware rules (day/night), device class adjustments, and versioned policy changes with rollback. Enforce role-based access control and provide safe defaults. Allow experimentation (A/B) to tune thresholds for pass rate vs. friction. All changes are logged and applied in real time to the scoring, guidance, and gate components.

Acceptance Criteria
Offline-capable and Cross-device Support
"As a tenant in a low-connectivity building, I want clarity checks and guidance to work offline so that I can submit usable evidence without waiting for a stable connection."
Description

Ensure guidance and gating operate without connectivity by running models locally, caching rules, and queuing submissions for later sync. Provide graceful degradation on low-end devices (reduced frame rate, simplified detectors) and a manual checklist fallback if real-time scoring is unsupported. Maintain a device compatibility matrix and automated capability detection to toggle features. On reconnection, sync photos, metadata, and logs reliably with retry policies.

Acceptance Criteria

Auto-Redact

AI automatically blurs faces, mail labels, screens, and other PII while preserving evidence areas. Policy settings let you enforce redaction for sensitive contexts (e.g., children’s rooms) to share images safely with owners, vendors, and inspectors. Boosts compliance and tenant trust—no manual edits required.

Requirements

Automatic PII Detection & Redaction Engine
"As a property manager, I want images and videos automatically redacted for PII so that I can safely share maintenance evidence without manual editing."
Description

Implements a high-accuracy computer vision pipeline that identifies and redacts personally identifiable information (PII) in uploaded media, including faces (adults/children), license plates, mail/package labels, monitors/screens, IDs, and house numbers. Supports images (JPEG/PNG/HEIC), PDFs (embedded images), and video keyframes with configurable blur/pixelation styles and intensity. Applies confidence thresholds and overlap rules to preserve evidence-relevant regions while masking sensitive areas. Processes in near real time to fit FixFlow’s maintenance intake flow and photo-timeline creation, with scalable inference (GPU-enabled server and optional edge runtime). Provides deterministic outputs and standardized masks to ensure consistent results across triage, vendor dispatch, and inspection sharing workflows.

Acceptance Criteria
Policy-Based Redaction Templates & Enforcement
"As a portfolio admin, I want to enforce redaction policies by property, room type, and workflow so that sensitive contexts are consistently protected."
Description

Introduces configurable redaction policies that can be assigned at portfolio, property, unit, and workflow step (e.g., intake, vendor dispatch, inspection). Policies allow admins to define sensitivity contexts (e.g., children’s rooms, bathrooms), object classes to redact, masking style/strength, and minimum confidence thresholds. Enforces mandatory redaction in designated contexts and supports exceptions with justification capture. Includes default templates compliant with common regulations and lets organizations clone/customize templates. Integrates with role-based access control to determine when policies are mandatory vs. advisory and ensures policies are applied automatically during upload and before any external sharing.

Acceptance Criteria
OCR/Text & Screen Content Redaction
"As a compliance officer, I want on-image text and screens redacted so that names, addresses, and account details are not exposed."
Description

Adds optical character recognition and layout analysis to detect and redact text-based PII within images, PDFs, and video frames, including names, phone numbers, emails, addresses, unit numbers, and account identifiers appearing on mail labels, packages, sticky notes, and screens. Detects screens/monitors and applies full-screen or region-only masks based on policy. Supports multilingual OCR and configurable dictionaries/regexes for jurisdiction-specific PII patterns. Coordinates with the core detection engine to avoid over-masking evidence areas, and exposes tunable settings per policy to balance privacy and usability.

Acceptance Criteria
Recipient-Aware Sharing & Export Redaction
"As a dispatcher, I want recipient-aware redacted versions generated on share so that vendors and owners see only what they’re authorized to see."
Description

Generates recipient-scoped, redacted derivatives automatically upon share/export based on recipient role (owner, vendor, inspector, tenant) and policy. Ensures unredacted originals never leave FixFlow; only derivative media is shared via secure links, timelines, or API. Handles batch exports and timeline compilations with consistent masks across all assets, embeds optional watermarks, and strips EXIF/metadata. Manages CDN caching and cache-busting so updated redactions propagate immediately. Provides guardrails that block share actions if required policies are not satisfied.

Acceptance Criteria
Redaction Review & Overrides UI
"As a property manager, I want to preview and tweak redactions before publishing so that evidence remains usable while privacy is maintained."
Description

Provides a lightweight review interface within the FixFlow media viewer and photo-timeline that previews redactions before publishing. Allows authorized users to adjust blur strength, add/remove masks, draw custom regions, and mark false positives/negatives with required justification. Includes before/after comparison, per-object mask toggles, keyboard shortcuts, and mobile responsiveness for field use. Supports batch actions across related media and records all overrides for auditability without altering the immutable original asset.

Acceptance Criteria
Immutable Audit Trail & Original Media Vault
"As an owner, I want an auditable record of redaction policies and changes so that disputes can be resolved with a clear chain of custody."
Description

Stores unredacted originals in an encrypted vault with strict access controls, per-tenant keys, and detailed access logs. Captures a tamper-evident audit trail including policy versions applied, model versions, detection confidence summaries, user overrides with justifications, timestamps, and recipient-specific derivative generation events. Supports exportable audit reports attached to work orders and inspection packets, enabling chain-of-custody proof during disputes or regulatory reviews. Implements retention rules and legal hold flags to manage lifecycle of originals and derivatives safely.

Acceptance Criteria

Gap Finder

A smart completeness checker compares captured media to the required angles, checklists, and evidence types (e.g., moisture reading, serial plate). It pinpoints exactly what’s missing and guides the next shot, enabling one-and-done submissions. Fewer back-and-forths, faster ticket closure.

Requirements

Configurable Evidence Templates
"As a property manager, I want to configure evidence requirements by issue type so that tenants submit complete, consistent documentation needed for faster, dispute-free repairs."
Description

Provide an admin interface for landlords and property managers to define, version, and manage evidence requirements per issue type (e.g., "leak under sink" requires: wide angle of cabinet, close-up of P-trap, moisture meter reading, serial plate of faucet). Supports conditional rules (requirements vary by property, fixture type, or tenant answers), default templates for common issues, and per-portfolio overrides. Templates specify required media types (photo/video), minimum quality thresholds (focus, exposure), angles, and structured data fields. Includes preview/testing mode, template versioning with audit history, and safe rollout (draft, staged, active). Integrates with Gap Finder’s guidance, detection, and scoring engines to drive what must be captured and when.

Acceptance Criteria
Angle Detection Engine
"As a tenant, I want the app to recognize whether my photo matches the requested angle so that I don’t have to guess and can capture the right shot the first time."
Description

Implement a computer-vision service that compares captured media against required shot angles and coverage defined in templates. Uses device orientation metadata, scene understanding, and pose/layout cues to determine whether the shot matches the requested perspective (e.g., wide room context vs. close-up of valve). Flags missing angles and duplicates, and returns structured feedback to the client (met/missing/low quality). Performs basic quality checks (blur, low light, obstruction) and suggests retakes. Designed for mobile performance with on-device heuristics and server-side verification. Exposes APIs consumed by the real-time guidance and completeness scoring modules.

Acceptance Criteria
Evidence Type Recognition (OCR & Object Detection)
"As a vendor, I want key details like serial numbers and moisture readings captured and readable so that I can arrive prepared with the correct parts and plan the fix without delays."
Description

Enable automated detection and extraction of required evidence types such as serial/model plates, moisture meter readings, circuit breaker labels, and fixture types. Combines object detection to confirm presence/legibility and OCR to parse text/numeric values into structured fields. Validates readings against expected ranges and flags illegible or incomplete captures with targeted retry prompts. Supports redaction of PII on plates before sharing externally. Outputs normalized data for timeline annotations and vendor dispatch packets.

Acceptance Criteria
Real-time Shot Guidance
"As a tenant, I want clear, step-by-step guidance on what to photograph next so that I can complete the submission in one pass without back-and-forth messages."
Description

Provide interactive capture guidance that translates template requirements and detection feedback into next-best-shot prompts. Shows visual overlays (ghost silhouettes, bounding boxes), direction arrows, and checklists; offers haptic/audio cues; and adapts prompts based on what’s already captured and what’s still missing. Works offline with queued validation, then reconciles with server responses when online. Localized copy and accessible UX (large touch targets, screen reader labels). Integrates tightly with the angle and evidence recognition engines for immediate feedback and retries.

Acceptance Criteria
Completeness Score & Submission Gate
"As a property manager, I want submissions blocked until required evidence is present or an override is documented so that downstream work can proceed without rework or disputes."
Description

Calculate a real-time completeness score per ticket against the active evidence template, displaying precisely which items are satisfied, missing, or low-quality. Prevent submission until required items meet acceptance criteria, with role-based override and reason capture for edge cases. Summarize unmet requirements with actionable prompts (e.g., “retake close-up of P-trap—image blurry”). Persist scoring outcomes and overrides for auditing and reporting. Expose a compact summary to vendors and owners to reduce clarification cycles.

Acceptance Criteria
Annotated Timeline Auto-Linking
"As an owner, I want an annotated media timeline linked to each ticket so that I have a clear, auditable record of what was captured and when."
Description

Automatically attach captured media and extracted data to the FixFlow ticket timeline with standardized annotations: shot type, satisfaction status, extracted readings/serials, capture timestamp, device metadata, and geo (if permitted). Maintain an immutable audit trail with versioned retakes and reasons. Provide exportable bundles for owners and insurers. Enforce role-based visibility so tenants, vendors, and owners see appropriate detail while sensitive data is redacted as configured.

Acceptance Criteria

ScaleCard Overlay

An AR overlay adds a ruler or standard object outline (credit card, dollar bill) to quantify damage size—mold patches, cracks, stain spread. Measurements are auto-embedded into the image and metadata to satisfy “document size” requirements. Objective sizing speeds triage and inspector acceptance.

Requirements

AR Scale Overlay & Calibration
"As a tenant reporting damage, I want a live overlay that measures size accurately so that I can document issues without guesswork and avoid back-and-forth."
Description

Adds an AR overlay of a ruler and standard object outlines (credit card, dollar bill) to quantify damage dimensions in real time. Detects surfaces and estimates distance to achieve measurements within acceptable error bounds under supported conditions. Provides guided alignment and live readouts for length, width, area, and perimeter. Supports manual calibration by aligning a known object, with confidence scoring and error prompts. Integrates into the FixFlow capture flow on iOS (ARKit) and Android (ARCore), gracefully degrading to an on-screen ruler when AR is unavailable.

Acceptance Criteria
Auto-Embedded Measurement Metadata
"As a property manager, I want measurements stored as metadata so that inspectors and insurers accept the photos without manual transcriptions."
Description

On capture, permanently embeds measurements and unit settings into the image as visible annotations and into EXIF/XMP metadata and a JSON sidecar, including dimension values, area, method (AR vs manual), calibration source, confidence, timestamp, device model, and app version. Associates the media with the related FixFlow ticket and workflow step, enabling deterministic downstream processing, audits, and search.

Acceptance Criteria
Triage Rules Powered by Measurements
"As a landlord, I want size-based auto-triage so that urgent issues are dispatched faster and minor issues are scheduled efficiently."
Description

Integrates captured size data into FixFlow’s triage engine to auto-route and prioritize requests based on objective thresholds (e.g., crack length triggers urgent inspection, mold area escalates to remediation vendor). Provides configurable rules per property/owner with default templates and displays machine-readable rationale in the ticket timeline to explain dispatch decisions.

Acceptance Criteria
Low-Light and Offline Capture Support
"As a tenant in a dark basement, I want reliable measurements and the ability to submit later so that my report doesn’t fail due to lighting or connectivity."
Description

Optimizes measurement capture in challenging conditions with torch control, exposure guidance, denoise, stability prompts, and low-light UI mode. Provides offline capture with local encryption and a retry queue for uploads, preserving measurement integrity and timestamps. Flags low-confidence measurements and suggests retakes or calibration assists, ensuring usable submissions when connectivity or lighting is poor.

Acceptance Criteria
Integrity and Anti-Tamper Audit Trail
"As an owner disputing responsibility, I want tamper-evident photos so that resolution decisions are based on trusted evidence."
Description

Generates a cryptographic hash of the image and measurement metadata at capture, stores a signed receipt server-side, and validates on upload to detect alterations. Applies optional visible watermark with capture time, location (if permitted), and measurement summary. Locks measurement fields from post-capture edits, recording any system-driven transformations in the ticket audit log to support dispute resolution.

Acceptance Criteria
Device Compatibility and Permissions
"As a tenant with an older phone, I want the feature to work or provide a clear fallback so that I can still submit usable evidence."
Description

Ensures support for a defined set of ARKit- and ARCore-capable devices, with graceful fallback experiences for unsupported models. Manages camera, storage, and location permissions with clear just-in-time prompts and privacy explanations. Implements a lightweight compatibility check and analytics to monitor accuracy by device class for continuous tuning and QA.

Acceptance Criteria
Inspector/Vendor Export and Sharing
"As an inspector, I want a standardized measurement report so that I can accept evidence without visiting or requesting re-measurements."
Description

Produces shareable artifacts for third parties, including a read-only web link and a PDF export that shows the original image, overlaid measurements, metadata summary, and measurement method and confidence. Supports redaction of personal information and batching multiple annotated images into a single report attached to the work order.

Acceptance Criteria

Inspector Ask

A secure, one-click request flow lets inspectors or owners request a specific follow-up shot or angle. FixFlow routes the ask with visual prompts to the right tenant or vendor and auto-tags the response to the checklist item. Targeted follow-ups without phone tag or guesswork.

Requirements

One-Click Request Link Generation
"As an inspector, I want to generate a one-click request for a specific follow-up shot so that the tenant can respond quickly without back-and-forth."
Description

Generate a unique, single-tap request link tied to a specific checklist item, embedding context such as requestor identity, unit, task ID, due date/time, and capture requirements. The link deep-links recipients into a lightweight capture experience (web/mobile) without login, optionally as a QR code for in-person visits. Supports prefilled instructions, localized content, and link expiry. Logs creation and dispatch events, and stores request metadata for tracking. Integrates with FixFlow incidents and checklist models to ensure requests are traceable and reusable as templates.

Acceptance Criteria
Secure Role-Based Access & Tokenized Requests
"As an owner, I want request links to be secure and revocable so that only the right party can submit the follow-up."
Description

Protect every request with short-lived, signed tokens scoped to the target checklist item and recipient, honoring FixFlow’s role permissions (owner, inspector, tenant, vendor). Enforce single-use or limited-use links, expiration, revocation, and rate limiting. Verify recipient identity via channel ownership (email/SMS) and optional PIN/one-time code. Prevent cross-unit data access and guard PII through least-privilege scoping. Provide admin controls to revoke or extend links and maintain security event logs for audits and compliance.

Acceptance Criteria
Visual Prompt Overlay & Guided Capture
"As a tenant, I want clear visual guidance on what to photograph so that I can capture exactly what the inspector needs."
Description

Present recipients with clear visual guidance at capture time: overlay outlines/arrows, example images, angle and distance hints, and step-by-step prompts. Support camera controls (flash, grid, orientation lock), multi-language text, accessibility (screen reader labels, high contrast), and low-bandwidth fallback. Allow inspectors to select from reusable prompt templates (e.g., "Valve close-up at 45°") or customize per request. Validate required steps before submission and gracefully handle multi-photo asks.

Acceptance Criteria
Smart Recipient Routing & Checklist Auto-Tagging
"As a property manager, I want responses automatically attached to the right checklist item so that I don’t have to manually organize files."
Description

Automatically determine the correct recipient (tenant or vendor) based on unit, assignment, and task ownership, with fallback contacts and business-hour rules. On submission, auto-associate received media and notes to the originating checklist item, thread the conversation, and update item status (e.g., Waiting on Follow-up, Received, Needs Review). Handle multiple responses with versioning and prevent misattribution across similar items. Notify the requester and related stakeholders and surface the response inline within the inspection task view.

Acceptance Criteria
Multi-Channel Delivery & SLA Reminders
"As an inspector, I want automatic reminders if the recipient hasn’t responded so that follow-ups complete on time."
Description

Deliver requests via SMS, email, and in-app push with channel preference and automatic fallback. Track delivery, open, and click events to drive a reminder cadence until the due date, respecting quiet hours and opt-outs. Allow requesters to set SLAs, reminder schedules, and escalation paths (e.g., alternate contact or vendor) when deadlines slip. Provide status visibility (Sent, Opened, In Progress, Overdue) in the request dashboard and surface blockers (undeliverable, bounced) with suggested next actions.

Acceptance Criteria
Media Quality Validation & Metadata Capture
"As a landlord, I want the system to verify photo quality and capture metadata so that the images are usable and trustworthy."
Description

Perform on-device checks for blur, low light, focus, and resolution thresholds based on the request type, prompting retakes or allowing overrides with justification. Capture and store metadata (timestamp, optional GPS with consent, device model, orientation) and embed it in EXIF while persisting structured fields server-side. Support efficient uploads with background retry, image compression, and originals retention policy. Present submitter with a confirmation preview and annotate with the requester’s instructions for clarity.

Acceptance Criteria
Audit Trail & Photo-Timeline Integration
"As a small property manager, I want follow-up requests and photos to appear in the unit’s timeline so that I have an auditable record for owners and tenants."
Description

Append request creation, dispatch, views, responses, approvals, and status changes to FixFlow’s annotated photo-timeline for the relevant incident/unit. Link each artifact to the checklist item and requester, preserving immutable timestamps and actor identities. Enable filtering by checklist item and export to PDF/ZIP for dispute resolution and owner reporting. Ensure consistent retention policies and GDPR/CCPA compliance for subject access and deletion requests while maintaining evidentiary integrity.

Acceptance Criteria

AutoMap Import

Drag in your CSV/XLSX/Sheets and let FixFlow auto-detect units, leases, and vendors across tabs, then map columns to the right fields. It de‑duplicates contacts and properties, validates addresses and phone/email formats, and previews changes before commit—cutting hours of cleanup and eliminating bad data from day one.

Requirements

Multi-Source Drag-and-Drop Intake
"As a property manager, I want to drag-and-drop my spreadsheets or connect Google Sheets so that I can quickly start importing without IT help."
Description

Enable users to upload CSV, XLSX, or connect Google Sheets via drag-and-drop or URL. Automatically detect encoding, delimiter, header rows, and enumerate tabs/sheets. Enforce file size/type constraints and handle anomalies such as merged cells and hidden rows. Provide progress indicators and resilient uploads with chunking and resume. Store files in encrypted, time-limited staging with role-based access and purge them per retention policy. Integrates with the AutoMap workflow as the first step, providing a normalized in-memory representation to downstream detection and mapping services.

Acceptance Criteria
Intelligent Entity Auto-Detection
"As an operations lead, I want FixFlow to auto-detect units, leases, and vendors across tabs so that I don’t have to manually classify each sheet."
Description

Infer entities (Units, Leases, Vendors, Tenants, Properties) across tabs using heuristics and pattern recognition based on headers, column value types, and foreign-key hints such as addresses, unit numbers, emails, and phone numbers. Link related rows across tabs (e.g., leases to units, vendor services to categories). Provide confidence scores and suggested entity types per tab with the ability to reclassify in the mapping UI. Output a draft schema graph to seed column mapping and relationship construction.

Acceptance Criteria
Assisted Column Mapping UI
"As an admin, I want suggested column mappings I can tweak and save as a template so that future imports are faster and consistent."
Description

Display suggested field mappings for each tab with type-aware autocomplete and inline validation. Allow manual remapping, splitting/combining columns (e.g., First/Last Name), and creating custom fields. Support reusable mapping templates per account and per source, persist partial progress, and provide back/forward navigation with keyboard shortcuts. Surface required fields and constraints inline. Integrates with auto-detection to prefill suggestions and with the validation engine to show issues in real time.

Acceptance Criteria
Data Validation and Normalization
"As a data steward, I want invalid addresses and phone/emails flagged and normalized so that our records are accurate from day one."
Description

Validate and normalize addresses, emails, phone numbers, dates, and currencies prior to import. Use address verification services, E.164 phone formatting, RFC-compliant email checks, and locale-aware date parsing. Enforce required fields per entity, detect invalid references, and standardize values such as state abbreviations and service categories. Provide row-level errors and warnings with suggested fixes and bulk actions, and block commits on critical errors while feeding results into the preview step.

Acceptance Criteria
Fuzzy Deduplication and Merge Rules
"As an owner, I want duplicates automatically found with clear merge rules so that I don’t end up with duplicate vendors and properties."
Description

Identify and merge duplicate contacts and properties using fuzzy matching on names, emails, phones, and addresses alongside deterministic keys. Allow tunable thresholds and tie-breakers, present merge suggestions for review, and support survivorship rules per field (prefer existing, most recent, or non-null). Safely link potential matches that need later confirmation and generate a dedup report, marking suppressed or merged rows accordingly.

Acceptance Criteria
Preview and Impact Summary
"As a manager, I want to preview exactly what will be created or updated before committing so that I can avoid bad imports."
Description

Provide a dry-run preview showing which entities will be created, updated, merged, or skipped, with counts and field-level diffs. Enable filtering by entity type, status, error category, and confidence level. Offer downloadable preview reports and row-level sampling to inspect details. Summarize downstream effects such as vendor invite counts and estimate import duration. No data is committed until the user confirms the import.

Acceptance Criteria
Transactional Import and Rollback
"As a property manager, I want imports to be transactional with rollback options so that mistakes can be safely undone."
Description

Execute imports in atomic, resumable batches with idempotency keys to prevent duplicate records on retries. Provide real-time progress, robust error handling with retry and backoff, and a complete audit log linked to the source file. Tag records with import batch metadata, allow time-bound rollback of newly created or updated records, and support re-running with the same mapping. Emit webhooks or events upon completion or failure for downstream processes.

Acceptance Criteria

Lease Lens

Upload lease PDFs or spreadsheets and automatically extract start/end dates, notice clauses, maintenance responsibilities, pets, and appliance coverage. Lease Lens preconfigures SplitCharge Rules and entry consent defaults, flags conflicts, and asks for quick confirmations—removing tedious manual setup while reducing future responsibility disputes.

Requirements

Multi-format Lease Ingestion & OCR
"As a property manager, I want to upload leases in any common format and get clean, searchable text so that I can onboard units without manual retyping."
Description

Accept lease files via drag-and-drop, mobile capture, or email-forwarding in PDF, image scans, DOCX, and spreadsheet formats. Perform secure upload with virus scanning, handle password-protected PDFs, run OCR with table/form detection, and normalize outputs into tokenized text with layout coordinates for provenance. Support multiple files and addenda per unit, automatic language detection, file size/page limits with graceful errors and retries, and persist originals with metadata. On success, emit a Lease Document Artifact to trigger the extraction pipeline and associate it with the property/unit context.

Acceptance Criteria
Clause & Field Extraction Engine with Confidence & Provenance
"As an independent landlord, I want Lease Lens to automatically extract key dates and responsibilities with confidence indicators so that I can trust the setup and catch issues quickly."
Description

Extract key terms including lease start/end dates, renewal options, notice periods, maintenance responsibilities, entry consent defaults, pet policy, appliance coverage, rent and deposit amounts, utilities, and contact info. Combine pattern/rule-based parsing with NLP models, normalize values to FixFlow schemas, and compute per-field confidence scores. Link each extracted value to source spans with page/line coordinates and clause snippets for transparency. Merge addenda, resolve duplicates, handle amendments by effective dates, and output a structured Lease Profile ready for downstream configuration.

Acceptance Criteria
Conflict Detection & Policy Alignment
"As a property owner, I want to be alerted when lease terms conflict with my default policies so that I can resolve discrepancies before maintenance requests arise."
Description

Compare extracted lease terms against property defaults and FixFlow policies to identify conflicts and ambiguities, including responsibility mismatches, entry consent discrepancies, pet policy clashes, overlapping or missing effective dates, and appliance coverage gaps. Assign severity levels, generate human-readable explanations with linked source clauses, and recommend resolutions. Surface conflicts in the review flow, expose an API for baseline policy retrieval, and block activation when critical conflicts remain unresolved.

Acceptance Criteria
Confirmation & Quick-Setup Wizard
"As an onboarding specialist, I want a fast review wizard that highlights the source text for each extracted field so that I can confirm accuracy and finish setup in minutes."
Description

Provide a guided review UI that groups extracted fields by category, displays confidence indicators, and highlights the exact source text on click. Enable one-click accept, inline edit, and mark-as-unknown actions, with validation for required fields. Offer batch apply to multiple units with similar leases, defaults for entry consent, and prompts for missing items. Support save-and-resume, keyboard shortcuts, mobile-friendly layout, and finalize to activate the Lease Profile. Write all decisions to an audit log and trigger downstream configuration when completed.

Acceptance Criteria
SplitCharge Rule Autoconfiguration
"As a landlord, I want SplitCharge rules to be auto-created from the lease so that repair cost responsibilities are enforced consistently without extra configuration."
Description

Translate maintenance responsibility and appliance coverage clauses into SplitCharge rules, creating charge triggers, percentages or caps, exclusions, and exceptions from clause tags. Validate rules to prevent contradictions and simulate example scenarios for user verification. Support reusable rule templates, owner overrides with rationale capture, and atomic publish alongside the Lease Profile so maintenance tickets immediately inherit correct cost allocation behavior.

Acceptance Criteria
Audit Trail, Provenance & Versioning
"As a compliance-conscious manager, I want a complete, versioned audit trail linking lease clauses to maintenance actions so that I can resolve disputes with evidence."
Description

Persist originals, OCR outputs, extraction results, user reviews, and final configurations as versioned artifacts with timestamps, actor attribution, and immutable hashes. Generate annotated clause highlights and a change log diff between versions, and enable export to PDF/JSON for off-platform records. Link the Lease Profile and its clauses to subsequent work orders and photo timelines to form an end-to-end, auditable record for dispute resolution.

Acceptance Criteria
Privacy, Security & Compliance Controls
"As a data steward, I want lease data to be protected and access-controlled so that tenants’ personal information remains secure and compliant."
Description

Detect and classify PII within leases, apply role-based access controls to sensitive fields, and enforce encryption in transit and at rest with expiring, signed file URLs. Provide data retention settings, consent logging, and access audit logs, with optional redaction for tenant/vendor sharing. Align controls with SOC 2 practices and support regional data residency to meet jurisdictional requirements.

Acceptance Criteria

Policy Blueprints

Apply prebuilt Cap Matrix and SLA templates tuned for property type, region, and risk tolerance. Get smart threshold suggestions based on your vendor rates and unit mix, clone policies across portfolios, and see projected impact before saving—so you launch with consistent, sensible guardrails in minutes.

Requirements

Template Catalog by Property Profile
"As a property manager, I want to quickly choose a prebuilt policy blueprint tailored to my property profile so that I can launch consistent guardrails without manual configuration."
Description

Provide a curated library of prebuilt Cap Matrix and SLA templates tuned by property type (e.g., single-family, multifamily, commercial), region (state/city), and risk tolerance (conservative/standard/aggressive). Users can browse, search, filter, and preview template contents (category spending caps, approval ladders, vendor dispatch rules, response/resolve SLAs) and select a baseline that auto-aligns with their FixFlow portfolio metadata (unit count, geo, currency). Templates are localized to regional norms and currency, map to FixFlow issue categories, and carry provenance metadata (source, last updated, change notes). The system periodically refreshes templates and notifies users of newer versions with a safe compare-and-apply flow.

Acceptance Criteria
Smart Threshold Suggestions
"As an owner, I want data-driven cap and SLA suggestions based on my costs so that policies match my real-world expenses and reduce over- or under-approvals."
Description

Ingest vendor rate cards, historical work-order costs, and unit mix to generate data-driven suggestions for category caps, approval thresholds, and SLA targets. Provide transparent rationale (inputs used, confidence bands, regional adjustments), support overrides with instant recalculation, and handle edge cases with low data via sensible template defaults. Model supports multiple vendor tiers, surcharges (after-hours/holiday), and property-specific variance. Suggestions update when rates or portfolio composition change and are accessible via UI and API for integration with custom cost models.

Acceptance Criteria
Policy Impact Simulator
"As a portfolio lead, I want to preview how a policy will affect costs and timelines so that I can choose settings that balance risk and speed."
Description

Run a non-destructive simulation that projects the effect of proposed policies on spend, approval volume, auto-dispatch rate, and SLA compliance using historical tickets (e.g., last 12 months). Present diffs versus current policy (auto-approvals, escalations, budget exposure bands, median time-to-resolution), allow side-by-side scenario comparisons, and export results. Simulations execute within strict performance bounds (synchronous under defined ticket thresholds; async with notification for larger datasets). Clearly surface assumptions and sensitivity controls (e.g., vendor rate variance). No changes are persisted until publish.

Acceptance Criteria
Bulk Clone and Portfolio Apply
"As an operator managing many buildings, I want to copy a finalized policy across them with minimal tweaks so that I can maintain consistency at scale."
Description

Enable cloning of a finalized policy blueprint to multiple portfolios/properties with variable tokens (currency, local caps, vendor pools) and mapping for differing issue categories. Provide a dry-run summary per target with detected gaps or conflicts, support scheduled rollouts and phased percentage deployments, and allow selective include/exclude of policy sections. Include per-portfolio rollback to the prior version and activity logging for traceability.

Acceptance Criteria
Policy Validation and Conflict Detection
"As an admin, I want the system to catch conflicts before publish so that policies work as intended and avoid operational breaks."
Description

Perform real-time validation to detect contradictory rules (overlapping caps, missing SLAs, cyclical escalations), regional compliance mismatches, and collisions with existing automation. Classify findings by severity, block publish on critical errors, and provide suggested fixes with direct links to affected fields. Expose validation results in the UI and via API, and run a quick smoke test against representative historical tickets to ensure the policy compiles and executes as intended.

Acceptance Criteria
Versioning and Auditable History
"As a compliance-focused owner, I want a complete policy history and the ability to revert so that I can audit decisions and correct mistakes."
Description

Maintain semantic versioning for policies with immutable audit records including author, timestamp, change summary, and a human-readable diff view. Link policy versions to ticket decision points so each action can be traced to the exact policy state active at that time. Support compare, annotate, and restore to previous versions, and include export of version history for compliance and owner reporting.

Acceptance Criteria
Role-Based Review and Publish Workflow
"As a team lead, I want a controlled review and publish workflow so that policy changes are vetted and released safely."
Description

Introduce a gated workflow (draft → review → approve → publish) with configurable roles and permissions, multi-approver quorum rules, due dates, and notifications. Provide a sandbox preview that renders policy behavior on sample or historical tickets prior to publish. Prevent enforcement until the policy is published, and capture approver comments and sign-offs in the audit trail.

Acceptance Criteria

Triage Sandbox

Run a safe, sample triage using realistic tickets generated from your unit and equipment profiles. Preview predicted cost ranges, auto‑assignments, and exception paths, then tweak thresholds and SLAs with instant ‘what‑if’ feedback—so you can validate fit and go live confident the workflow matches your reality.

Requirements

Synthetic Ticket Generator
"As a property manager, I want to generate realistic sample tickets from my units and equipment so that I can validate triage rules against scenarios that mirror my portfolio."
Description

Generate realistic maintenance tickets using a property's unit and equipment profiles, historical issue patterns, and seasonal context. The generator should attach sample photos, annotate symptoms, include structured metadata (location, priority, access constraints), and vary the quality of tenant-provided information to reflect real-world noise. Allow users to select scope (single unit, building, or portfolio), seed parameters, and volume. Tickets must be clearly tagged as simulated and isolated from production pipelines while remaining fully compatible with triage engines, dashboards, and reporting views.

Acceptance Criteria
Real-time What-if Tuning Panel
"As an owner-operator, I want instant feedback when I tweak thresholds and SLAs so that I can see how my changes affect assignments, costs, and timelines before going live."
Description

Provide an interactive panel to adjust triage thresholds, SLAs, routing rules, and escalation timers with immediate recomputation of outcomes on the active sandbox tickets. Display deltas versus a saved baseline (assignment, ETA, cost range, SLA risk) and highlight the specific rules impacted. Enforce a feedback latency target under 400 ms per rule change, and support undo/redo, draft saving, and named presets. All changes remain confined to the sandbox until explicitly published.

Acceptance Criteria
Cost Range Prediction Preview
"As a landlord, I want to preview cost ranges for simulated jobs so that I can assess budget impact and adjust policies accordingly."
Description

Compute and display predicted cost ranges for each sandbox ticket using vendor rate cards, travel time models, parts price lists, and job complexity signals. Present min/most-likely/max values with confidence bands and key cost drivers. Support market overrides, taxes/fees, and service-level surcharges. Indicate assumptions and data freshness, and allow manual adjustments for sensitivity testing without altering production data.

Acceptance Criteria
Auto-assignment Preview with Capacity
"As a small property manager, I want to see which vendors would be assigned and when so that I can verify staffing and coverage before enabling automation."
Description

Simulate vendor auto-assignment using skills, coverage zones, availability calendars, and performance scores. Surface conflicts, waitlist behavior, and fallback sequences, and show expected ETAs and communication templates that would be sent. Respect vendor opt-in/blacklist settings and per-job constraints such as licensing or insurance requirements. Provide side-by-side comparisons between current and proposed routing rules.

Acceptance Criteria
Exception Path Simulator
"As a dispatcher, I want to simulate common exceptions so that I can confirm our escalation paths and SLAs will hold under edge cases."
Description

Model exception scenarios including no-access, safety hazards, after-hours, warranty or owner-approval required, and parts backorder. Present branching workflows with timers, notifications, responsible parties, and SLA impacts. Allow forcing an exception on any sandbox ticket to preview escalations and breach risk, and record simulated outcomes for audit and training.

Acceptance Criteria
Sandbox Isolation and Versioned Publish
"As an admin, I want a safe, versioned space to experiment and a controlled publish process so that I can deploy triage changes confidently and revert if needed."
Description

Isolate sandbox operations and data from production to ensure no real messages, work orders, or vendor pings are sent. Track triage configuration as versioned drafts with diff views, change summaries, and impact analysis across sample tickets. Require role-based approvals to publish to production, support rollback to previous versions, and maintain complete audit logs of changes with timestamps and actors.

Acceptance Criteria

Vendor Sync

Bulk‑invite preferred vendors via email or SMS to self-complete profiles, service categories, coverage radius, and availability. Collect W‑9/COI with expiry tracking, baseline their SLA performance, and visualize a coverage heatmap to spot gaps—ensuring you’re dispatch‑ready and compliant before the first ticket.

Requirements

Bulk Vendor Invitations via Email/SMS
"As a property manager, I want to bulk‑invite vendors via email or SMS so that I can onboard my preferred network quickly without manual one‑by‑one outreach."
Description

Enable property managers to upload or paste vendor contact lists and send branded invitations via email and SMS containing secure, time‑boxed magic links to a self‑onboarding flow. Handle deduplication by email/phone, consent and opt‑out compliance for messaging, delivery/open/bounce tracking, automated reminder cadences, and resend with token regeneration. Provide rate limiting, localization, and templating controls. Maintain an audit trail of invite events per vendor and account, and surface real‑time invite status to ensure high conversion into dispatch‑ready vendors.

Acceptance Criteria
Vendor Self‑Service Profile Completion
"As a vendor, I want to self‑complete my profile, coverage, and availability so that I can start receiving appropriate jobs without back‑and‑forth."
Description

Provide a mobile‑friendly onboarding portal where vendors complete profiles including legal name, contact methods, tax classification, service categories (using FixFlow’s taxonomy), coverage area (radius from base address, ZIP lists, or map polygon), standard hours, emergency availability, blackout dates, notification preferences, base rates, license numbers, and attachments. Validate required fields, format, and geospatial inputs in real time; allow save‑and‑resume; and support multi‑location coverage. Store structured data to drive dispatch logic and heatmaps, and expose an activity log of profile changes for auditability.

Acceptance Criteria
Compliance Docs Collection & Expiry Tracking
"As a property manager, I want to collect W‑9/COI with automated expiry tracking so that I stay compliant and avoid dispatching non‑qualified vendors."
Description

Collect and securely store required compliance artifacts per vendor, including digital W‑9 capture and Certificate of Insurance (COI) uploads. Extract and validate key fields (e.g., TIN format, COI policy limits and expiration) via form constraints and OCR, allow manual correction, and apply configurable minimum coverage rules by service category. Track document status and expiration, send automated reminders before expiry to vendor and manager, and block dispatch when requirements are unmet. Encrypt documents at rest/in transit, restrict access by role, and preserve an audit trail of submissions and approvals.

Acceptance Criteria
Dispatch Readiness Gatekeeping
"As a dispatcher, I want the system to only show dispatch‑ready vendors so that I avoid failed assignments and rework."
Description

Compute a per‑vendor readiness state based on completion of profile, verified contact methods, selected service categories, defined coverage, valid non‑expired compliance documents, and availability. Expose readiness status and reasons, and only surface Ready vendors in dispatch selection for matching categories/locations/time windows. Support configurable overrides with justification, real‑time re‑evaluation on profile/document changes, and preflight checks in the dispatch flow to prevent assignment to noncompliant or out‑of‑coverage vendors.

Acceptance Criteria
Coverage Heatmap & Gap Analysis
"As a property manager, I want a heatmap of my vendor coverage so that I can spot service gaps and recruit where I’m exposed before issues arise."
Description

Visualize vendor coverage across managed properties by overlaying vendor service areas, categories, availability windows, and compliance state on an interactive map. Provide filters by trade, urgency (standard vs emergency), and time of day; display density and response capability; and highlight gaps where property clusters lack compliant, available vendors. Offer drill‑downs to vendor lists per region, exportable reports, and invitations shortcuts to recruit into uncovered areas. Optimize for performance with tiled geospatial layers and caching.

Acceptance Criteria
SLA Baseline & Vendor Scorecards
"As a property manager, I want objective SLA baselines and scorecards so that I can dispatch the best vendors and improve outcomes over time."
Description

Establish baseline service‑level metrics per vendor and category using FixFlow job history, including time‑to‑acknowledge, acceptance rate, time‑to‑ETA, on‑time arrival, completion time vs target, and first‑time fix rate. Compute baselines after a minimum sample size with default priors for new vendors, update metrics continuously, and present scorecards within Vendor Sync, dispatch ranking, and the heatmap overlays. Allow threshold alerts and export. Ensure data lineage and time‑windowed comparisons for fair, contextual evaluation.

Acceptance Criteria

Readiness Radar

A live checklist with a go‑live score that tracks data completeness, policy setup, vendor compliance, and test notifications. It pinpoints blockers, offers one‑tap fixes, and includes a ‘Test Dispatch’ dry run—guiding you to lift‑off inside an hour with no surprises.

Requirements

Live Readiness Checklist & Go-Live Score
"As a small property manager, I want a live readiness checklist with a go-live score so that I can see exactly how close I am to launching and what remains."
Description

Implements a dynamic, real-time checklist that aggregates readiness across four pillars—Data Completeness, Policy Setup, Vendor Compliance, and Notification Tests—and computes a single go-live score. The checklist updates instantly on data changes, shows item-level status, progress by category, and highlights the minimum threshold required for launch. It supports multi-property contexts, persists progress per account, and provides an at-a-glance dashboard with accessible UI, localization-ready copy, and analytics hooks to track completion rates. Integrates tightly with FixFlow setup flows to reflect readiness state and reduce time-to-launch.

Acceptance Criteria
Data Completeness Scanner
"As an independent landlord, I want automatic detection of missing setup data so that I can quickly fill gaps and avoid go-live surprises."
Description

Creates a rules-driven scanner that evaluates critical setup entities—properties, units, tenants, contact methods, vendor roster, and owner/payment preferences—for presence, validity, and consistency. Flags gaps (e.g., missing unit contacts, invalid phone formats), suggests best-next actions, and provides deep links to the exact form/field to resolve. Runs automatically on relevant field changes and on-demand, supports CSV/import validation, and exposes a service API for other modules. Results feed the checklist and go-live score to prevent launch delays due to missing data.

Acceptance Criteria
Policy Setup Wizard & Templates
"As a property manager, I want a guided wizard to set maintenance policies so that dispatch and approvals work correctly from day one."
Description

Delivers a guided, step-by-step wizard to configure maintenance triage policies, SLAs, escalation paths, operating hours, approval thresholds, budget caps, and category routing. Includes industry-tested templates for common scenarios, inline validations, and an outcome preview that shows how a sample request would route. Supports per-property overrides, versioning with audit history, and instant propagation to the readiness score. Integrates with FixFlow’s dispatch engine to ensure correct behavior at launch.

Acceptance Criteria
Vendor Compliance Verification
"As a landlord, I want vendor compliance status visible with clear blockers so that I only dispatch to vetted, covered vendors."
Description

Builds automated checks for vendor onboarding status, including W-9 collection, insurance certificate upload with expiry tracking, service area coverage, contact channel verification, and signed vendor agreement. Surfaces pass/fail status per vendor, blocks dispatch to non-compliant vendors, and offers one-tap reminders and document requests. Integrates with document storage, optional third-party insurance verification, and the vendor directory. Compliance outcomes roll up into the readiness checklist and score.

Acceptance Criteria
Test Notification & Dispatch Simulator
"As a property manager, I want to run a test dispatch dry run so that I can verify routing and notifications before going live."
Description

Provides a safe, sandboxed dry run that exercises triage rules and sends test notifications (email/SMS) to designated recipients without creating live work orders. Measures delivery, latency, and routing accuracy, with retry logic and deliverability checks. Generates a timestamped test report and annotated event timeline, then feeds pass/fail into the checklist. Includes one-tap start from the Readiness Radar and configurable test scenarios per property.

Acceptance Criteria
Blocker Detection & One-Tap Fixes
"As a busy landlord, I want one-tap fixes for readiness blockers so that I can launch within an hour without hunting through settings."
Description

Aggregates blockers from scanners, policy validation, vendor compliance, and test outcomes into a prioritized list with context and impact. Offers inline quick actions (e.g., add missing contact, request vendor COI, enable escalation rule) that open targeted modals or auto-populate forms to minimize clicks. Completing a fix immediately updates the readiness score and checklist item via event-driven updates. Supports bulk actions, assignment to team members, and in-app reminders to accelerate go-live.

Acceptance Criteria

Product Ideas

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

Access Key Handshake

Issue expiring access codes and verify vendor identity at the door. Entry events auto-attach to tickets, cutting lockouts and access disputes.

Idea

ChargeGuard Auto-Approvals

Enforce per-unit spend caps with auto-approvals and instant owner pings for exceptions. Line-item reason codes flag overages before invoices hit.

Idea

Tenant Self-Fix Coach

Interactive fix guides for simple issues (clog, pilot light, tripped breaker) with parts links and upload prompts. Prevents unnecessary dispatch and builds proof.

Idea

Vendor Capacity Radar

Match jobs to vendors by live capacity, travel radius, and past SLA performance. ETAs auto-update tenants, slashing no-shows.

Idea

Outage Neighborhood Radar

Detect building- or block-wide outages by clustering tenant reports and utility feeds. Pause duplicate dispatches, send bulk updates, and reschedule automatically.

Idea

Compliance Photo Prompts

Force required photo angles and checklists per issue type (leaks, mold, heat). Time-stamped prompts create audit-ready evidence that satisfies inspectors.

Idea

Onboarding Lift-Off Wizard

One-hour setup wizard importing units, vendors, and leases from spreadsheets. Preloads spend thresholds, SLAs, and runs a sample triage simulation to validate fit.

Idea

Press Coverage

Imagined press coverage for this groundbreaking product concept.

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.