Skip to content

feat(web): generate WIP-103 ownership proofs in the browser - #629

Open
kchaw2005 wants to merge 3 commits into
mainfrom
feat/web-prove-credential-sub
Open

kchaw2005 wants to merge 3 commits into
mainfrom
feat/web-prove-credential-sub

Conversation

@kchaw2005

@kchaw2005 kchaw2005 commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Why

  • The web authenticator needs to prove ownership of a credential sub (WIP-103) in the browser. proveCredentialSub was stubbed out on wasm32 because ProveKit was native-only.
  • world-id-protocol 0.17.1 (#1132) enables ownership proving on wasm32 and requires provekit-spongefish 0.2.1, which hashes its squeeze counters as u64. Browser (32-bit) and native transcripts now match.

What

  • Bump world-id-core and world-id-proof 0.16 → 0.17.1. The lockfile moves every world-id-* crate to 0.17.1 and provekit-spongefish / -pow to 0.2.1, and adds lzma-rs. No git patches.
  • Core: remove the wasm32 stub. prove_credential_sub delegates to a Rust-only prove_credential_sub_at(…, now), which isn't exported over uniffi.
  • Web: authenticator.proveCredentialSub(nonce, context, blindingFactor, sub, now?) returns the CBOR-encoded proof as a Uint8Array. The README documents the user-action requirement, the default now, and cancelling with terminate().
  • Supersedes chore: adopt published Spongefish transcript fix #626.

Test

Check Result
cargo fmt, Prettier clean
Clippy native walletkit-core --all-targets and wasm32 walletkit-web, -D warnings clean
walletkit-core unit tests 262 passed
WASM package build and consumer type checks pass
Package browser tests (Chrome) 15 passed; the opt-in staging spec is skipped by default
Browser-generated proof verified natively verifies; a proof with a changed context, nonce or sub is rejected
cargo deny check bans licenses sources pass
cargo deny check advisories ok, with ctutils and tokio bumped as in #630 (RUSTSEC-2026-0385, -0386)

The cross-target check is opt-in and uses WALLETKIT_STAGING_PROOF:

  1. tests/staging-ownership.spec.ts generates a proof in Chrome for a registered staging account and writes it to that path.
  2. crates/walletkit-core/tests/ownership_cross_target.rs verifies it natively with the embedded ownership verifier. Without the variable it does nothing.

Measured on desktop Chrome against staging: about 1.0 s to prove, and a 570 KB CBOR proof.

Not run yet: the wasm-bindgen worker tests on Firefox; the package tests on Safari or Firefox; proving time on a phone.

Risk

  • walletkit.wasm grows from 42.14 MB to 44.20 MB (+2.06 MB raw, +1.1 MB gzip, +1.0 MB brotli). About 1.1 MB is the ownership .pkp/.pkv keys; the rest is the WASM witness solver and decoder. For context, 38.1 MB of the module is embedded proving keys (36 MB of it OPRF zkeys). Loading keys on demand instead of embedding them would be a separate change.
  • WASM witness solving supports single-function circuits without foreign or ACIR calls (per #1132). Native and mobile keep ProveKit's original path.
  • Proving occupies the worker and can't be cancelled per call. Callers should pick a timeout from real-device measurements.

AI assistance

  • Prepared with Claude (Opus 5.5) in Claude Code. It rebased the existing branch, replaced the git patches with the published releases, added the cross-target test, and ran the checks above.

Note

Medium Risk
Adds browser-side ZK ownership proving and bumps cryptographic/protocol dependencies (~2 MB WASM growth); proving is security-sensitive and must stay user-initiated, but verification and cross-target tests mitigate transcript mismatch risk.

Overview
Enables WIP-103 credential ownership proving in the browser by bumping world-id-core / world-id-proof to 0.17.1 (with provekit-spongefish 0.2.1 in the lockfile) so wasm32 can run the same ownership prover as native.

Core drops the wasm32 error stub: prove_credential_sub now forwards to a new prove_credential_sub_at(..., now) path so wasm callers supply Unix time (native still resolves now itself). Web exposes authenticator.proveCredentialSub, returning CBOR as Uint8Array, with optional now defaulting like generateProof. Docs remove ownership proving from the browser limitations table and describe user-action and worker-blocking behavior.

CI installs nargo and prefetches Noir deps in the wasm-check job so world-id-proof can build wasm32 artifacts. Tests: opt-in Playwright staging spec writes a proof; ownership_cross_target verifies it natively and rejects tampered public inputs; consumer typings include the new API.

Reviewed by Cursor Bugbot for commit fa10c16. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • New Features
    • Browser clients can now generate credential ownership proofs, with an optional timestamp that defaults to the browser clock.
  • Documentation
    • Added guidance on generating ownership proofs, including browser usage limitations and how to cancel a proof operation.

@coderabbitai

coderabbitai Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: b85cb4a3-4af4-4622-9c71-ef01c4045444
Commits

Reviewing files that changed from the base of the PR and between 301fa6d and fa10c16.

Files ignored due to path filters: 1
  • Cargo.lock is excluded by !**/*.lock
Files selected for processing: 9
  • .github/workflows/ci.yml
  • Cargo.toml
  • crates/walletkit-core/src/authenticator/mod.rs
  • crates/walletkit-core/tests/ownership_cross_target.rs
  • crates/walletkit-web/src/authenticator.rs
  • crates/walletkit-web/src/lib.rs
  • web/walletkit/README.md
  • web/walletkit/tests/staging-ownership.spec.ts
  • web/walletkit/tests/types/consumer.ts

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

Walkthrough

The core now generates credential-sub ownership proofs on WASM through a timestamp-based method. The web API exposes proof generation to JavaScript. Opt-in browser and native tests cover proof generation and verification.

Changes: Credential ownership proofs

Layer / File(s) Summary
Core proof generation
Cargo.toml, crates/walletkit-core/src/authenticator/mod.rs
The workspace pins world-id-core and world-id-proof to version 0.17.1. The core adds timestamp-based proof generation, and the existing method delegates to it.
Web ownership proof API
crates/walletkit-web/src/authenticator.rs, crates/walletkit-web/src/lib.rs, web/walletkit/README.md, web/walletkit/tests/types/consumer.ts
The web authenticator exposes proveCredentialSub and returns encoded proof bytes. The documentation and consumer typing check describe and exercise the API.
Cross-target proof validation
web/walletkit/tests/staging-ownership.spec.ts, crates/walletkit-core/tests/ownership_cross_target.rs, .github/workflows/ci.yml
An opt-in browser test writes a generated proof and its inputs to JSON. An opt-in native test verifies the proof and checks altered inputs. The CI job installs Nargo and prefetches Noir dependencies.

Priority: Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant JsAuthenticator
  participant Authenticator
  Caller->>JsAuthenticator: proveCredentialSub inputs and optional timestamp
  JsAuthenticator->>Authenticator: prove_credential_sub_at with resolved timestamp
  Authenticator-->>JsAuthenticator: OwnershipProof
  JsAuthenticator-->>Caller: CBOR-encoded Uint8Array
Loading

Suggested reviewers: dzejkop, paolodamico

Merge Risk: Minimal · up to fa10c

The browser proof API returns proof bytes as documented, and no actionable issue remains before merge. Firefox, Safari, and phone performance have not been validated.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 10 functions across 6 files. (3 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main change: browser-side generation of WIP-103 ownership proofs.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 10 functions across 6 files. (3 skipped: 3 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

Comment @coderabbitai help to get the list of available commands.

@kchaw2005

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 23, 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-25T02:42:44.067795Z fa10c16 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 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: baa772ba95

ℹ️ 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 on lines +473 to +474
#[wasm_bindgen(js_name = proveCredentialSub, unchecked_return_type = "Promise<Uint8Array>")]
pub fn prove_credential_sub(

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3 Badge Update the facade docs for the ownership-proof export

When developers inspect the Rust facade documentation, this new export contradicts crates/walletkit-web/src/lib.rs, whose module docs still state that credential ownership proofs are native-only. This makes the newly supported browser API appear unavailable, so update that module-level description alongside the export.

AGENTS.md reference: AGENTS.md:L53-L55

Useful? React with 👍 / 👎.

@kchaw2005

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep it up!

Reviewed commit: c00f1bd98e

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

Kartike Chawla added 2 commits October 23, 2026 15:21
Bump world-id-core and world-id-proof to 0.17.1, which enables ownership
proving on wasm32 and requires provekit-spongefish 0.2.1 (target-independent
transcripts). Remove the wasm32 stub: prove_credential_sub delegates to
prove_credential_sub_at(now), and walletkit-web exposes
authenticator.proveCredentialSub(nonce, context, blindingFactor, sub, now?)
returning the CBOR proof.

Add an opt-in cross-target check: the staging browser spec writes a proof that
tests/ownership_cross_target.rs verifies natively and rejects with a changed
context, nonce or sub.
world-id-proof 0.17.1 builds the ownership proof artifacts for wasm32, so its
build script now needs nargo there too, as the native jobs already provide.
@kchaw2005
kchaw2005 force-pushed the feat/web-prove-credential-sub branch from 004f37b to 10328a1 Compare October 23, 2026 22:22
@kchaw2005
kchaw2005 marked this pull request as ready for review October 25, 2026 02:40
Copilot AI balanced review requested due to automatic review settings October 25, 2026 02:40

Copilot AI 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.

🔵 Needs a closer look

Security-sensitive proving and transcript changes warrant human sign-off, with cross-browser and phone validation still outstanding.

No open issues 🎉

What changed in this PR

Enables browser-side WIP-103 credential ownership proofs through WalletKit’s existing worker API, using protocol dependencies that support matching browser and native transcripts.

Changes:

  • Adds proveCredentialSub, returning CBOR proof bytes with an optional browser-clock timestamp.
  • Updates protocol and transcript dependencies and adds the required WASM CI tooling.
  • Adds consumer type coverage, opt-in browser-to-native verification, and usage documentation.

No critical issues were identified. Residual validation gaps include cross-browser behavior and phone performance; cross-target verification remains opt-in.

File Description
web/​walletkit/​tests/​types/​consumer.ts Checks the ownership-proof API’s return type.
web/​walletkit/​tests/​staging-ownership.spec.ts Generates a browser proof for opt-in native verification.
web/​walletkit/​README.md Documents ownership proving, timing defaults, and cancellation.
crates/​walletkit-web/​src/​lib.rs Removes the outdated native-only ownership-proof limitation.
crates/​walletkit-web/​src/​authenticator.rs Exposes ownership proving as CBOR bytes to JavaScript.
crates/​walletkit-core/​tests/​ownership_cross_target.rs Verifies browser proofs natively and rejects altered public inputs.
crates/​walletkit-core/​src/​authenticator/​mod.rs Replaces the WASM stub with a shared, caller-timed proving path.
Cargo.toml Requires protocol dependencies at version 0.17.1.
Cargo.lock Updates protocol and transcript packages and adds WASM prover dependencies.
.github/​workflows/​ci.yml Installs nargo and prefetches Noir dependencies for WASM checks.

Review effort: Balanced

@coderabbitai

coderabbitai Bot commented Oct 25, 2026

Copy link
Copy Markdown
Contributor

Auto-fix stopped before satisfying the configured readiness conditions.

Blocking condition: Auto-fix requires data retention to be enabled for the organization.

Triggered by rule Auto-fix PRs. This is the Auto-fix result for commit fa10c16; it does not confirm that the pull request was merged.

View activity

This branch has not been deployed

No deployments
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.

2 participants