SK-3053: Split SDK into skyflow-android-sdk (v1) + skyflow-flowvault-android-sdk (v2) sharing a common core- #194 - #195
Merged
saileshwar-skyflow merged 12 commits intoAug 17, 2026
Conversation
…les — foundation Restructure the single SDK into two independently publishable modules sharing a contract-agnostic core, per docs/sdk-split-plan.md. Published artifact ids are unchanged (skyflow-android-sdk; new skyflow-flowvault-android-sdk). - Rename module Skyflow -> skyvault (legacy/v1); add flowvault module (v1.0.0) - Extract shared sources into common/ (compiled into each module via source set, so Kotlin `internal` visibility is preserved without a separate :core module) - Container marker classes -> common; per-product container ops stay per-module - Base+extend for divergent types: BaseSkyflowClient / BaseConfiguration / BaseCollectElementInput / BaseRevealElementInput in common; legacy subclasses keep v1 shapes (table / skyflowID / redaction / /v1/vaults/ URL) - Error model: common SkyflowInternalError (exception) + legacy typealias SkyflowError (flowvault will bind SkyflowError to its v2 data class) - SdkInfo identity in common, stamped by each product's init() - Split Utils: neutral helpers -> common; v1-only helpers -> LegacyUtils - Add docs/sdk-split-plan.md Verified: skyvault v1 test suite passes; common compiles standalone inside the flowvault module (proving self-containment). FlowVault v2 port is in progress. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…nd docs Builds on the split foundation to finish the two-SDK architecture from one codebase: FlowVault (v2) module — port the beta v2 contract onto shared common/: - base+extend subclasses: CollectElementInput(tableName/skyflowId), RevealElementInput (no redaction), Configuration (no /v1/vaults/ suffix), Client (wires FlowDBAPIClient, no standalone client methods), Init (stamps SdkInfo) - v2 types + FlowDB* API layer, MockCVV, typed callbacks, container extensions (client.apiClient reached via (client as Client) since Container.client is BaseSkyflowClient) - 93-test v2 suite green (MockCVV/Response/Composable/InputFormatting/Utils/Validation) Common (kept contract-neutral): - promote JWTUtils to common/core (shared by both api clients) - add neutral okHttpClient superset to BaseConfiguration; add Element.skyflowId read alias Versioning + CI: - bump_version.sh takes a leading product arg (legacy|flowvault) - runOnGitHub + pr.yml build/test both modules - legacy release workflows retargeted to :skyvault; new mirrored flowvault_* workflows keyed to flowvault/* tags Both modules compile, lint, test, assembleRelease, and publishToMavenLocal (skyflow-android-sdk:1.27.0, skyflow-flowvault-android-sdk:1.0.0); flowvault POM carries no common module dependency. v1/v2 source coverage verified complete. docs/sdk-split-plan.md finalized to match the implementation. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Pure file relocation (git mv, 58 files) across common/skyvault/flowvault: move the files that sat flat in src/main/kotlin/Skyflow/ into logical subfolders — client/, config/, container/, element/, options/, response/, error/, logging/, auth/, style/, connection/. No content changes: every file keeps its `package Skyflow` declaration, so fully-qualified names, consumer imports, samples, and the published AAR API are all unchanged (all 58 changes are 100%-similarity renames). Kotlin allows package != folder, so kotlinc/Gradle/CI are unaffected; only the IDE shows a cosmetic folder-vs-package hint. Pre-existing package anomalies (com.Skyflow.* validations, ContainerProtocol, State.kt), test sources, and build/CI config are intentionally left untouched. Verified: both modules compile, lint, test (skyvault v1 + flowvault 93-test v2), and assembleRelease — all green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
APIClient (v1) and FlowDBAPIClient (v2) had byte-identical token handling (isValidToken + getAccessToken) — the only difference was SkyflowError vs SkyflowInternalError, which are the same type (skyvault aliases SkyflowError to SkyflowInternalError). Pull that lifecycle into a new internal common/core/BaseApiClient; both api clients now extend it and keep only their contract-specific request methods and endpoints. Same base-class pattern as BaseSkyflowClient/BaseConfiguration. Both api clients are internal, so no public API change; behavior is unchanged. Verified: both modules compile; skyvault v1 suite + flowvault 93-test v2 suite green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…or binary compat) Previously the thrown exception was defined once in common as SkyflowInternalError, with skyvault aliasing `SkyflowError` onto it. That changed the legacy artifact's JVM class from `Skyflow.SkyflowError` (1.27.0) to `Skyflow.SkyflowInternalError` — a source break for Java consumers and a binary break for precompiled/reflection consumers. Now each product defines its own error class; common only *references* the neutral throw-name `SkyflowInternalError` (shared source, resolved per module): - common: no longer defines the exception (deleted SkyflowInternalError.kt). - skyvault: restores the real v1 `class SkyflowError` (byte-identical to 1.27.0) and adds `internal typealias SkyflowInternalError = SkyflowError`, so common's throws produce real `Skyflow.SkyflowError` instances again. - flowvault: adds its own `internal class SkyflowInternalError` (plumbing only) and keeps the public `SkyflowError` data class unchanged. Verified against the clean AARs: skyvault exposes `Skyflow.SkyflowError` (no SkyflowInternalError class); flowvault has the SkyflowError data class + internal SkyflowInternalError. Both modules compile, assemble, and pass tests (skyvault v1 + flowvault 93-test v2). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ta/internal) Collapse the six release workflows into three. Each now triggers on both products' refs and derives the product from a single "Determine product" step: - release.yml : tags x.y.z (legacy) | flowvault/x.y.z (flowvault) - beta_release.yml : tags *.*.*-beta.* | flowvault/*-beta.* - internal_release.yml: branches release/* | flowvault-release/* The step sets product / module / version / gradle_file / label as step outputs; the shared bump / commit / publish steps read them, so the logic lives once. Deleted the three flowvault_*.yml duplicates. Also modernized the deprecated `::set-output` to $GITHUB_OUTPUT. Publish routing is unchanged (skyvault vs flowvault by ref namespace). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…client (v1-safe) Mirror the JS/Java SDK restructure on Android, as far as Kotlin allows, keeping the v1 (skyvault) public API byte-compatible — every change is additive or internal. Shared into common (written once): - ISkyflowClient — public client contract the base implements (analogue of JS ISkyflow). - initClient<T : BaseSkyflowClient> — the shared init body with a generic return (analogue of JS `static init<T>`); each product's `init(Configuration): Client` is a one-line delegate that supplies the concrete Client + its BuildConfig. - BaseCollectContainer / BaseRevealContainer — the byte-identical `create` body (createElement / createLabel) and element validation (validateElements/validateElement), reused by both products. Stays per-product (the genuine divergence): - the public `create(CollectElementInput)` / `create(RevealElementInput)` — thin delegates that keep each product's own input type and unchanged public/binary signature. - collect/reveal/post/get/update — contract-specific (v1 APIClient `/v1/vaults/` vs v2 FlowDBAPIClient `/v2/…`). - the concrete Client + init entry point (Kotlin can't inherit/specialize a static factory). Also tightened the element-input bases (BaseCollectElementInput/BaseRevealElementInput) from open to abstract (new in the split, never instantiated directly). Not done (flagged infeasible in Kotlin): container as an interface / member methods (ops are extension functions — would break v1 binary), CRTP self-type (no fluent client API), element inputs as interfaces (they hold state). Verified: both modules compile, lint, test (skyvault 430 + flowvault 93), assembleRelease; skyvault public-API surface unchanged except the additive ISkyflowClient superinterface (Client/Container/SkyflowError/CollectElementInput/Configuration byte-identical). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Cosmetic rename of the shared generic init helper (and the two per-module init delegates' calls + KDoc references). No behavior or signature change; the public `init(Configuration): Client` entry points are unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…scope of change
Rework internal_release.yml so one release/* branch (one PR, no separate
flowvault-release branch) publishes both dev SDKs based on what changed vs main —
mirroring the skyflow-js internal workflow:
- common/ or a shared root (scripts, root build.gradle, settings.gradle, gradle
wrapper, .github/workflows) changed -> publish BOTH skyvault + flowvault
- only skyvault/ changed -> publish skyvault
- only flowvault/ changed -> publish flowvault
Scope = git diff against merge-base with main (idempotent across re-pushes). So
merging the split PR into release/* (which touches common/) publishes both dev
artifacts in one run. Public/beta workflows are unchanged (still per-product by
tag namespace) — scope logic is internal-only.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- README.md -> slim product index (SkyVault v1 / FlowVault v2) linking each package guide + sample - skyvault/README.md: v1 guide (moved from root); sample links -> samples/skyvault/ - flowvault/README.md: v2 guide (from beta-release/26.7.0) with install coordinates repointed to the NEW separate package (com.skyflowapi.android:skyflow-flowvault-android-sdk:1.0.0) - samples/skyvault/: v1 sample (-> :skyvault); samples/flowvault/: v2 sample (-> :flowvault, distinct applicationId) - samples/README.md: two-sample index + shared vault-setup prerequisites Samples stay reference-only (not wired into settings.gradle), mirroring the iOS layout. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace RevealRecord.metadata (Map<String, Any?>) with a typed RevealMetadata(tableName, skyflowId), matching the iOS RevealResponse. Update toJson/fromJson accordingly (fromJson tolerates the raw 'skyflowID' key as well as the normalized 'skyflowId') and add a metadata-parsing test. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
FlowVault is a new package versioned from 1.0.0 that targets the v2 API - it is not 'SDK v2'. Match the skyflow-js package-split README: distinguish the two SDKs by vault type + API version (skyflow-android-sdk = PDB vault (v1 API); skyflow-flowvault-android-sdk = Flow vault (v2 API)) and add the backward-compat guidance. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
skyflow-bharti
approved these changes
Aug 17, 2026
saileshwar-skyflow
changed the base branch from
flowvault-release/26.8.0
to
release/26.8.0
August 17, 2026 16:57
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
Splits the single
skyflow-androidcodebase into two independently publishable AAR SDKs that share one common core, with the variant fixed by which artifact an app installs — no build flags, no runtime switch.:skyvaultskyflow-android-sdk(unchanged)/v1/vaults/, untypedCallback,table/fields/skyflow_idmain(1.27.0):flowvaultskyflow-flowvault-android-sdk(new,1.0.0)tokenGroupRedactions,/v2/records|tokens/, typed callbacks,tableName/tokens/skyflowIdbeta-release/26.7.0(1.28.0-beta.1)common/(shared source folder, not a module)common/is a plain source folder added to both modules' source sets, so Kotlininternalworks natively (no@RestrictToleakage) and each AAR is self-contained. FlowVault is implemented by extending shared base types (BaseSkyflowClient,BaseConfiguration,BaseCollectElementInput,BaseRevealElementInput), not by branching inside shared code.Backward compatibility: the legacy v1 public surface is unchanged (branch cut from
main;Configurationkeeps its/v1/vaults/suffix via subclass; v1 wire keys preserved).Key mechanics
SkyflowError= coreSkyflowInternalErrorin v1; a typed data class in v2).JWTUtilspromoted tocommon/core; neutralokHttpClientsuperset onBaseConfiguration;Element.skyflowIdread alias.bump_version.sh <legacy|flowvault> …), per-product release workflows keyed to tag namespaces (x.y.z/*-beta.*→ skyvault;flowvault/*→ flowvault), PR CI builds+tests both.Verification (all green)
:skyvault+:flowvaultcompile, lint, test, andassembleRelease(runOnGitHub→ BUILD SUCCESSFUL).publishToMavenLocal→skyflow-android-sdk:1.27.0andskyflow-flowvault-android-sdk:1.0.0; flowvault POM has nocommonmodule dependency (shared source compiled into the AAR).Skyflow/module removed with no stale references.Notes / deliberate deviations
Skyflowpackage with each layer, so a leak is an unqualified reference, not an import). CI builds both modules, so any violation breaks the build. A Konsist AST test is left as an optional future enhancement rather than adding a network dependency.samples/remains the v1 reference app (points at:skyvault, standalone as onmain). No dedicated FlowVault sample in this PR.