Skip to content

chore: prepare Bitkit 3.1.1 - #1298

Closed
piotr-iohk wants to merge 10 commits into
masterfrom
release-3.1.1
Closed

piotr-iohk wants to merge 10 commits into
masterfrom
release-3.1.1

Conversation

@piotr-iohk

@piotr-iohk piotr-iohk commented Nov 12, 2026 •

Copy link
Copy Markdown
Collaborator

Twin: synonymdev/bitkit-android#1878

Prepares Bitkit 3.1.1 (build 204) from v3.1.0, with the version bump and collected hotfix changelog.

Description

Design

No separate release design; profile behavior and QA details are in the linked backports.

Preview

See the profile backport for the feature preview.

QA Notes

Setup

The runs below test c4bfb15735cd9131150116113f77b60b4684d55b on release-3.1.1 using the E2E repository’s main branch. Migration uses the archived native 3.1.0 build and includes the extended RN 1.1.6 cases.

Journeys

  • J1: new edit-pubky-app-profile.xml — profile changes are shared with pubky.app.
  • J2: new request-note-too-long.xml — an oversized Paykit note is rejected before submission.
  • J3: new grant-signup-rejected-code.xml — a rejected signup code gets a clear error.

Automated Checks

Evidence

Local backend simulator app built and verified; 669 targeted tests passed on iPhone 17. SwiftFormat and translation validation passed.

Gaps

Full E2E and migration results are tracked in the linked runs. Device journeys are separate from the local unit tests.

Models used

  • Planning/scoping: GPT-6 (reasoning: Not exposed)
  • Implementation: GPT-6 (reasoning: Not exposed)
  • Review: Not performed

The session exposes the model family but not its variant or reasoning setting.

ovitrif and others added 6 commits November 12, 2026 08:15
chore: adopt Paykit 0.1.1-rc6
(cherry picked from commit fe0cc2d)
feat: use the pubky.app profile directly
(cherry picked from commit a1dbb83)
chore: bump ldk-node and vss client
(cherry picked from commit 1ebdfc5)
chore: bump ldk-node to 0.7.0-rc.80
(cherry picked from commit 1b56274)
chore: bump paykit to 0.1.1-rc8
(cherry picked from commit a9c1a9b)
ci: pass Blocktank regtest auth to E2E jobs
(cherry picked from commit 8adc704)
@piotr-iohk

piotr-iohk commented Nov 12, 2026 •

Copy link
Copy Markdown
Collaborator Author

After 3.1.1 ships from this branch, close this PR without merging. A separate follow-up PR will bump the version and update the 3.1.1 changelog on master.

Validation after the profile-tag fix.

Results before the tag-preservation fix

The first migration run hit HTTP 401 in all four React Native wallet setup jobs. The setup jobs failed while funding the legacy app, before exercising the iOS 3.1.1 migration.

iOS #1250 is now backported in 25284fa8a and supplies the existing regtest credential to staging, migration, and the reusable wallet setup workflow. The E2E suite uses main, which includes the auth helper and reusable workflow from E2E #304. Native migration still uses the archived 3.1.0 app.

Check Earlier run
Local E2E 11 passed, 2 failed · both send cases expect newer BIP21 routing
Staging E2E 25 nightly UI cases passed, 3 failed · ✅ 6 Pubky/Paykit cases passed on attempt 2 · transfer and multi-address had no matching cases
Migration ✅ 4/4 standard cases passed · both upgrades on attempt 1 and both restores on attempt 2
Unit tests ✅ 2,987 passed, 1 skipped
Native UI 38 passed, 1 failed, 4 skipped · the profile copy toast disappeared before XCTest could tap it · ✅ focused local repeat passed 2/2
Integration tests ✅ All 30 tests passed with staging fixture auth

The integration dispatch uses signed commit b03f4a610, which passes the staging credential to the deposit and mining fixtures in the XCTest target. ✅ The simulator build and local unit suite passed with 2,987 tests passing and one skipped. The commit changes the integration workflow and test sources only.

The standard matrix exercises native 3.1.0 upgrade and restore and RN 1.1.6 upgrade and restore. It supersedes the extended migration run. Both RN fixture jobs funded wallets successfully with auth. The restore fixture’s first attempt showed a legacy-app broadcast timeout and passed on retry with the same app and suite. Both restore cases retried after Appium session creation timed out before the test started. The logs show both restores completed on attempt 2. The migration suite ran E2E commit 0ca01e0a2. A signed iOS device archive for 3.1.1 build 204 is prepared.

The local run used E2E commit 0ca01e0a2. Both @send_1 and @send_2 failed on all three attempts. The recordings show the 10,000-sat and 20,000-sat BIP21 requests reaching the Amount screen. The tests now expect the direct review route added by iOS #1198. The release branch has the same send-routing source as shipped 3.1.0, whose local run passed both send cases with E2E commit 611509ee2.

The native UI failure was in ProfileRecoveryUITests.testProfileControlsStayReadOnlyUntilSessionAndProfileRecover. It passed on shipped iOS 3.1.0. The toast still auto-dismisses after three seconds, and the UI test still waits for it and then taps it. The same test passed both focused repeats on the release-branch simulator build. The three-second dismissal and the successful repeats point to an XCTest timing flake.

The iOS staging job funded and mined both deposits in the two-receipt case. Its first and third attempts timed out creating an Appium session. Attempt 2 showed the dev-mode-disabled toast in the recording, though the test missed it. The send amount was $1.11 when the test expected $1.01, and a late receipt overlay covered Send after the second deposit. Those two cases need a focused repeat to distinguish timing from an app issue. All three passed on the shipped 3.1.0 staging run. 3.1.0 staging control

Original evidence: staging and migration.

@piotr-iohk
piotr-iohk marked this pull request as ready for review November 12, 2026 08:50
@greptile-apps

greptile-apps Bot commented Nov 12, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 4/5

[Medium impact] The changes reach public profile editing and payment-request workflows in the iOS app.

Preserve the restored profile's unread-tags flag before merging so profile creation cannot erase saved tags.

Findings

  1. P1 Restored profiles can lose tags ▶

Summary

Prepares Bitkit 3.1.1, build 204.

  • Bitkit profile edits now update the profile shown on pubky.app.
  • Profile saves and deletes now respect changes already in progress.
  • Paykit checks proof size before it accepts or prepares a payment.
  • USDT payments made well before a request no longer count as its payment.
  • Signup approval now explains rejected codes and connection failures.
  • Bitkit's release metadata and payment dependencies move to the 3.1.1 baseline.

One fix is needed: profile creation must preserve the restored profile's unread-tags flag.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Load own profile] --> B[Read Paykit copy and tags]
    B --> C[Read pubky.app profile and revision]
    C --> D[Show profile]
    D --> E[Save changed fields at loaded revision]
    E --> F{Revision still matches?}
    F -- No --> G[Reload and ask user to edit again]
    F -- Yes --> H[Save pubky.app profile]
    H --> I[Update Paykit copy and tags]
Loading

Reviews (1) · Last reviewed commit: "Merge pull request #1250 from synonymdev..." · Reviewed by Greptile

@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.

1 finding (1 P1). Prepares Bitkit 3.1.1 (build 204) on release-3.1.1 from v3.1.0: five backports, the version bump, the changelog, and a test commit that authenticates the staging regtest fixtures. Reviewed b03f4a6, full tier, static.

What I checked, and 3 candidates I ruled out

Backports: #1235, #1252, #1290, #1292 and #1250 carry the same changed lines as their merges on master. #1237 differs by 8 test-only lines (fixture ids and two new PrivatePaymentListDeliveryReport / proposal fields that exist only on master), consistent with the body's "adapts the Paykit and reauthentication tests to the release baseline".
Version commit c4bfb15: MARKETING_VERSION 3.1.1 and CURRENT_PROJECT_VERSION 204 on every target, three fragments consumed into CHANGELOG 3.1.1.
Test commit b03f4a6: BlocktankRegtestFixture reads BLOCKTANK_REGTEST_AUTH and posts to the staging fixture API; the secret is passed only on a workflow_dispatch of release-3.1.1 with no pr or merge_commit input.
Merge to master: git merge-tree against master conflicts in AddressTypeIntegrationTests.swift, PaykitSdkIdentityCheckTests.swift, UtxoSelectionTests.swift; integration-tests.yml auto-merges (finding below).
CI on the release branch: integration-tests, unit-tests and the E2E runs were still in progress when I read them.
Build: not built here; iOS does not build on Linux.
Cold reader: had not answered on the P1 when this was posted; the finding rests on the merge-tree output and the workflow's own dispatch inputs.

Ruled out

  • Fixture credential reaching PR code on master: the env condition pins github.ref_name == 'release-3.1.1' and empty pr/merge_commit, so on master it evaluates to ''.
  • Fragments collected twice after the merge: master's copies of 1235/1237/1290 come back into changelog.d/next and are collected under [Unreleased] next release; same pattern as 3.0.1, a process choice.
  • Test-file conflicts: master replaced the Blocktank fixture calls with LocalRegtest; resolving to master's side is correct.

Merge confidence: 3/5, one P1 in the workflow that the merge to master carries over.

Reviewer model: claude-opus-5-5
Reasoning effort: Not exposed (the run metadata names the model only)

Comment thread .github/workflows/integration-tests.yml Resolved
@jvsena42

Copy link
Copy Markdown
Member

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

@piotr-iohk

Copy link
Copy Markdown
Collaborator Author

@jvsena42 Thanks for flagging the conflicts. This PR is for reviewing 3.1.1, which is based on v3.1.0 with selected backports. Rebasing onto master would pull in newer changes and require validating a different release candidate. Please review the patch against its release base. 3.1.1 patch diff

After 3.1.1 ships from this branch, we’ll close this PR without merging and open a separate PR on master for the version bump and changelog.

@piotr-iohk

piotr-iohk commented Nov 12, 2026 •

Copy link
Copy Markdown
Collaborator Author

3.1.1 validation after the profile-tag fix

The release branch now includes the tag-preservation fix in signed commit eb94e76cd. ✅ The local simulator build passed with 2,988 unit tests passing and one skipped. The new restore regression passed. Patch against v3.1.0

Check on eb94e76cd Run
Unit and native UI ✅ Passed · 2,988 unit and 39 native UI tests passed · 1 unit and 4 native UI tests skipped
Integration ✅ All 30 tests passed · staging-funded fixtures executed
Local E2E with the shipped 3.1.0 suite Run
Staging E2E Run
Standard migration ✅ 4/4 cases passed · native restore passed on attempt 2 after an Appium session startup timeout

The RN restore fixture recovered from a keyboard permission prompt and a transaction broadcast timeout in RN 1.1.6. All candidate migration cases ran.

@ovi-reviewer ovi-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Verdict: ⚠️ Not verified. I found no defects. The picks, the bitkit-core pin, the version bump and the profile-tag fix are all correct. Local E2E and staging E2E at eb94e76 were still running when I posted.

Findings: none.

QA for eb94e76:

Check: The picks match the 3.1.1 list ✅ The picks are #1237, #1235, #1252, #1290, #1292 and #1250, in that order. All match their master merges except #1237, which differs only in its tests.
  • Checked with git log --first-parent v3.1.0..eb94e76. Each pick's changed lines were diffed against its master merge.
  • #1237 differs by 8 test lines: a fixture id, plus acknowledged, proposalRecordedAt and acceptanceRecordedAt, which exist only on master.
  • Four more commits are direct: 6bcce8f77 (the 3.1.0 changelog line now links #1140; the same commit is on master), the version commit c4bfb1573, the staging-fixture test commit b03f4a610, and the tag fix eb94e76cd.
  • Nothing else is in the patch. No bitkit-core rc15 (#1295) and no Spark/Breez code: the added lines have 0 matches.
Check: Dependency pins ✅ bitkit-core stays at `0.8.0-rc11` (revision `22e0acc`). ldk-node is `0.7.0-rc.80`, vss-client `0.5.26-rc2` and Paykit `0.1.1-rc8`.

The project.pbxproj and Package.resolved changes against v3.1.0 touch only those three packages and the version numbers.

Check: Restoring a profile keeps its tags ✅ Without the fix, a restore save erases the stored tags. With it, they are kept, and no other save path loses them.

The bug at b03f4a610, without the fix:

  1. CreateProfileView keeps the restored profile as existingProfile, loaded through PubkyAppProfileStore.load. That is the production resolver: AppScene.swift:460 uses the default.
  2. When the copy read fails, the profile has empty tags and tagsUnread = true (PubkyAppProfileStore.swift:191).
  3. A later load reads the copy and removes the key from tagsUnavailable (:151). It also remembers the same revision with the real tags (:195).
  4. On Save, copyUnread is false (:219), so storedCopy skips the read (:335). The form's [] differs from previousTags, so the copy is published with no tags.

The fix: eb94e76cd passes existingProfile?.tagsUnread through createIdentity and createProfile into save (CreateProfileView.swift:237, PubkyProfileManager.swift:505/541/778). The store then re-reads the copy and merges the stored tags in (:345-348).

The other save paths: the edit screen (EditProfileView.swift:163) and the profile screen's tag add and remove (ProfileView.swift:284) pass the tagsUnread of the profile they show. The flag travels with the profile, so a load that clears the store flag cannot make a stale form look readable. The load's copy refresh (:196-204) runs only after a successful read. The migration writes to pubky.app only.

The commit: it matches #1303's code commit line for line. Only the changelog fragment is dropped, which is right: this bug never shipped. @jvsena42 reviewed #1303 on master with no findings.

Check: Version and release notes ✅ `MARKETING_VERSION` is 3.1.1 and `CURRENT_PROJECT_VERSION` is 204 on all six app targets. The three fragments are collected into `[3.1.1] - 2026-11-12`, and the compare links are updated.

These notes do not block the release:

  • The Security line names only the Lightning node. It does not mention the VSS client and Paykit rustls updates (#1252, #1292).
  • The collected section leaves five blank lines before ## [3.1.0].
Check: CI at eb94e76 ⏭️ Unit, native UI, integration and standard migration passed. Local E2E and staging E2E were still running.

The earlier candidate's comment left two staging cases to repeat: the $1.11 vs $1.01 amount, and the receipt overlay covering Send. They belong in that staging run.

Considerations:

  • A removed tag can come back: if a load fails to read the copy while the edit form is open, it remembers the form's revision with empty tags (PubkyAppProfileStore.swift:195, :322-330). A save that removes a tag then merges the stored tags back, so the removed tag returns. If the re-read also fails, a "tags not saved" error appears. No stored tags are lost.
  • Talos's cache-mode: read point on integration-tests.yml: this applies only if this branch merges into master. The PR closes unmerged, and the master follow-up carries only the version and the changelog.
  • BLOCKTANK_REGTEST_AUTH: it reaches the integration job only on a workflow_dispatch of release-3.1.1 with empty pr and merge_commit inputs. A pull_request run gets an empty value, so the fixture tests fail there by design.

No device cases were driven here, and I could not show that the new journeys J1–J3 ran at this head. Staging uses e2e main (0ca01e0a2), and its pubky job had not finished. The runs come from @piotr-iohk's validation after the tag fix. The review covered the full v3.1.0...eb94e76 patch, statically.

Twin: synonymdev/bitkit-android#1878 has the matching picks and the same restore fix. Its extras are explained: #1798 is Android-only, and there is no iOS-style test commit. Android has a HIGH that iOS does not have: it reads a global unread flag at save time, while iOS carries the flag on the profile.


Reviewed by claude-opus-5-5

@piotr-iohk

piotr-iohk commented Nov 12, 2026 •

Copy link
Copy Markdown
Collaborator Author

Ovi’s review found no iOS code defects. The signed changelog update in accbdd6f7 records the VSS client and Paykit rustls updates and removes the extra spacing.

The iOS edit and tag flows carry the unread status on the profile they display. If a Paykit read fails during an edit, the conservative merge can still keep a tag the user tried to remove. That behavior preserves stored tags during the outage and remains in this patch.

  • ✅ Local E2E passed on eb94e76.
  • ✅ Staging E2E passed on eb94e76 using E2E commit 0ca01e0a2.
    • ✅ Nightly UI passed all 28 cases on attempt 2, including the amount-entry and two-receipt cases that failed on the earlier candidate. Attempt 1 timed out creating the Appium session before tests ran.
    • ✅ Pubky/Paykit passed all 6 cases on attempt 3 after two Appium startup failures. The standalone transfer and multi-address specs were skipped. Multi-address coverage ran in nightly UI.

The changelog is the only diff between eb94e76 and accbdd6f7.

@piotr-iohk

Copy link
Copy Markdown
Collaborator Author

@ovitrif @jvsena42 Could you review the iOS 3.1.1 release candidate at accbdd6f7 and approve it if it looks good? Staging passed, including all 28 nightly UI cases. The latest commit updates the changelog. Validation results

ovi-reviewer[bot]
ovi-reviewer Bot previously approved these changes Nov 12, 2026

@ovi-reviewer ovi-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Verdict: ✅ Approve. I found no new defects. Release CI has finished successfully, and the latest commit changes only the changelog.

Findings: none.

QA for accbdd6:

Check: Release scope and dependencies ✅ The selected backports, dependency pins and release metadata match the intended 3.1.1 release.

I compared each backport with its original merge. The production changes match; the Paykit backport differs only in tests adapted to the release baseline. The restore-tag follow-up retains the form's unread-tags flag through publication.

The app and extensions use version 3.1.1, build 204. The pins are ldk-node 0.7.0-rc.80, VSS client 0.5.26-rc2, Paykit 0.1.1-rc8, and unchanged bitkit-core 0.8.0-rc11. The changelog now includes the VSS client and Paykit rustls updates.

Check: Edit the shared pubky.app profile ✅ J1 has a recorded device pass on the unchanged edit path.

The profile device report at 49f305a3f shows the name edit reaching pubky.app, preserving its other fields and tags, and surviving relaunch. The edit form, profile screen and profile store match the final source backport. Later changes preserve the unread-tags flag during profile restoration and do not change this journey.

Check: Refuse an oversized request note and send a shorter one ✅ J2 has a recorded device pass on the unchanged proposal and error-handling paths.

The Paykit device review at a1c126d records rejection of the 256-heart note with “Shorten the note and try again.”, followed by “Coffee” reaching the payer's 1,000-sat confirmation. The confirmation was closed without paying. The proposal service and error handling are unchanged in this release.

Check: Explain a rejected signup code ✅ J3 has a recorded device pass on the unchanged signup-error path.

The same Paykit device review records the specific rejected-code message, an available Authorize button, and no identity after canceling. The authorization sheet's handler matches that tested source.

Check: Completed release validation ✅ The release candidate's executable changes passed CI.

These runs tested eb94e76; git diff eb94e76..accbdd6 changes only CHANGELOG.md.

The logs confirm nightly UI and Pubky/Paykit passed after Appium startup retries. The standalone staging transfer and multi-address jobs ran no cases; multi-address coverage ran within nightly UI. The unit/native UI run also retains its reported skips.

Check: Build the reviewed head ✅ A fresh build of `accbdd6` succeeded.

Built from source with Xcode 27.0, Debug/E2E, arm64 for iOS Simulator. The resulting app reports 3.1.1 (204). SwiftFormat 0.64.0 lint on the changed Swift files, translation validation and git diff --check also passed.

I reviewed the full release patch, 6bcce8f...accbdd6, including production code, tests, workflows, pins and release notes. The three listed journeys rely on the linked device recordings and were not re-driven. The restore-tag race and other concurrency/error paths received code review and automated coverage, rather than a new device run.

Twin: bitkit-android#1878 chore: prepare Bitkit 3.1.1 matches the shared profile, proof-sizing, signup-error and USDT timing behavior, including the restore-tag follow-up.


Reviewed by gpt-6.1-sol-high

ovitrif
ovitrif previously approved these changes Nov 12, 2026

@ovitrif ovitrif left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

utAck

@ovitrif
ovitrif dismissed stale reviews from ovi-reviewer[bot] and themself November 12, 2026 13:34

Release PR: reviewed and ready to release, but kept unapproved so it can't merge before the store release.

@ovitrif

ovitrif commented Nov 12, 2026

Copy link
Copy Markdown
Collaborator

✅ Ready to release: review at accbdd6, no findings.

I dismissed both approvals on this PR: a release PR stays unapproved until after the store release, so it can't be merged by accident.

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