Skip to content

perf(mobile): sign iOS events with native secp256k1 - #8446

Open
brow wants to merge 6 commits into
mainfrom
mobile-native-signing
Open

brow wants to merge 6 commits into
mainfrom
mobile-native-signing

Conversation

@brow

@brow brow commented Oct 19, 2026 •

Copy link
Copy Markdown
Collaborator

Routes all mobile event creation through the existing CSecp256k1 library on iOS, replacing Dart signing. Android retains Dart signing and its cached-public-key optimization. Native keypairs are short-lived and wiped after signing; the randomized shared context retains no account secrets.

This PR targets main independently. It changes signing only, preserving existing call scheduling. Media/query worker offloading remains separate.

Validation

Same-process Debug iPhone 17 Pro Simulator comparison: identical kind-24242 inputs, cached public key supplied to both paths, ten warmup calls each, seven samples per burst, alternating order. Both paths run synchronously on the Dart UI isolate. These are complete event-construction elapsed times, not UIKit main-thread CPU time or rendered-frame measurements.

Events per burst Dart median Native median Time saved
1 3.62 ms 0.88 ms 2.74 ms
8 26.50 ms 6.66 ms 19.84 ms
32 104.67 ms 25.61 ms 79.07 ms
64 209.65 ms 50.21 ms 159.44 ms

Native signing reduces the 64-event burst by 76% (4.2x faster). This is not a physical-device Release benchmark. The reproducible comparison is in mobile/tool/compare_event_signers.dart.

  • Standalone-on-main validation: actual linked Runner signing/media/query probe, five Dart-to-C tests, 57 relay/media regression tests, and Flutter analysis pass.
  • Linked-Runner CI exercises production DynamicLibrary.process(); device Release CI checks all three exported symbols in the postprocessed archive. Earlier missing-export mutations each produced the expected lookup failure, then passed when restored. Current-head Codex review found no major issues. All current-head GitHub checks passed, including the linked Simulator probe and postprocessed Release archive export checks. Current-head Codex review found no major issues.
  • Review fixes: the hosted identity-binding service now uses the shared signer. Its actual Simulator signature/browser-return probe and focused tests pass; restoring the direct Dart constructor makes the inventory guard fail. A local device Release archive succeeds and retains all three exports after Xcode stripping.
  • Full local just ci stopped at the unchanged desktop reaps_descendant_on_timeout test: its PID file was empty under a 300 ms deadline (3,421 passed, 1 failed, 19 ignored). The isolated rerun passed. No desktop code changed; this is not a full-suite pass.
  • Basic internal-relay simulator smoke passed on this head: normal app pairing, channel list, channel timeline, message image and avatars rendered. No public message was posted. Personal human testing is not applicable under the standing mobile exception.

@brow

brow commented Oct 19, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

Codex Review Summary

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

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-20T19:55:19.447366Z 7aa63ef Draft marked ready
ℹ️ 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.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Chef's kiss.

Reviewed commit: 657c9e04bd

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@brow
brow marked this pull request as ready for review October 19, 2026 01:27
@brow
brow requested a review from a team as a code owner October 19, 2026 01:27

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 657c9e04bd

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/_ci-clients.yml
@brow
brow marked this pull request as draft October 19, 2026 01:36

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

:bot: Jude’s code review agent

Verdict: REQUEST CHANGES

Reviewed: 6c5102ac40a5f5135affdf177e7eeb09922a8935..657c9e04bd77ca945591df81fd5bf2de35c9d75d (exact head 657c9e04bd77ca945591df81fd5bf2de35c9d75d)

Risk: critical — every iOS event signature and its private key now cross a new Dart → C FFI and app-linking boundary.

Blocking finding

[P2] The required regression bypasses the production iOS Runner linking seam.

scripts/test-mobile-native-signing.sh:9-18 builds a standalone macOS dylib and supplies it through BUZZ_SIGNER_LIBRARY; mobile/test/shared/crypto/event_signer_test.dart:9-12,30-34 then opens that dylib directly. Meanwhile, the test’s ordinary signEvent case runs on macOS, so mobile/lib/shared/crypto/event_signer.dart:19-27 takes the Dart fallback. No checked-in CI command launches mobile/tool/native_signing_probe.dart inside the built Runner.

The suite therefore never exercises the shipped iOS lookup through DynamicLibrary.process() (mobile/lib/shared/crypto/event_signer.dart:39,45-64) or proves that the retention flags in mobile/ios/Flutter/Debug.xcconfig:31-32 and mobile/ios/Flutter/Release.xcconfig:21-22 keep all three symbols reachable. Removing or breaking a retention/export flag leaves the standalone-dylib tests and app build green, but the first signing call in the app fails at runtime. This violates the repository’s production-seam/falsifiability requirement in AGENTS.md:234-238 and TESTING.md:25-31.

Author action: add a CI regression that executes signEvent through DynamicLibrary.process() in the actual linked iOS Runner for both Debug and Release configurations. It should validate a canonical signed event and the media worker-isolate path. Mutation-prove the regression by removing or breaking each required linker-retention symbol/flag and showing that the linked-Runner journey fails causally.

Verification owner: author for the regression and mutation evidence; exact-head CI for execution; reviewer for the fresh-head delta and final immutable-head check.

Integrated trace

No additional concrete defect was found in the reviewed head:

  • Dart/native declarations match the C pointer and status contracts; malformed or invalid 32-byte scalars fail explicitly.
  • Canonical hashing remains in nostr.Event.unsigned; native code signs that 32-byte ID with a 64-byte BIP340 signature, returns the x-only public key, and self-verifies.
  • The randomized process context is initialized once and then read-only. Each signing call owns its keypair; native keypair/auxiliary randomness and the Dart scratch arena are wiped. No account or host secret cache was added.
  • Swift coverage exercises concurrent independent identities and recovery after per-call failure. All production event creation found under mobile/lib routes through signEvent; the remaining nostr.Event.from is the intentional non-iOS fallback.
  • The bounded media path remains serialized, capped at 64, and off the UI isolate. The changed UI signing callers do not add a new burst loop; typing remains throttled. Android deliberately retains the Dart signer.

Validation

At exact head 657c9e04bd77ca945591df81fd5bf2de35c9d75d with a clean detached checkout:

  • PASS: just mobile-install && just mobile-check — formatting clean; Flutter analysis reported no issues.
  • PASS: just file-size-check.
  • PASS: git diff --check.
  • PASS: terminal GitHub rollup: 56 successful, 23 skipped by workflow/matrix routing, 0 failed, 0 pending. Relevant green jobs include all Flutter shards, Android, Mobile Checks, Mobile Swift Native, Mobile Swift Release, Security, and aggregates.
  • BLOCKED by reviewer environment, not PR-caused: local just mobile-test stopped before test execution because the host’s Xcode 27.1 license is not accepted.
  • Not independently witnessed: a real linked-Runner journey and physical-device Release latency. The latter is a release/performance confidence gap, not an additional author defect; current latency claims are simulator/host measurements and preserve the existing worker queue.

@brow

brow commented Oct 19, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@jedwards27
jedwards27 dismissed their stale review October 19, 2026 01:41

Dismissed because the PR head advanced before submission completed. This review applies only to 657c9e0; a fresh review of the new head is required.

@brow
brow requested a review from jedwards27 October 19, 2026 01:44
@brow

brow commented Oct 19, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Can't wait for the next one!

Reviewed commit: 3a26907bd6

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

brow added 4 commits October 20, 2026 10:15
Signed-off-by: Tom Brow <tomb@block.xyz>
Signed-off-by: Tom Brow <tomb@block.xyz>
Signed-off-by: Tom Brow <tomb@block.xyz>
@brow
brow force-pushed the mobile-native-signing branch from 3a26907 to 58f54a2 Compare October 20, 2026 17:22
@brow
brow changed the base branch from mobile-navigation-layout to main October 20, 2026 17:23
@brow

brow commented Oct 20, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🚀

Reviewed commit: 58f54a20b9

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@brow
brow marked this pull request as ready for review October 20, 2026 17:56
@brow
brow deployed to codex-review October 20, 2026 17:56 — with GitHub Actions Active
@github-actions github-actions Bot added the codex-security-review-current The posted Codex security review matches its recorded range. label Oct 20, 2026
@github-actions

github-actions Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

🔐 Codex Security Review

Note: This is an automated, security-focused review generated by Codex.
Use it as a supplement to human review; false positives are possible.

Scope

  • Exact PR diff: fcdabcf774203884c4f5b258aad000a740586eb6...7aa63ef33493e7db82a5068556e3d20929610979
  • Model: gpt-6.1-sol

💡 Click "edited" above to see earlier reviews for this PR.


Review Summary

Overall Risk: NONE

No concrete security, correctness, or reliability findings identified in the authorized PR range.

Findings

No concrete security, correctness, or reliability findings were identified.

Notes

  • Review used read-only source and history inspection. Builds, tests, and native iOS runtime validation were not executed.

Generated by Codex Security Review |
Requested by: @brow |
Workflow run

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

🤖 Star Lord’s automated source review via Wes’s account, integrating independent Rocket, Mantis and Groot reviews.

Reviewed head 58f54a20b9af13226368fa12e027e4261057c4e2 against base/merge-base 0b53fc699dd649ec483c07d628f9c41197607a3c.

One P1 release-configuration finding inline. No additional actionable correctness, secret-handling, concurrency or caller-flow defects found. Canonical event hashing, per-call native keypair cleanup and the Android fallback remain consistent with existing behavior. The linked Runner probe addresses the earlier standalone-dylib test gap; archive postprocessing is a separate boundary.

Optional wording note: the description says “all mobile event creation,” but mobile/lib/shared/hosted/web_connect_binding.dart:54 still uses the existing Dart signer. Narrow that wording if desired; this unchanged one-shot caller is not a functional regression.

Validation: source inspection only; no PR code, tests, builds, archives or apps executed. Read-only CI snapshot: 78 successful and 29 skipped checks, including successful Mobile Swift Native and Release jobs. Those results do not verify a postprocessed archive/IPA, installed-device symbol lookup, physical-device performance, native error/retry focus or accessibility. Current signing calls and the probe remain synchronous on the UI isolate; worker offloading is separate. Public description inspected, no attached screenshots or actionable disclosure found; a historical review’s third-party severity badge was not rendered. This COMMENT is non-blocking feedback, not approval or merge authorization.

#include? "AppOverrides.xcconfig"

// Keep the Dart FFI entry points visible in the app executable.
OTHER_LDFLAGS = $(inherited) -Wl,-u,_buzz_signer_create -Wl,-u,_buzz_signer_sign -Wl,-u,_buzz_signer_destroy

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.

🤖 [P1] Preserve the FFI exports through archive stripping

These -u flags force the three functions into the linked executable, but do not preserve them through the subsequent archive/install strip step. Runner’s checked-in scheme archives Release, and its tracked configuration leaves STRIP_STYLE at Xcode’s default All Symbols. For a normal archive without an external override, the runtime-only buzz_signer_* exports can therefore be stripped even though the ordinary device build passes nm. The first DynamicLibrary.process() lookup in event_signer.dart then fails, breaking the migrated iOS authentication, media and send paths.

Set STRIP_STYLE = non-global for Runner Release (or explicitly preserve these exported symbols), as prescribed by Flutter’s iOS FFI stripping guidance, and check all three exports in the postprocessed archive/IPA executable. The current CI check at _ci-clients.yml:256–262 inspects flutter build ios --release --no-codesign, so it misses archive stripping. This is a source/configuration finding; I did not build an archive or observe an installed-app failure, and external release overrides were not inspected.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🤖 Addressed in 7aa63ef. Runner Release now uses non-global stripping, and CI inspects the postprocessed archive executable. A local unsigned device Release archive succeeded; its log confirms strip -x and nm -gU confirms all three buzz_signer exports remain. This validates archive retention without claiming installed physical-device execution.

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

:bot: Jude’s code review agent

Verdict: REQUEST CHANGES

Reviewed: 0b53fc699dd649ec483c07d628f9c41197607a3c..58f54a20b9af13226368fa12e027e4261057c4e2 (exact head 58f54a20b9af13226368fa12e027e4261057c4e2)

Risk: critical — mobile identity secrets and every migrated iOS event signature cross a new Dart → C FFI and app-linking boundary.

Blocking finding

[P2] One live iOS event-creation path still bypasses the shared/native signer.

mobile/lib/shared/hosted/web_connect_binding.dart:54 still constructs its kind-24243 identity-binding event with nostr.Event.from(...). This is production behavior reached by hosted account binding and browser return at mobile/lib/shared/hosted/hosted_flow.dart:494 and :528. On iOS it therefore continues through the Dart secp256k1 implementation instead of this PR's signEvent / DynamicLibrary.process() route.

A source inventory at the reviewed head found only two direct nostr.Event.from calls under mobile/lib: the intentional non-iOS fallback at mobile/lib/shared/crypto/event_signer.dart:22, and this hosted binding call. The latter predates the PR, but omitting it leaves the PR's stated migration—“Routes all mobile event creation” and the new mobile/README.md:84 rule to use the shared signer—materially incomplete in a real identity flow.

Author action: route the hosted binding event through signEvent(..., pubkey: keys.public) and add regression coverage that prevents a production direct-constructor bypass from returning. Preserve the existing account/pubkey checks and hosted-binding behavior.

Verification owner: author for the patch and regression; exact-head CI for the linked iOS Runner/native-symbol gates; reviewer for the fresh caller inventory and hosted-flow trace.

Integrated trace

No second author-actionable defect was found:

  • Dart/native declarations match the C pointer/status contracts. Canonical event hashing remains in nostr.Event.unsigned; native code derives the x-only key, emits a 64-byte BIP340 signature, and self-verifies it.
  • The randomized process context is initialized once and then used read-only. Keypair handles and per-sign auxiliary randomness are per-call and wiped; no account/host secret cache was added. Concurrent independent keypairs have Swift coverage.
  • The actual Debug Runner executes the signer through DynamicLibrary.process(). The current probe validates ordinary events, synchronous media-auth signatures and foreign-host isolation, and NIP-98 query signatures. The device Release job checks all three exports in the actual Buzz.app/Buzz executable.
  • Current-tree scope matters: mobile/tool/native_signing_probe.dart:63-65 invokes synchronous MediaGetAuthService.headersFor, and this tree has no headersForAsync worker-isolate route. Earlier-head claims that the probe covers a media worker isolate do not apply. This is not an additional defect because the PR now explicitly preserves synchronous scheduling and treats offloading as separate work.
  • The revised performance claim is properly limited to complete synchronous Debug Simulator event construction, not rendered-frame or physical-device Release performance. No new media/navigation state transition was introduced.

Validation

At clean detached HEAD 58f54a20b9af13226368fa12e027e4261057c4e2:

  • PASS: git diff --check.
  • PASS: bash -n scripts/test-mobile-linked-signing.sh.
  • SOURCE TRACE: rg -n 'nostr\.Event\.from\(' mobile/lib -g '*.dart' found the intentional fallback and the hosted-binding bypass above.
  • PASS: exact-head GitHub rollup is terminal: 78 success, 29 workflow/matrix skips, 0 failed or pending.
  • PASS: Mobile Swift Native ran the linked Debug Runner and logged SIGNING_PROBE COMPLETE, valid media/host-isolation results, and valid query signatures.
  • PASS: Mobile Swift Release built build/ios/iphoneos/Buzz.app and completed the exact-export checks for buzz_signer_create, buzz_signer_sign, and buzz_signer_destroy.

Manual/native evidence: exact-head CI executed the actual linked Debug Simulator Runner and inspected the actual device Release executable. I did not independently run a physical-device Release build or rendered-frame journey.

Residual risk: physical-device Release latency and user-visible frame behavior remain unwitnessed. Those are release/performance confidence gaps, not additional author rework; the checked-in claim is correctly narrower.

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

:bot: Jude’s code review agent

Verdict: REQUEST CHANGES

Reviewed: 0b53fc699dd649ec483c07d628f9c41197607a3c..58f54a20b9af13226368fa12e027e4261057c4e2 (exact head 58f54a20b9af13226368fa12e027e4261057c4e2)

Risk: high — this migration changes the private-key/signature boundary for iOS event creation, but one live identity-binding path still bypasses that boundary.

Blocking finding

[P1] The hosted web-connect identity-binding flow still signs in Dart instead of using the native iOS signer.

mobile/lib/shared/hosted/web_connect_binding.dart:54-73 creates the kind-24243 binding event with nostr.Event.from(...). Both live hosted-flow branches call this service: automatic identity binding at mobile/lib/shared/hosted/hosted_flow.dart:494-501, and an incoming NostrBindDeepLink immediately before browser return at mobile/lib/shared/hosted/hosted_flow.dart:528-539.

On iOS, these journeys therefore bypass signEvent and retain synchronous Dart secp256k1 signing on the UI isolate. That contradicts the PR’s stated contract to route all mobile/iOS event creation through the shared native signer, leaving a real account-binding event outside the migration. The existing mobile/test/shared/hosted/web_connect_binding_test.dart:89-123 validates the event shape, but passes while the direct-constructor bypass remains; it does not bind the hosted route to the production signer.

Author action: replace the direct constructor with signEvent(kind: 24243, ..., secretKey: keys.secret, pubkey: keys.public, verify: false). Add hosted-binding/return coverage bound to that production seam and a caller-inventory guard that rejects direct production Event.from signing outside the intentional non-iOS fallback. Extend the linked iOS Runner probe to exercise the hosted kind-24243 route causally, rather than only a synthetic event of that kind.

Verification owner: author for the patch and regressions; reviewer for fresh-head production-caller inventory and mutation bite; linked iOS CI for process-native execution of kind 24243.

Integrated review

No separate author-actionable defect was found in the reviewed ABI signatures, canonical hash/native-pubkey/BIP340 path, per-call key/handle cleanup, randomized shared read-only context, identity isolation, explicit missing-symbol failure, Debug linked-Runner lookup, Release executable symbol retention, or revised benchmark wording.

The rebased linked probe at mobile/tool/native_signing_probe.dart:63-65 calls synchronous MediaGetAuthService.headersFor; exact-tree search found no headersForAsync under mobile/lib, mobile/tool, or mobile/test. It therefore proves synchronous media-auth signature and host-isolation behavior, not worker-isolate behavior. That corrects earlier-head evidence; it is not a second defect because this tree exposes no worker-isolate media-signing route.

Validation

At clean detached HEAD 58f54a20b9af13226368fa12e027e4261057c4e2:

  • PASS: git diff --check 0b53fc699dd649ec483c07d628f9c41197607a3c...HEAD.
  • PASS: exact-head GitHub rollup is terminal: 78 passed, 29 skipped by workflow/matrix routing, 0 failed or pending. Relevant green jobs include all Flutter shards, Android, Mobile Checks, Mobile Swift Native linked-Runner execution, Mobile Swift Release symbol inspection, Security, and aggregates.
  • PASS: production-caller inventory found the intentional non-iOS fallback at mobile/lib/shared/crypto/event_signer.dart:22 and the omitted hosted signer at mobile/lib/shared/hosted/web_connect_binding.dart:54.
  • Not independently witnessed: physical-device Release execution and rendered-frame latency. The PR correctly limits its benchmark to synchronous Debug Simulator event-construction timing; these remain release/performance confidence gaps, not additional author rework.

@brow
brow marked this pull request as draft October 20, 2026 18:12
brow added 2 commits October 20, 2026 11:13
Signed-off-by: Tom Brow <tomb@block.xyz>
Signed-off-by: Tom Brow <tomb@block.xyz>
@github-actions github-actions Bot removed the codex-security-review-current The posted Codex security review matches its recorded range. label Oct 20, 2026
@brow

brow commented Oct 20, 2026

Copy link
Copy Markdown
Collaborator Author

🤖 Addressed the hosted-binding bypass in 4153655. The production service now uses signEvent with its cached public key. Focused tests and analysis passed; the actual iOS Runner executed the service and verified the kind-24243 signature before browser return. Restoring the direct constructor caused the new production inventory guard to fail on that exact file. Fresh CI and review are pending.

@brow
brow dismissed stale reviews from jedwards27 and jedwards27 October 20, 2026 18:23

blockers resolved

@brow
brow requested a review from jedwards27 October 20, 2026 18:23
@brow

brow commented Oct 20, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Breezy!

Reviewed commit: 7aa63ef334

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@brow
brow marked this pull request as ready for review October 20, 2026 19:52
@brow
brow deployed to codex-review October 20, 2026 19:52 — with GitHub Actions Active
@github-actions github-actions Bot added the codex-security-review-current The posted Codex security review matches its recorded range. label Oct 20, 2026

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

:bot: Jude’s code review agent

Verdict: APPROVE

Reviewed: 0b53fc699dd649ec483c07d628f9c41197607a3c..7aa63ef33493e7db82a5068556e3d20929610979 (exact head 7aa63ef33493e7db82a5068556e3d20929610979)

The prior hosted web-connect bypass and Release archive-stripping concerns are resolved. No author-actionable defect remains.

Integrated review

  • Dart’s three FFI declarations match the C header. Dart constructs the canonical unsigned event hash and passes exactly 32 ID bytes; native code produces and self-verifies the 64-byte BIP340 signature against the x-only public key. Invalid scalar and randomness failures are explicit, with no fallback.
  • pthread_once publishes one randomized read-only context. Each call owns its keypair and auxiliary randomness, wipes native key material plus the Dart arena, and cleans up on all exits. Swift coverage exercises concurrent independent keys and invalid-key recovery; no account or host secret cache was introduced.
  • Production inventory under mobile/lib finds 14 signEvent call sites and only one direct Event.from: the intentional non-iOS fallback. The formerly omitted hosted kind-24243 path now calls signEvent with the resolved identity pubkey while retaining cancellation, identity-match, server-verification, and browser-return ordering.
  • The inventory regression is causal: mutating hosted binding back to Event.from makes it fail with the exact production file, then pass after restoration.
  • Debug CI builds and launches the actual iOS Runner, exercising DynamicLibrary.process(). The exact-head probe verifies message, media, NIP-98, foreign-host isolation, hosted kind-24243 binding, and verified browser return before completion.
  • Release CI archives the device app and checks all three required exports after archive stripping. The exact-head log reaches ARCHIVE SUCCEEDED and all post-strip symbol checks pass.
  • Android intentionally retains the existing Dart signer. iOS missing-symbol and native failures remain explicit. The documented performance result is correctly scoped to synchronous Debug Simulator event construction rather than rendered frames or physical-device Release behavior.

Validation

At exact head 7aa63ef33493e7db82a5068556e3d20929610979:

  • PASS: focused shared-signer and hosted-binding tests: 7 passed, 4 expected native-library skips locally; native execution is covered by the linked macOS CI lanes.
  • PASS: git diff --check; clean detached worktree during review.
  • PASS: live GitHub rollup was terminal immediately before submission: 94 completed checks, no failed, cancelled, pending, or action-required checks. CI run 39473757621 is successful at this head, including mobile shards, Android, linked Mobile Swift Native, archived Mobile Swift Release, Security, and aggregate jobs; other entries are workflow/matrix skips.
  • PASS: authenticated reviewer is jedwards27, distinct from PR author brow; PR remained open, non-draft, mergeable, and pinned to the reviewed head immediately before submission.

Confidence gaps

No signed/TestFlight physical-device Release journey was observed. Current evidence proves linked Debug Runner behavior and post-strip Release export retention, not physical-device Release latency or distribution behavior. This is release confidence, not author remediation.

Author action: none.

Verification owner: Release/QA for an optional signed physical-device/TestFlight smoke across hosted binding and verified browser return, identity switching, message/auth/media signing, and perceived responsiveness. Any new head invalidates this approval and requires delta review.

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

🤖 Star Lord’s automated source review via Wes’s account, integrating independent Rocket, Mantis and Groot reviews.

Reviewed head 7aa63ef33493e7db82a5068556e3d20929610979 against base/merge-base 0b53fc699dd649ec483c07d628f9c41197607a3c, including the five-file follow-up from previously reviewed head 58f54a20b9af13226368fa12e027e4261057c4e2.

No actionable findings. The earlier archive-stripping finding is addressed in source: Release now sets STRIP_STYLE = non-global, and CI checks the three FFI exports in the postprocessed archive executable. Hosted identity binding now uses the shared signer while retaining identity checks, server verification before browser return, and the existing cancellation/retry flow. The linked Runner probe includes that binding path.

Validation: source inspection only; no PR code, tests, builds, archives or apps executed by this review. A read-only current-head CI snapshot showed 62 successful and 32 skipped checks. We did not independently verify installed-device symbol lookup, physical-device performance, native error/retry focus, accessibility, or external release overrides. Signing remains synchronous; worker offloading is separate. Public PR description inspected with no attached screenshots or actionable disclosure found; a historical review’s third-party severity badge was not rendered. This COMMENT is non-blocking feedback, not approval or merge authorization.

This branch was successfully deployed

1 active deployment
codex-review — 7aa63ef3 Deployed Oct 20, 2026 by brow via Run Codex Security Review #9221
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

codex-security-review-current The posted Codex security review matches its recorded range.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants