Skip to content

Release 26.8.0: FlowVault Android SDK — public release (skyflow-flowvault-android-sdk) - #196

Merged
saileshwar-skyflow merged 18 commits into
mainfrom
release/26.8.0
Aug 25, 2026
Merged

Release 26.8.0: FlowVault Android SDK — public release (skyflow-flowvault-android-sdk)#196
saileshwar-skyflow merged 18 commits into
mainfrom
release/26.8.0

Conversation

@saileshwar-skyflow

Copy link
Copy Markdown
Collaborator

What

Merges release/26.8.0 into main to ship the first public release of the FlowVault Android SDK (skyflow-flowvault-android-sdk) — the FlowDB v2 SDK built alongside the existing skyvault v1 SDK in this repo.

Includes the SK-3053 FlowVault SDK work plus the CX-reported FlowDB fixes (custom-validation ClassCastException, FlowDBMixedAPICallback double-report, response decode → onFailure, main-thread callbacks) — commits 5bf09c8, 3cbfc27, c96124d, and the sample fixes d837ad9. Also carries the skyvault (legacy) updates that are part of the 26.8.0 train.

How the public release is triggered (after this merges)

The public release is tag-driven (.github/workflows/release.yml, "Public Release"). On main:

git tag flowvault/1.0.0
git push origin flowvault/1.0.0

That fires the workflow, which:

  1. Checks out main, runs scripts/bump_version.sh flowvault 1.0.0 → sets flowvault/build.gradle mVersionName = "1.0.0" (public — no -dev suffix),
  2. commits the bump, and
  3. runs ./gradlew :flowvault:publish → publishes skyflow-flowvault-android-sdk:1.0.0 to GitHub Packages (maven.pkg.github.com/skyflowapi/skyflow-android).

The package name skyflow-flowvault-android-sdk is already the mArtifactId; the public publication uses it as-is (the -dev/-beta variants are internal/beta channels only). No flowvault/* tags exist yet, so 1.0.0 is the first public flowvault version.

🤖 Generated with Claude Code

saileshwar-skyflow and others added 18 commits August 17, 2026 22:37
…y fetch --tags)

The scope step computed BASE=$(git merge-base FETCH_HEAD HEAD), but the preceding
'git fetch --tags' re-pointed FETCH_HEAD from main to the release branch. merge-base then
collapsed to HEAD, the diff was empty, both SDKs read as out-of-scope, and the publish/bump
steps were skipped. Fetch main into refs/remotes/origin/main explicitly and compute the
merge-base against origin/main (which the tags fetch cannot clobber).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Blockers (legacy v1 parity, verified byte-/binary-identical to 1.27.0):
- B1: resolve the __SKYFLOW_SDK_ID__ placeholder on the thrown-error path so error messages render
  'Android SDK v<version>' (skyvault 1.27.0 / flowvault 1.0.0) instead of the raw token.
- B2: restore TextField.update(CollectElementInput) binary descriptor.
- B3: restore Client.getConfiguration():Configuration via a covariant override.

HIGH:
- H2: flowvault reveal() validates vault config (fail-fast), matching collect + legacy reveal.

MEDIUM/LOW (flowvault):
- M2: additionalFields column collisions throw DUPLICATE_COLUMN_FOUND (v1 parity), not a silent drop.
- M3: validate additionalFields (empty records/table/data/column).
- M4: deliver onSuccess outside the failure try — no double callback.
- M5: log (not swallow) malformed fields in Utils.removeEmptyAndNullFields.
- M6: remove dead SdkInfo.name (name must not appear in errors; telemetry reads BuildConfig directly).
- M7: remove dead update() extensions.
- Hoist CollectRequestRecord to common; fail fast on empty collect (EMPTY_RECORDS).
- Error contract: flowvault delivers a populated SkyflowError (constructErrorResponse) rather than a
  stringified exception, so onFailure carries the real httpCode + message. skyvault's constructError
  (v1 wire contract) is untouched.

Tests: 7 upsert expectations updated to the substituted form; new B1/H2/M2/M3/M4 regression tests.
skyvault 432 + flowvault ~100 unit tests green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…rdMetadata (JS parity)

Match the JS SDK response interfaces in flowvault (v2):
- CollectRecordToken(token, tokenGroupName?, path?) and CollectRecordHashedData(data, hashName)
- retype CollectRecord.tokens/hashedData to Map<String, List<...>> (parsed in fromJson, serialized in toJson)
- rename RevealMetadata -> RevealRecordMetadata
- sample + ResponseTest updated to typed access

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
New opt-in CollectElementOptions.returnMockValue (default false), matching the JS SDK.
When true on a CVV element, the collect response returns a fixed mock (999 for 3-digit,
9999 for 4-digit) instead of the real token, so a downstream proxy can reliably identify
it; no-op for non-CVV types. Previously flowvault always mocked CVV with a random value.

- CollectElementOptions is split out of common into per-module copies so the option is
  flowvault-only: skyvault keeps the exact 1.27.0 6-arg class (verified byte-identical +
  identical constructor descriptor via javap); flowvault adds the returnMockValue field.
- MockCVV: CVVMap.capture/captureForUpdate now gate on returnMockValue; random
  generateMockCVV replaced by fixed mockCVV(length) constants (single source of truth).
- MockCVVTest rewritten: fixed-value assertions + real-element capture gating suite.
- Sample CardBrandChoiceActivity demonstrates returnMockValue = true.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Verified samples/flowvault and samples/skyvault compile against the local :flowvault/:skyvault
builds. Fixes pre-existing gaps (unrelated to the SDK API):
- samples/skyvault/build.gradle: drop stale kotlin-android plugins (AGP 9 has built-in Kotlin),
  remove obsolete kotlinOptions + $kotlin_version stdlib dep, add namespace, enable buildConfig.
- add the missing @font/roboto_light resource referenced by both samples' CustomStyles.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- MOCK_CVV_3/MOCK_CVV_4 -> 817/8173 (was 999/9999), finalized values
- remove unused CVVMap.captureForUpdate (no production callers) + its tests
- update sample comment

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- H1: flowvault bearer-token failures convert the internal error via
  constructErrorResponse, so the app receives the real code+message instead of
  a mangled 500 (FlowDBCollectAPICallback/FlowDBRevealApiCallback.onFailure).
- H2: reveal no longer double-fires — RevealValueCallback delivers onSuccess
  outside the try that maps to onFailure (mirrors the collect M4 fix).
- H4: SkyflowErrorCode.message resolves the __SKYFLOW_SDK_ID__ placeholder on
  read (kept as var, so getMessage()/setMessage() binary surface is unchanged);
  3 direct .message log sites now use getMessage(). Restores 1.27.0 strings.
- SdkInfo -> internal (was a new public mutable process-global).
- remove dead buildUpdateRequestBodyFromMap + flowvault SOAP xml*; fix stale
  ResponseTest comment + Client.kt doc.
- tests: add ErrorDeliveryTest (H1/H2 regression); ComposableElementsTests now
  assert the resolved message (both modules).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…MEDs (flowvault-only)

- F2: an update element and an additionalFields update record sharing a
  (tableName, skyflowId) are now MERGED into a single record (matching v1s
  "${table}_${skyflowID}" merge) instead of being sent as two. Logic extracted
  into shared FlowDBCollectRequestBody.buildCombinedUpdateBody, used by both
  CollectContainer and ComposableContainer; additionalFields overwrite element
  columns on collision (v1 last-writer-wins).
- MED (JWT crash): FlowDBAPIClient.isValidToken swallows JWTUtils parse errors
  on a malformed/opaque bearer token so getAccessToken emits a typed
  INVALID_BEARER_TOKEN instead of crashing on the provider thread.
  BaseApiClient.isValidToken made protected open (additive; skyvault does NOT
  override -> v1 keeps exact 1.27.0 behavior).
- MED (composable null styles): flowvault Client.container(...) defaults null
  ContainerOptions styles before the shared Container constructor force-unwraps
  them (NPE), so a null-styles composable container renders; getComposableLayout
  hardened too. skyvault unchanged.
- tests: UpdateMergeTest, ErrorDeliveryTest (JWT), ComposableElementsTests (null styles).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…response decode, callback threading)

- Custom validation rules (common — affects both SDKs): add validate() to the
  public ValidationRule and call it directly in SkyflowValidator (drop the
  internal-protocol cast); delete SkyflowInternalValidationProtocol; reconcile the
  8 built-in rules. Consumer-authored rules now work instead of throwing
  ClassCastException at create()/first keystroke.
- Mixed insert+update callback (flowvault): FlowDBMixedAPICallback counts both
  success and failure toward completion and fires exactly one terminal callback.
  A committed half is no longer dropped (consolidated onSuccess with per-record
  error records); both-fail delivers a single onFailure (was firing twice).
- Response decoding (flowvault): add strict fromJsonOrThrow + logging; success-path
  adapters route an undecodable response to onFailure instead of a false empty
  onSuccess; non-object records entries are logged, not silently dropped.
- Callback threading (flowvault): deliver CollectCallback/RevealCallback on the
  main thread and document it — stops an app-handler exception from killing the
  OkHttp dispatcher thread's process, and fixes CalledFromWrongThreadException.

Adds regression tests in flowvault + skyvault ValidationTests. setValue/clearValue
dev-only behavior is intended (matches iOS), so no change there.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…op CardBrandChoice; stop samples-only pushes triggering internal release

- Config: samples/flowvault activities now read VAULT_ID/VAULT_URL/TABLE_NAME/
  COLUMN_NAME/etc. from local.properties via BuildConfig (matching the README)
  instead of inline <PLACEHOLDER> literals; build.gradle exposes the missing keys
  with null-safe placeholder defaults. REDACTION_TYPE stays a plain String; the
  card_lookup bearer token now flows through DemoTokenProvider/TOKEN_URL.
- Schema: replace samples/flowvault/data/vaultSchema.json (previously the PDB
  schema, byte-identical to skyvault) with a valid FlowDB schema (vaultType,
  tokenGroup, columns with tokenGroups/hashings); workspaceID placeholdered.
- Remove the CardBrandChoice sample (activity, manifest entry, menu button, string).
- CI: internal_release.yml ignores samples/** so a samples-only push no longer
  triggers an internal (dev) release.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

🔐 Gitleaks Findings: 14 issue(s) detected

🔸 Rule: generic-api-key
📄 File: flowvault/README.md:null
📝 Description: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
🔑 Secret: **********
🔗 Path: flowvault/README.md:null

🔸 Rule: generic-api-key
📄 File: flowvault/README.md:null
📝 Description: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
🔑 Secret: **********
🔗 Path: flowvault/README.md:null

🔸 Rule: generic-api-key
📄 File: flowvault/README.md:null
📝 Description: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
🔑 Secret: **********
🔗 Path: flowvault/README.md:null

🔸 Rule: generic-api-key
📄 File: flowvault/README.md:null
📝 Description: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
🔑 Secret: **********
🔗 Path: flowvault/README.md:null

🔸 Rule: generic-api-key
📄 File: flowvault/README.md:null
📝 Description: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
🔑 Secret: **********
🔗 Path: flowvault/README.md:null

🔸 Rule: generic-api-key
📄 File: flowvault/README.md:null
📝 Description: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
🔑 Secret: **********
🔗 Path: flowvault/README.md:null

🔸 Rule: generic-api-key
📄 File: flowvault/README.md:null
📝 Description: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
🔑 Secret: **********
🔗 Path: flowvault/README.md:null

🔸 Rule: generic-api-key
📄 File: flowvault/README.md:null
📝 Description: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
🔑 Secret: **********
🔗 Path: flowvault/README.md:null

🔸 Rule: generic-api-key
📄 File: flowvault/README.md:null
📝 Description: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
🔑 Secret: **********
🔗 Path: flowvault/README.md:null

🔸 Rule: generic-api-key
📄 File: skyvault/README.md:null
📝 Description: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
🔑 Secret: **********
🔗 Path: skyvault/README.md:null

...and more. Only showing first 10 findings.

@github-actions

Copy link
Copy Markdown

Semgrep Findings: Issues with Error level severity are found (Error is Highest severity in Semgrep), Please resolve the issues before merging.

@saileshwar-skyflow saileshwar-skyflow changed the title Release 26.8.0: FlowVault Android SDK v2 — first public release (skyflow-flowvault-android-sdk) Release 26.8.0: FlowVault Android SDK — public release (skyflow-flowvault-android-sdk) Aug 25, 2026
@saileshwar-skyflow
saileshwar-skyflow merged commit 8988d66 into main Aug 25, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants