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.
toJsonproduces 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.
responseIdis only populated on PulseEvent.surveyCompleted;reasonis 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
ingestRespondentshape (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:answersis 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 callingon(...). - 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
mainwould 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
readCurrentKbcPatch—nullwhen 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.
- 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_coloroverrides the seed when present. - SankofaSwitch
-
Sankofa Switch — feature flags on Flutter. Construct once after
Sankofa.instance.init(): - SankofaUpdate
-
Patch metadata returned by
checkForKbcUpdatewhen status is SankofaUpdateStatus.outdated. Mirrors Shorebird'sPatchplus the fields the Sankofa server actually exposes. - SankofaUpdateCheckResult
-
Result of a
checkForKbcUpdatecall. - SankofaUpdater
-
The one class you call. Mirrors Shorebird's
ShorebirdUpdaterin every respect: zero constructor arguments, lazy auto-config fromsankofa.yaml, no exposed engine versions or signing keys, noinit()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.
dialogis a centered Material card (showDialog);bottomSheetis 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
checkForKbcUpdatecall. - 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 formlo, thenhi / 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.
decisionisnullwhen the item was removed remotely. - FlagChangeListener = void Function(FlagDecision? decision)
-
Callback fired when a flag's decision changes after a handshake
refresh.
decisionisnullwhen 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
loadModuleFromBytesfrompackage: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
contextand 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 withSankofaPulse.instance.registerRenderer(...); passnullto 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.