Live vs Periodic Fields

17 min read•docs/LIVE-VS-PERIODIC-FIELDS.md•

Live vs periodic fields matrix (T1.9)

Status: locked for test (implement agent attestation 2026-08-12)
Purpose: Decide, for every P0 entity.field, whether the value is evented (live), import (periodic), or manual. Unblocks T1.10 freshness targets and tells ingest which path is allowed.
Related: SOURCE-INVENTORY.md (T0.5), SOURCE-OWNERSHIP.md, SOURCE-EVENT-MAPPING.md, PORSLINE-FORMS.md (T1.5), DATA-MODEL.md, SCHEMA.md, RISK-RULES-V1.md, ops/CSV-IMPORT.md (T2.8)


1. Classes (closed set)

Every P0 field uses exactly one primary class. Supplemental paths are notes, not a fourth class. The class value is never unknown.

Class Meaning Write path Not allowed
evented Live product / Orbit fact. Collector is the only event write ingress (ADR 0002). Includes Orbit derived projections (SYS-01, T2.4, T2.9, T3.4) rebuilt from canonical events. Backend SDK / outbox, form webhook → collector, or Orbit job → collector CSV as the source of truth for booking, payment, session, pause, completion, or stop
import Periodic batch that is not yet (or not primarily) on the live event path. Job audits rows and, if an event is produced, POSTs the collector — it never writes canonical_event directly (T2.8). Orbit import job (apps/import-job) Authoritative P0 booking / payment / session facts
manual Human-authored in Orbit (staff UI / API). Not rebuildable from the event log (SCHEMA.md rebuild boundary). apps/web operational writes (action, insight) Using staff notes as a substitute for Simiaroom backend outcomes

Derived vs evented: client.current_stage, session_count, risk_level, and other T2.9 / T3.4 serving fields are evented. They are projections of canonical events, not a separate class.

CDC (inventory #9, blocked) is reconciliation, not a field class. When unblocked it re-emits the same evented facts with the same source + source_event_id (SOURCE-EVENT-MAPPING.md).


2. Latency expectations per class

Aligned with TECHNICAL-ARCHITECTURE.md §5 (freshness) and VOLUME-AND-RETENTION.md §6 (dashboard p95). Numeric DQ gates (evented accept < 5 s, event lag < 24 h, completeness ≥ 99%) are locked in DATA-QUALITY-BAR.md (T1.10). These rows remain the class contracts.

Class Ingest freshness (source → collector / store) Serving freshness (decision-loop screens) Dashboard query p95 (not ingest lag)
evented Same-day required for P0 authoritative outcomes. Collector HTTP accept is seconds; profile/risk recompute follows SYS-01 (minutes after the triggering event in normal ops). At-risk / Client 360 / journey / retention read precomputed profile + snapshots, not raw replay. Timeline ≤ 2 s; at-risk list ≤ 3 s; funnel / retention ≤ 5 s
import Near-daily acceptable (architecture §5). Shipped P0 feed ops_support_ticket is weekly (CSV-IMPORT.md). Form CSV (until webhook) is weekly. One-time historical backfill is off-peak, not a freshness SLO. After collector ingest + SYS-01, same serving path as evented. Ops extras that stay audit-only (open tickets) appear on import reports, not as risk facts, until mapped to an event. Same screen p95 after the batch has been ingested
manual Immediate on staff save (operational Postgres). Immediate on /at-risk assign/close and Client 360 actions (T3.8). Same as evented screens that join action

Late events are first-class: preserve occurred_at, sent_at, received_at (DATA-MODEL.md §9). Freshness is measured on received_at vs occurred_at (T2.11), not by silently rewriting history.


3. Import feeds and owners

Every import field below maps to one of these feeds. Owners use T0.5 team slugs (SOURCE-INVENTORY.md). Named Simiaroom contacts remain TBD; escalation: CX Orbit technical lead → Simiaroom engineering lead.

Feed ID What it carries Cadence Owner (file / vendor) Owner (Orbit job) Inventory # P0 status
ops_support_ticket Call logs, tickets, complaint status, manual follow-ups that are not yet evented (architecture §4.4). Resolved rows with case fields may plan internal_case_resolved. Weekly Simiaroom ops (CSV export) cx-orbit-ops / apps/import-job 14 + §4.4 Shipped (T2.8). Job granted; live ops CSV requested
porsline_form_export FDB-02 / FDB-04 / FDB-07 responses until Porsline webhook is granted Weekly (until webhook → evented) cx-orbit-data + Simiaroom ops cx-orbit-data (T2.7) 11 requested — P0 mitigation; join keys in PORSLINE-FORMS.md; T2.7 importer
myoutcomes_form_export Same FDB types; alternate, not a second primary Same as Porsline cx-orbit-data + Simiaroom clinical cx-orbit-data (T2.7) 12 requested — do not run as P0 SoT. T1.5 locked Porsline as primary
assessment_legacy Historical assessment_completed until assessment SDK is live One-time / as needed assessment-team cx-orbit-data 2 Mitigation only. Primary class remains evented (simiaroom_assessment)
churn_reason_historical Historical CHR-02 / CHR-06 ledgers / offboarding forms One-time / as needed clinical-team + cx-orbit-data cx-orbit-data 7, 8 Mitigation only. Primary class remains evented (simiaroom_clinical)

Not import feeds (locked): bookings, payments, sessions, pause, treatment completion, therapist selection. Those stay evented even if CDC/import is used later for backfill — backfill must reuse the producer source + source_event_id (SOURCE-OWNERSHIP.md).


4. P0 entity coverage

DATA-MODEL §1 entities. Physical tables: SCHEMA.md / packages/db. Generic aliases: Customer=client, Provider=therapist, Interaction=session.

Entity Table P0 decision-loop? Primary class (entity)
Client client Yes (360, journey, retention, at-risk) evented (derived profile)
Therapist therapist Yes (join key; T3.5 depth is P1) evented
Session session Yes evented
Booking booking Yes evented
Payment payment Yes evented
Assessment assessment Yes (funnel assessed) evented
FeedbackResponse feedback_response Yes when present (SIG-FDB-*; missing ≠ trigger) import (P0) → evented when webhook granted
Insight insight No (P1 T3.7 shipped /insights) manual
Action action Yes (T3.8 assign/close) manual
Event canonical_event Yes (timeline / rebuild) evented
IdentityLink identity_link Yes (identified funnel; incomplete identity excluded) evented
RawEvent raw_event Infrastructure evented
EventQuarantine event_quarantine Infrastructure evented
RiskSnapshot risk_snapshot Yes (explainability) evented (derived)

Import audit tables (import_batch, import_row) are the import class’s own audit, not P0 decision fields.


5. Matrix — `entity.field` → class

Legend: P0 decision = used by journey (T3.2), retention (T3.3), at-risk (T3.4), Client 360 (T2.10), or actions (T3.8). Class is never unknown.

project_id, created_at, and updated_at on event-backed tables are Orbit serving metadata written with the projection (evented). On action / insight they are manual.

5.1 Client (`client`) + derived profile

Field Class P0 decision Source / notes
client_id evented Yes Identity from authentication_succeeded / identity_link_created (simiaroom_auth, inventory #1)
current_stage evented Yes T2.9 from journey events (JOURNEY-STAGE-MACHINE.md)
current_therapist_id evented Yes therapist_selected / later session+booking (simiaroom_matching #3)
session_count evented Yes Count of session_completed only (T2.4)
last_session_at evented Yes Last session_completed
days_since_last_session evented Yes Derived at as_of from last_session_at
next_session_booked evented Yes Open booking_confirmed with slot ≥ as_of
established_cadence_days evented Yes Observed median gap (T2.4) or declared on pause event; not import
current_pause_flag evented Yes therapy_pause_declared without later resume/complete (simiaroom_clinical #7)
expected_return_date evented Yes Pause-event property (not a client column today; T2.9/T3.4 input). Fallback 14 UTC days if missing is a rule, not an import
completion_flag evented Yes treatment_completed (#7)
therapist_change_count evented Yes CHG-01/02 + rematch (simiaroom_matching #3)
last_meaningful_event_at evented Yes T2.9 from SYS-01 trigger set
risk_level evented Yes T3.4 risk_v1 (derived). Storage may be the enum value unknown when unscored — that is a level, not a field class
risk_reasons evented Yes T3.4 composition
risk_rule_version evented Yes Written by T3.4 (risk_v1)
Identity refs (user_id / anonymous_id) evented Yes identity_link + event envelope; not CSV
Segment attrs (channel, issue_type) evented Yes (T3.2 optional filters) channel / auth_method on identified events; issue_type on assessment_completed. Null → drop out of that filter (METRICS-AND-RISK.md §3) — still classified

5.2 Therapist (`therapist`)

Field Class P0 decision Source / notes
therapist_id evented Yes Matching / session / booking producers (#3, #4, #6)
specialty_tags evented No (T3.5 P1) Matching service when available; omit rather than invent. Not import

5.3 Session (`session`)

Field Class P0 decision Source / notes
session_id evented Yes simiaroom_sessions #6
client_id / therapist_id / booking_id / payment_id evented Yes Same producers; join keys
session_number evented Yes T2.4 continuum (not reset on rematch)
status evented Yes session_completed / no-show / attendance issue
scheduled_start_at evented Yes Booking/session scheduled slot
completed_at evented Yes session_completed
attendance evented Yes SES-06 / SES-08 / SES-S01. Browser session_joined is non-authoritative (P1)
gap_from_previous_days evented Yes T2.4 derived
therapist_changed_since_previous evented Yes T2.4 derived
feedback_linked evented Yes Set when a feedback row joins; feedback payload class is import until webhook
continuation_status evented Yes Derived from pause/stop/complete/next booking

5.4 Booking (`booking`)

Field Class P0 decision Source / notes
booking_id / client_id / therapist_id / payment_id / slot_id evented Yes simiaroom_booking #4
status evented Yes booking_confirmed / booking_cancelled
scheduled_start_at evented Yes Slot start (scheduling privacy class)
cancel_reschedule evented Yes Cancel actor/reason on BKG-S04

Browser BKG-01/05/06 are behavioral only — they do not write these fields.

5.5 Payment (`payment`)

Field Class P0 decision Source / notes
payment_id / client_id / booking_id / session_id evented Yes simiaroom_payments #5 (gateway #10 feeds the handler, not Orbit)
amount / currency evented Yes PAY-06 / PAY-07
status evented Yes Succeeded / failed — never from checkout UI (PAY-04)
package evented Yes Payment verification properties
discount / refund evented Yes Payment backend; refund is a compensating event, not a silent overwrite

5.6 Assessment (`assessment`)

Field Class P0 decision Source / notes
assessment_id / client_id evented Yes simiaroom_assessment #2
method evented Yes assessment_completed
progress evented Funnel uses completion, not in-progress Live completion is evented. ASM-02/04 browser progress is P1 behavioral
completed_at evented Yes ASM-09. Supplemental import: assessment_legacy until SDK live — does not change primary class

5.7 FeedbackResponse (`feedback_response`)

Field Class P0 decision Source / notes
feedback_id import Yes when present Feed porsline_form_export (primary) or myoutcomes_form_export (alternate). Target class evented when inventory #11/#12 webhook is granted
client_id / session_id / therapist_id import Yes (join) PORSLINE-FORMS.md join keys; T2.7 importer. Missing join → quarantine, not a silent client
form_type / form_version import Yes Form catalog (PORSLINE-FORMS.md)
scores import Yes (SIG-FDB-LOW / DECLINE) Restricted. Missing scores do not fire signals
free_text import No (restricted; not a risk input) Restricted storage; not a P0 decision field
imported_category import No (P1 text themes) Rule/keyword/LLM-light — T3.6
submitted_at import Yes Form occurred_at / submitted timestamp

P0 rule: do not block at-risk or timeline if feedback is empty (empty.feedback = true on Client 360).

5.8 Insight (`insight`) — P1 entity, class locked

Field Class P0 decision Source / notes
insight_id / title / severity / segment / evidence / suggested_action / status manual No Semi-manual (T3.7 /insights). Not evented. source=insight actions are T3.10 (P1; not the P0 at-risk loop)

5.9 Action (`action`)

Field Class P0 decision Source / notes
action_id / title / source / linked_client_id / linked_insight_id / owner / priority / status / result / completed_at manual Yes T3.8 staff UI/API (client_risk / manual). T3.10 allows source=insight + linked_insight_id from /insights
Canonical INT-01 / INT-03 / INT-09 evented Yes (SIG-FOLLOWUP) Orbit Actions → collector (cx_orbit_system #14). Supplemental import: resolved ops_support_ticket rows may plan internal_case_resolved (T2.8). Open/in-progress tickets stay audit-only

T3.8 today persists operational rows and does not yet emit INT-03/INT-09. The class is still evented for those canonical types (ownership + mapping). Until emit ships, SIG-FOLLOWUP only fires from fixtures or import-planned INT-09 — that is a residual, not an unclassified field.

5.10 Event, identity, ingest, risk snapshot

Entity.field Class P0 decision Source / notes
canonical_event.* evented Yes Collector mapping from accepted raw
identity_link.* evented Yes AUTH-04 + T2.3 job (simiaroom_auth #1)
raw_event.* / event_ingestion_request.* / event_dedup_* evented Infra Collector only
event_quarantine.* evented Infra Collector reject/quarantine path
risk_snapshot.level / reasons / rule_version / source_event_id / computed_at evented Yes T3.4 append-only audit
import_batch.* / import_row.* import Audit T2.8; not decision facts
source_reconciliation_run.* evented DQ (T2.11) Orbit ingest job; CDC still blocked (#9)

6. At-risk inputs (`risk_v1`) — every input has a class

Authoritative input list: RISK-RULES-V1.md §2. Test Agent check: no row without a class.

Input Class Producer / feed Signal(s)
current_stage evented T2.9 from journey events Eligibility / churned queue
session_count evented session_completed (#6) Eligibility (need ≥ 1)
last_session_at evented session_completed Gap math
days_since_last_session evented Derived at as_of SIG-GAP-*, SIG-NO-BOOKING
established_cadence_days evented T2.4 / pause properties SIG-GAP-CADENCE / LONG / FALLBACK
next_session_booked evented Future booking_confirmed (#4) SIG-GAP-LONG copy, SIG-NO-BOOKING
current_pause_flag evented therapy_pause_declared (#7) Suppressions / cap
expected_return_date evented Pause record properties SIG-GAP-PAUSE-BREACH
completion_flag evented treatment_completed (#7) Hard suppress
Recent payment_failed / payment_succeeded evented PAY-07 / PAY-06 (#5) SIG-PAY-FAIL
Recent booking_cancelled / session_no_show_recorded evented BKG-S04 / SES-08 (#4, #6) SIG-NOSHOW
therapist_change_count / therapist_change_* evented CHG-01/02 (#3) SIG-THERAPIST-CHG
Feedback scores / session_dissatisfaction_reported import porsline_form_export (primary). Target evented when #11 webhook granted. Missing ≠ trigger SIG-FDB-LOW / DECLINE / DISSAT
client_contact_attempted / internal_case_resolved evented Orbit Actions → collector (#14). Supplemental import ops_support_ticket for resolved extras SIG-FOLLOWUP
therapy_stop_declared evented simiaroom_clinical (#7). Supplemental import churn_reason_historical for backfill only SIG-STOP
unplanned_gap_detected (CON-S01) evented Orbit T2.4 — corroboration only, not a required input SIG-GAP-*

as_of is the report clock, not a stored field — not classified.


7. P0 decision fields — none left unclassified

Closed list used by the P0 loop. Every row has class evented, import, or manual.

Decision use Fields Class
Identity / funnel entry client_id, identity link, channel evented
Journey spine assessment complete, therapist selected, booking confirmed, payment succeeded, session completed evented
Retention / session number session_number, session_count, completed_at, continuation flags evented
Pause / complete / stop current_pause_flag, expected_return_date, completion_flag, therapy_stop_declared evented
At-risk score All §6 inputs except feedback evented
At-risk score (optional quality) Feedback scores / FDB-07 import
At-risk follow-up signal INT-03 / INT-09 evented (+ import supplemental)
At-risk serving risk_level, risk_reasons[], risk_rule_version, risk_snapshot.* evented
Ops action loop action.* manual
Ops extras not in Actions UI Ticket/call/complaint rows import (ops_support_ticket)

8. Alignment with T0.5 source inventory

Inventory # System How this matrix uses it
1–8 Simiaroom backends evented primary for identity, assessment, matching, booking, payment, session, clinical lifecycle
9 Product DB CDC Blocked — not a field class; future reconciliation of evented facts
10 Payment gateway Feeds payments-team handler; Orbit still evented from #5
11–12 Porsline / MyOutcomes import until webhook granted; then evented
13 Collector Ingress for all evented (and import-emitted) events
14 Orbit store + jobs evented derived + INT-*; manual actions/insights; import job owner for ops_support_ticket

No fantasy sources. Access states stay as in the inventory (requested / blocked / granted).


9. Out of scope (explicit)

Item Why deferred
T2.7 form importer implementation P1 task; this matrix only locks class + owner + cadence for FDB fields. Catalog: PORSLINE-FORMS.md
Emitting INT-03/INT-09 from T3.8 Class is evented; emit is a later wiring residual
Browser SDK fields (ASM-02/04, BKG-01/05/06, PAY-04, SES-04, RET-01) P1 behavioral; non-authoritative; do not write P0 current-state facts
ClickHouse / sub-second BI Capacity guardrail; ingest class ≠ query engine
Using CSV for booking/payment/session Forbidden — would contradict T0.6 producer-of-record

10. Sign-off

Role Name Date Status
Data lead (cx-orbit-data) TBD — stakeholder sync — Pending named signatory
Eng lead (CX Orbit technical lead) TBD — stakeholder sync — Pending named signatory
Implement agent (T1.9 deliverable) cx-orbit-implement-task 2026-08-12 Matrix complete; no P0 decision field unclassified; ready for Test Agent

References