sankofa_flutter library

Flutter client SDK for Sankofa Analytics, Deploy, Switch, and Config — offline queueing, session replay, feature flags, and remote config.

Construct Sankofa.instance.init once at app startup, then (optionally) construct SankofaSwitch and SankofaConfig to light up those modules.

Classes

CatchBreadcrumb
CatchCaptureOptions
Optional parameters passed to captureException / captureMessage.
CatchDebugImage
Debug-meta — loaded binary table for native symbolication under ASLR. Rarely populated on pure-Dart errors; the iOS/Android native bridges fill this in when a native crash is reported up via the platform channel.
CatchDebugMeta
CatchDeviceContext
CatchEvent
The full event envelope. toJson produces the exact wire shape.
CatchException
CatchMechanism
CatchStackFrame
CatchStackTrace
CatchUserContext
FlagDecision
A single flag evaluation result.
ItemDecision
One decision per config item. value is already typed per type — server decodes JSON before emitting, so the SDK doesn't re-parse.
KbcFetchResult
Outcome of fetchAndApplyKbcPatch.
KbcPatchResult
Outcome of SankofaDeploy.applyKbcPatchFromBytes / SankofaDeploy.applyKbcPatchFromFile.
KbcStagedPatchInfo
Read-only view of a KBC patch staged on disk — what SankofaDeploy.getStagedKbcPatchInfo returns. Lets dashboards / support / debug screens surface which patch a device is on without re-running the interpreter.
ModuleIntegrationStatus
ParsedKbcEnvelope
Result of parsing a SANKOFA_KBC_ENVELOPE.
PulseBranchingActionKind
PulseBranchingCondition
PulseBranchingCondKind
PulseBranchingCondOp
PulseBranchingRule
PulseContext
PulseDecision
PulseEligibilityContext
Full eligibility context — mirrors server EligibilityContext.
PulseEventPayload
Payload delivered to every PulseEventListener. responseId is only populated on PulseEvent.surveyCompleted; reason is populated on dismissal when we have one (e.g. eligibility miss).
PulseHandshakeResponse
PulseMatchOp
PulseOutcome
PulseQuestion
PulseQuestionOption
PulseRenderRequest
Everything a custom Pulse renderer needs to present a survey and report back its lifecycle — the "survey state + controller" pair.
PulseRespondent
Respondent identity envelope. Mirrors the server's ingestRespondent shape (server/engine/ee/pulse/handlers_ingest.go). At least one of the three fields should be set; the server tolerates all-empty for fully anonymous submissions but the dashboard groups responses by the most-specific id present.
PulseRuleKind
PulseSubmitPayload
Final-submit payload. The wire shape matches the server's ingestPayload: answers is a map keyed by question_id (NOT a list of {question_id, value} pairs — that earlier shape was silently 400'd in production because the Go decoder treats arrays
PulseSubmitResponse
PulseSubscription
Token returned by SankofaPulse.instance.on(...). Hold it to keep the listener alive; call cancel to remove it. The constructor is public for SDK-internal use; hosts should only ever obtain instances by calling on(...).
PulseSurvey
PulseSurveyBundle
Full survey bundle — survey row + targeting rules + branching rules + translations. Themes and partial state will land here as those features graduate; the Go-side wire shape includes them all already.
PulseTargetingRule
One targeting rule. Loosely-typed by design — relevant fields depend on kind; absent fields are simply unused.
PulseTheme
PulseTranslator
Sankofa
The main entry point for the Sankofa Analytics SDK.
SankofaBootstrap
One-call bootstrap that does everything main would otherwise hand-wire:
SankofaBootstrapOptions
Configuration object exposed to Sankofa.bootstrap. Most fields mirror Sankofa.init one-to-one, with the addition of:
SankofaBootstrapResult
Result of Sankofa.bootstrap — what the engine + SDK figured out about the project at startup, plus any staged KBC patch the deploy pipeline applied before the first frame.
SankofaCatch
Sankofa Catch — error tracking for Flutter. Construct once after Sankofa.instance.init():
SankofaConfig
Sankofa Config — remote config on Flutter. Typed variables (string/int/float/bool/json) with cohort-targeted payloads and version history on the server side. The SDK owns:
SankofaCurrentPatch
Information about the currently-installed patch on this device. Returned by readCurrentKbcPatchnull when no patch has ever been applied (the app is running its baseline AOT code).
SankofaDeploy
Sankofa Deploy — Flutter Code OTA updates.
SankofaDeployOptions
Per-module options for Sankofa Deploy (OTA updates).
SankofaMask
A widget that masks its child from being captured in session replays.
SankofaNavigatorObserver
A NavigatorObserver that automatically tracks screen changes for Sankofa Analytics.
SankofaPulse
Sankofa Pulse — in-app surveys on Flutter.
SankofaReplay
The controller for managing session replay and visual recording.
SankofaReplayBoundary
A widget that defines the visual boundary for session replay recording.
SankofaReplaySuppress
Marks its subtree as off-limits for session replay capture.
SankofaSurveyDialog
Pure-Flutter survey renderer. Wraps every supported question kind in Material widgets — Theme.of(context) drives the look so the host app's brand colors apply automatically. Survey-level theme.primary_color overrides the seed when present.
SankofaSwitch
Sankofa Switch — feature flags on Flutter. Construct once after Sankofa.instance.init():
SankofaUpdate
Patch metadata returned by checkForKbcUpdate when status is SankofaUpdateStatus.outdated. Mirrors Shorebird's Patch plus the fields the Sankofa server actually exposes.
SankofaUpdateCheckResult
Result of a checkForKbcUpdate call.
SankofaUpdater
The one class you call. Mirrors Shorebird's ShorebirdUpdater in every respect: zero constructor arguments, lazy auto-config from sankofa.yaml, no exposed engine versions or signing keys, no init() to remember.

Enums

CatchLevel
ConfigType
Concrete data type of a config item. Declared on the server and echoed in every decision so the SDK doesn't need to re-parse JSON values.
FlagReason
Reason tag returned alongside a flag decision. Stable across server releases — SDKs and dashboards may key off these values. Unknown reasons (e.g. a new reason shipped on the server before the SDK knew about it) fall into FlagReason.unknown.
ItemReason
Reason an item resolved the way it did. Stable across server releases; unknown reasons fall into ItemReason.unknown.
KbcSigAlg
Signature algorithm identifiers carried in the trailer.
ModuleIntegrationLevel
Reports how complete the host's integration of a given module is.
PulseEvent
Lifecycle events the SDK fires while a survey is on screen. Hosts subscribe via SankofaPulse.instance.on(...) to wire Pulse into their own analytics / CRM / replay tooling.
PulseSurveyPresentation
How the built-in survey renderer wraps itself. dialog is a centered Material card (showDialog); bottomSheet is an edge-to-edge sheet rising from the bottom (showModalBottomSheet), the native-feeling default on mobile.
SankofaModuleName
Traffic Cop — Module Registry
SankofaReplayMode
The recording mode for session replay.
SankofaUpdateStatus
Status of a checkForKbcUpdate call.
UpdateStatus
Result of a Sankofa Deploy update check or install lifecycle event.

Constants

envelopeVersion → const int
pulseBranchingEndOfSurvey → const String
Sentinel: when PulseOutcome.nextQuestionId equals this string, the survey should end immediately.

Functions

applyKbcEnvelope(Uint8List envelopeBytes, {required KbcLoaderFn loader, String? signingPubkeyB64, List<String>? signingPubkeysB64}) Future<KbcPatchResult>
Internal apply pipeline. Exposed publicly via SankofaDeploy.
applyKbcEnvelopeFromFile(String path, {required KbcLoaderFn loader, String? signingPubkeyB64, List<String>? signingPubkeysB64}) Future<KbcPatchResult>
Read a file from disk, parse + verify, hand the inner KBC bytes to loader. See applyKbcEnvelope.
evaluatePulseBranchingCondition(PulseBranchingCondition cond, Map<String, Object?> answers) bool
evaluatePulseTargeting(List<PulseTargetingRule> rules, PulseEligibilityContext ctx) PulseDecision
fetchAndApplyKbcPatch({required String endpoint, required String apiKey, required String appVersion, required String engineVersion, required String distinctId, required KbcLoaderFn loader, String platform = 'ios', String? currentLabel, bool persistToDisk = true, Duration timeout = const Duration(seconds: 30), String? signingPubkeyB64, List<String>? signingPubkeysB64, Set<String>? bannedLabels}) Future<KbcFetchResult>
Hit the server, fetch a KBC patch envelope if one is available, verify integrity, and apply it via the supplied loader.
parseKbcEnvelope(Uint8List input) ParsedKbcEnvelope
Parse + validate a SANKOFA_KBC_ENVELOPE buffer.
pulseStableHash(String input) double
Synchronous SHA-256 over a UTF-8 string, returning the top 64 bits as a value in [0, 1). Same construction the Go + Web sides use — top 4 bytes form hi, next 4 form lo, then hi / 2^32 + lo / 2^64. Critical for cross-language parity: the same input MUST produce the same score in every SDK.
resolvePulseBranching(List<PulseBranchingRule> rules, String currentQuestionId, Map<String, Object?> answers) PulseOutcome

Typedefs

ConfigChangeListener = void Function(ItemDecision? decision)
Callback fired when an item's decision changes after a handshake refresh. decision is null when the item was removed remotely.
FlagChangeListener = void Function(FlagDecision? decision)
Callback fired when a flag's decision changes after a handshake refresh. decision is null when the flag was removed from the config entirely (archived remotely, key renamed, etc).
KbcLoaderFn = Future<Object?> Function(Uint8List kbcBytes)
Loader signature host apps wire in. Almost always loadModuleFromBytes from package:dynamic_modules/dynamic_modules.dart.
PulseEventListener = void Function(PulseEventPayload payload)
PulseSurveyRenderer = Future<void> Function(BuildContext context, PulseRenderRequest request)
A host-supplied renderer. Present whatever UI you like from context and return a Future that completes when the survey UI is gone (submitted or dismissed) — Pulse uses completion to clear its "a survey is on screen" guard. Register with SankofaPulse.instance.registerRenderer(...); pass null to fall back to the built-in renderer.

Exceptions / Errors

KbcApplyException
Raised when an envelope fails any pre-load check: bad magic, wrong version, SHA mismatch, malformed metadata, unsupported signature.
KbcEnvelopeFormatException
Raised when an envelope is malformed or fails integrity checks.
KbcFetchException
Raised for any failure inside fetchAndApplyKbcPatch.