Skip to content

SessionState

session.getSnapshot() returns a SessionState. Most UIs never read it directly: pass it to toScreen and fieldState.

  • phase: "idle" | "starting" | "questioning" | "quoting" | "quoted" | "failed" | "handoff".
  • vertical, questionnaireId.
  • questions: every question seen, by name.
  • sections: the ordered sections, cached from the first response.
  • order: question names, first seen first.
  • outstanding: names the latest response still asks for.
  • values: the latest local value per name. PII: never log.
  • sent: the last value the server acknowledged per name. Pending = differs from values.
  • errors: server errors by name.
  • ready: the server offers quotes. Optional questions may still be outstanding.
  • sync: { status: "idle" | "pending" | "syncing" } or { status: "error", error }.
  • quotes: undefined, or one of:
    • { status: "blocked", missing }: quotes requested before ready.
    • { status: "quoting" }
    • { status: "quoted", quoteSet }
    • { status: "failed", reason: "quote_failed" | "timeout" | "error", error }
  • search: trade search results by name: { status: "loading" | "done" | "error", text, results, ... }.
  • handoffUrl: set on handoff.
  • error: { action: "start" | "selectQuote", error } or undefined.
idle ─▶ starting ─▶ questioning ─▶ quoting ─▶ quoted ─▶ handoff
▲ │ │
└── edit ────┴──────────┘
▼
failed ─▶ retryQuotes()

Passed to onEvent. They carry counts, durations and error names only, never answers.

type Fields
phase from, to
resumed
resume_discarded status
sync ok, answers (count), ms, errorName?
quote_started
quoted quotes (count), ms
quote_failed reason, ms, errorName
selected quoteId
no_quotes quotes (count)
error action, errorName, status?, requestId?

A StorageAdapter is { load(key), save(key, value), remove(key) }. load may be async; save and remove are sync and must not throw.

  • memoryStorage(): the default. Lost on reload.
  • sessionStorageAdapter(store = sessionStorage): per browser tab. Quota errors, private mode and corrupt data are swallowed.

The session writes on start, after each sync, on pagehide and on dispose(), never per keystroke. It removes the entry on handoff.

const encryptedStorage: StorageAdapter = {
load: (key) => decrypt(localStorage.getItem(key)),
save: (key, value) => { try { localStorage.setItem(key, encrypt(value)); } catch {} },
remove: (key) => localStorage.removeItem(key),
};