clariodesk library
ClarioDesk Flutter SDK — headless surface.
Quick start:
// 1. Once at app start. Awaiting is optional — subsequent calls
// transparently wait on the in-flight bootstrap if you don't.
await ClarioDesk.init(apiKey: 'pk_live_…');
// 2. After the host's own auth flow knows the user. Metadata only —
// the device's hardware-bound key is the actual identity.
await ClarioDesk.identify(
externalId: hostUser.id,
email: hostUser.email,
traits: {'plan': 'pro'},
);
// 3. Writes are imperative.
final t = await ClarioDesk.createTicket(
subject: 'Upload broken',
body: 'Tapping upload does nothing.',
);
// 4. Reads are reactive streams — auto-prime + live updates.
StreamBuilder<List<Ticket>>(
stream: ClarioDesk.ticketsStream(),
builder: (_, snap) => …,
);
Auth model: Device-Is-Identity. On first launch
the SDK generates an ECDSA P-256 keypair inside iOS Secure Enclave /
Android Keystore, registers it via challenge-response, and signs
every subsequent request with that key. The publishable pk_* key
you pass to init only opens the door to register a new device; it
cannot read tickets or impersonate users.
Classes
- Attachment
-
One file/photo/video on a Message. Mirrors the API's attachment
payload. image/file carry a short-lived
presigned R2 GET (
url+ urlExpiresAt, refreshable); video carries the Cloudflare Stream fields (playbackUrl/posterUrl/processingStatus). - ChangelogEntry
- A published "What's New" changelog entry.
- ClarioDesk
- Static facade. Backed by a singleton state holder so hot reload (which preserves Dart globals across rebuilds) keeps registration state intact.
- ClarioDeskDiagnostic
-
A non-fatal event the SDK would otherwise swallow silently — a best-effort
failure, an exhausted retry, a dropped queued write, a fatal transition.
Delivered to the host's ClarioDiagnosticHandler (wired at
init) so it can pipe SDK internals into Sentry/Crashlytics: "swallow with a receipt". code is a stable machine key; message is for logs; context carries structured extras (ticketId, clientId, error code). - ClarioDeskDiagnostics
-
A point-in-time snapshot of SDK health, from
ClarioDesk.diagnostics(). Designed to be pasted straight into a support ticket — toJson renders the same field names on every ClarioDesk SDK. - ClarioDeskFeedback
-
Headless feedback-board API, reached via ClarioDesk.feedback
(docs/FEEDBACK_BOARD_IN_APP_SURFACE). Every call funnels through the same
signed client as tickets, so it inherits the SDK's auth, retries, and
resilience. Reads throw ClarioDeskException (404
feedback_not_enabled) when the app owner hasn't provisioned a board. - ClarioPushPayload
-
A parsed ClarioDesk push payload (the FCM
message.datamap). Produced by ClarioDesk.parsePushPayload; null for any message that isn't ours. - DeviceKey
- A device-resident ECDSA P-256 keypair backed by iOS Secure Enclave or Android Keystore. The private key is non-extractable by design — every operation that needs it (signing, attestation) goes through this interface.
- FeedbackBoard
- The board's config + taxonomy — everything the SDK needs to render the shell.
- FeedbackCategory
- An optional tag a post can carry.
- FeedbackComment
- A public comment on a post.
- FeedbackPost
- A feedback post (feature request / idea).
- FeedbackPostCreated
- Result of creating a post: its id + whether it's held for moderation.
- FeedbackPostDetail
- A post plus its comment thread.
- FeedbackStatus
- A status column on the board (Open / Planned / Shipped …).
- IdentityTokenProvider
- Supplies a fresh verified-identity token for the current host session.
- Message
- NotificationPreferences
-
The end user's notification preferences.
Quiet-hours bounds are
HH:MM24h strings in timezone; all three are null when no window is set. - OutgoingAttachment
-
A file the host has picked and handed to
ClarioDesk.sendMessage/createTicketto attach. The SDK reads its bytes, uploads them (sign → direct PUT/Stream), and binds the resulting id when the message is sent. - PushTokenProvider
- Source of the device's push token, owned by the host app, not the SDK.
- SdkFeatureFlags
- SdkNotice
- SdkRuntimeConfig
- SecureStorage
-
Persists tiny pieces of identity state across app launches — today
only the
deviceIdminted by/v1/sdk/devicesregistration. The device's private key itself never travels through here; it lives in Secure Enclave / Keystore via DeviceKey. - Ticket
Enums
- AttachmentKind
-
Server-derived discriminator both the bubble and viewer switch on. The wire
also carries legacy
screenshot/logvalues which collapse to file. - ClarioDeskConnectionState
- ClarioDeskErrorCode
- ClarioDiagnosticLevel
-
Severity of a ClarioDeskDiagnostic. Advisory — branch on
code, not this. - ConversationSyncState
- Per-conversation sync lifecycle (REALTIME_ARCHITECTURE §9). Distinct from ClarioDeskConnectionState: a connected socket doesn't mean a given thread is caught up. Drives the mid-session "Updating…" / "Offline" hints the pre-built UI renders on top of the message list.
- DevicePlatform
-
String form on the wire — matches
device_platform_enumin the backend schema. Sent on registration so the server can both rate-limit per-platform and surface the device in the dashboard. - IdentityMode
- KeyAttestation
-
Where the private key actually lives. The native layer reports the
strongest backing it landed in; the server records the same enum on
devices.key_attestationso the dashboard can surface a per-device badge. - MessageAuthor
- MessageReadState
- Delivery state of an end-user's own outgoing message, for status-tick rendering. A failed send is signalled separately by Message.failed; this enum covers the success path only.
- SdkFeature
- TicketStatus
- TicketType
Functions
-
readStateOf(
Message m, Ticket t) → MessageReadState -
Derives the MessageReadState of
mwithint. Meaningful only for the end-user's own messages; callers gate on author/failedfirst. Headless hosts use this to render delivery ticks without reimplementing the read-pointer comparison; the pre-built UI uses it too.
Typedefs
- ClarioDiagnosticHandler = void Function(ClarioDeskDiagnostic diagnostic)
-
Optional host hook passed to
ClarioDesk.init(onDiagnostic: …). The SDK guarantees it never throws into the host: it is invoked inside a guard, so a sink that itself throws can't crash the SDK (the never-crash contract).