Skip to content

chore: send regtest auth from env - #1867

Merged
ovitrif merged 3 commits into
masterfrom
feat/regtest-auth
Nov 11, 2026
Merged

ovitrif merged 3 commits into
masterfrom
feat/regtest-auth

Conversation

@ovitrif

@ovitrif ovitrif commented Nov 11, 2026 •

Copy link
Copy Markdown
Collaborator

Closes #1857

Twin: synonymdev/bitkit-ios#1284
Dependency: synonymdev/bitkit-core#202 (released as https://github.com/synonymdev/bitkit-core/releases/tag/v0.8.0-rc14)

Staging Blocktank protects its /regtest/* routes with HTTP basic auth, so the Settings > Blocktank Regtest actions failed with 401. This PR sends the credentials from a local variable in debug builds.

Description

  • Bump bitkit-core from 0.8.0-rc13 to 0.8.0-rc14, whose regtest calls take an optional auth (user:password). The only other change since rc13 is new API the app does not call yet (pubky swaps as a Paykit route, feat: pubky swaps as paykit route bitkit-core#182).
  • Env.blocktankRegtestAuth reads BLOCKTANK_REGTEST_AUTH from local.properties into the debug BuildConfig only; other builds get an empty value, read as null. CoreService passes it as auth to regtest_mine, regtest_deposit, regtest_pay and regtest_close_channel. Add BLOCKTANK_REGTEST_AUTH=user:password to local.properties. The value is never committed.
  • A 401 from the regtest routes shows bitkit-core's message, "401 Unauthorized: regtest auth is missing or was rejected", in the failure toast.
  • The Blocktank LSP skill documents the variable.

Design

N/A — no UI changes.

Preview

Settings > Blocktank Regtest > Deposit against staging, without and with BLOCKTANK_REGTEST_AUTH:

Without auth With auth

QA Notes

Manual Tests

  1. Without BLOCKTANK_REGTEST_AUTH, Settings > Blocktank Regtest > Deposit shows the 401 auth error.
  2. With it set, Deposit succeeds and shows the txid.

Automated Checks

  • ./gradlew testDevDebugUnitTest on rc14: 5,351 tests passed, none failed.
  • ./gradlew detekt and compileDevDebugKotlin: passed.

Evidence

Cases 1 and 2 passed on cd21340 with the published rc14 package, against staging regtest on an Android 16 emulator. Without the variable, Deposit showed the 401 auth error; with it, the deposit arrived and the wallet showed the received 100,000 sats.

@ovitrif ovitrif self-assigned this Nov 11, 2026
@ovitrif
ovitrif requested review from a team, ben-kaufman and pwltr and removed request for a team November 11, 2026 14:26
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 11, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-11T14:27:36.093142Z cd21340 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@greptile-apps

greptile-apps Bot commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 4/5

[Medium impact] The changes affect the bounded Blocktank staging regtest workflow.

Escape the credential before merging so valid passwords cannot break debug builds.

Findings

  1. P1 Some passwords break debug builds ▶

Summary

Adds build-time credentials for the Blocktank regtest actions.

  • Blocktank regtest actions can use credentials from debug builds.

Reviews (1) · Last reviewed commit: "chore: bump bitkit-core to 0.8.0-rc14" · Reviewed by Greptile

Comment thread app/build.gradle.kts Resolved

@jvsena42 jvsena42 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code scan at cd2134014: no findings.

  • Debug only: build.gradle.kts:367-369 reads BLOCKTANK_REGTEST_AUTH only for buildType == "debug" (env, then Gradle property, then local.properties). Every other build type gets "", so a release APK never carries it. Env.kt:46 guards it again with isDebug && isNotBlank().
  • Callers: only the BlocktankService regtest methods (CoreService.kt:2273-2301), reached from Dev Settings → Blocktank Regtest, which shows only on Network.REGTEST (DevSettingsScreen.kt:149).
  • Not logged or committed: core rc14 redacts the credential from its errors, and git grep finds no literal secret.
  • Core rc11 → rc14: this matches the iOS twin synonymdev/bitkit-ios#1284 (8fbf1d75). rc14 also adds the swaps module and two required PaykitRouteRequest fields, which nothing on master calls.

Unlike iOS, the regtest methods have no network == REGTEST guard of their own. The menu is the only gate, and the route is deep-linkable, so a mainnet or tnet debug build with the variable set could send the header to that network's Blocktank. Developer-only, so a note, not a finding.

Device gate (partial): cd2134014 — not run yet; a dev debug build with and without the variable, and mining a block from Blocktank Regtest, are running now.

Reviewer model: Claude Opus 5.5 (claude-opus-5-5)
Reasoning effort: not exposed

@github-actions

github-actions Bot commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

Regtest APK

Built from 8744b2d (run).

Download bitkit-dev-debug universal APK (expires in 30 days).

@pwltr pwltr left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed cd21340 against d642de9.

Medium — Escape regtest credentials before generating BuildConfig (app/build.gradle.kts:367-369, app/build.gradle.kts:419-420). BLOCKTANK_REGTEST_AUTH now passes through stringField(), which adds quotes without escaping Java string characters. A valid password containing " can prevent debug compilation; a literal backslash followed by t becomes a tab and changes the credential sent by the regtest actions. Debug-only guards limit the scope but do not handle these inputs. Serialize the value as a Java string literal so the configured credential is preserved. This is the same unresolved issue already raised in the Greptile thread.

Review details

Quick review
Model: Claude Opus 5.5
Reasoning effort: high

General review
Model: GPT-6.1 Sol
Reasoning effort: high

Combined review
Model: GPT-6.1 Sol
Reasoning effort: high

@ovitrif

ovitrif commented Nov 11, 2026

Copy link
Copy Markdown
Collaborator Author

@pwltr Fixed in 282e56f: stringField() escapes backslashes and quotes, so a password containing " or \t reaches the regtest calls unchanged. Compile and lint pass. I resolved the matching Greptile thread.

@jvsena42 On the network guard: I'm keeping the gate as it is. The value exists only in debug builds, and Blocktank Regtest only shows on regtest. A debug build with the variable set deep-linking to that screen on another network would only send a developer's own staging credentials.

@ovitrif
ovitrif requested a review from pwltr November 11, 2026 14:50

@talosmachina talosmachina left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No findings. Bumps bitkit-core to 0.8.0-rc14 and passes Env.blocktankRegtestAuth as auth to the four regtest calls; the value comes from BLOCKTANK_REGTEST_AUTH into the debug BuildConfig only, and stringField() now escapes backslashes and quotes. Reviewed 282e56f, light tier on the code, read whole for the build script hunk.

What I checked, and 3 candidates I ruled out

Read: the full diff, localProp and the variant block in app/build.gradle.kts, Env.kt, the regtest methods in CoreService.kt and their only callers in BlocktankRegtestViewModel.kt.
Ruled out

  • The credential reaching a release build: the key sits in the loop that gives every non-debug variant provider { "" }, and Env.blocktankRegtestAuth also requires isDebug and a non-blank value.
  • The escaping changing an existing field: backslashes are doubled before quotes are escaped, so an existing value with neither (every URL and key here) produces the same literal as before; a value with a quote used to break the generated Java and now compiles.
  • A regtest call left without auth: regtestMine, regtestDeposit, regtestPay and regtestCloseChannel are the four the view model calls, and all four pass it.

Build: not built here. Auto reviews on bitkit-android are static by policy, since Gradle would run the branch's code on this box. CI: build-local, detekt, lint and compose-ui green; build-and-test and the local e2e jobs were still running when I posted.

Merge confidence: 4/5, the rc14 bump and the debug-only gate have no test and the unit job had not finished.

Reviewer model: claude-opus-5-5
Reasoning effort: Not exposed (the run's metadata available to the reviewer names the model only)

@jvsena42

Copy link
Copy Markdown
Member

@ovitrif this conflicts with master; please rebase. I'll review it again once it merges cleanly.

@pwltr pwltr left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 282e56f. No findings.

stringField() now escapes backslashes, then quotes, before wrapping the value, so a regtest password reaches the generated BuildConfig unchanged. The order is right: escaping backslashes first keeps the backslash added for a quote from being doubled, and an escaped backslash also stops Java reading \u as a unicode escape. That resolves the Low from my review of cd21340, for every string field.

CI at 282e56f: build-and-test, lint, compose-ui and build-local were still running.

Review details

General review
Model: Claude Opus 5.5
Reasoning effort: high

@ovitrif

ovitrif commented Nov 11, 2026

Copy link
Copy Markdown
Collaborator Author

@jvsena42 Rebased onto master (force push to 8744b2d). The only conflict was gradle/libs.versions.toml, where master had moved biometric to 1.4.0-beta01; I kept that and the rc14 pin. just compile passes.

@jvsena42 jvsena42 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Device gate on cd2134014; the head is now 8744b2d1d (rebased onto master, mergeable). Approving.

8744b2d1d escapes \ and " in stringField(), so a value with either character can't break BuildConfig. It applies to every string field. The auth value contains neither, so its BuildConfig output is unchanged.

Case Result
Built without the variable The BuildConfig field is empty, and the value isn't in the APK. Deposit and Mine Blocks show "Blocktank regtest API returned 401 Unauthorized: regtest auth is missing or was rejected".
Built with the variable Deposit succeeded (txid 36ace532…34e4, 100,000 sats arrived 15:25:03Z) and 1 block was mined.
Secret exposure The value is not on screen, in the app log or in logcat (checked as booleans).

Device gate: cd2134014 (head 8744b2d1d: rebase plus BuildConfig escaping, reviewed) — 2 cases passed (Gate_Throwaway emulator, staging regtest); perf: not relevant; iOS: synonymdev/bitkit-ios#1284 passed the same cases.

Reviewer model: Claude Opus 5.5 (claude-opus-5-5)
Reasoning effort: not exposed

@ovitrif

ovitrif commented Nov 11, 2026

Copy link
Copy Markdown
Collaborator Author

Auto-merge on: approved by @jvsena42 on 8744b2d and by @pwltr on 282e56f (the same change before the rebase). No open threads. It merges once the remaining e2e check finishes green.

@ovitrif
ovitrif enabled auto-merge November 11, 2026 15:44
@ovitrif
ovitrif merged commit 088c9d3 into master Nov 11, 2026
23 checks passed
@ovitrif
ovitrif deleted the feat/regtest-auth branch November 11, 2026 15:45
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.

bug: blocktank regtest actions fail with 401 on staging

4 participants