Upgrade: bifold 3.0.16 / credo-ts 0.6.3 / React 19 + DTG VC 2.0 + eddsa-rdfc-2022 Data Integrity & witnessed exchange#31
Open
albertoleon7794 wants to merge 2259 commits into
Open
Upgrade: bifold 3.0.16 / credo-ts 0.6.3 / React 19 + DTG VC 2.0 + eddsa-rdfc-2022 Data Integrity & witnessed exchange#31albertoleon7794 wants to merge 2259 commits into
albertoleon7794 wants to merge 2259 commits into
Conversation
Signed-off-by: "github-actions[bot]" <"41898282+github-actions[bot]@users.noreply.github.com"> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Signed-off-by: Travis Lee <travislee2k15@gmail.com>
Signed-off-by: "github-actions[bot]" <"41898282+github-actions[bot]@users.noreply.github.com"> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Signed-off-by: ehanoc <ehanoc@protonmail.com>
Signed-off-by: Christian Lippa <christian.lippa@ontario.ca> Co-authored-by: Mostafa Gamal <46829557+MosCD3@users.noreply.github.com>
Signed-off-by: Matthew Golshani <matthew.golshani@gov.bc.ca> Co-authored-by: Matthew Golshani <matthew.golshani@gov.bc.ca> Co-authored-by: Al Rosenthal <alfred.k.rosenthal@gmail.com>
Signed-off-by: Bryce McMath <bryce.j.mcmath@gmail.com> Signed-off-by: Bryce McMath <32586431+bryce-mcmath@users.noreply.github.com>
Signed-off-by: "github-actions[bot]" <"41898282+github-actions[bot]@users.noreply.github.com"> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Signed-off-by: ehanoc <ehanoc@protonmail.com>
Signed-off-by: Travis Lee <travislee2k15@gmail.com> Signed-off-by: traviskhl <travislee2k15@gmail.com> Co-authored-by: Al Rosenthal <alfred.k.rosenthal@gmail.com>
Signed-off-by: Bryce McMath <bryce.j.mcmath@gmail.com>
…2337 (#1581) Signed-off-by: Mac Deluca <Mac.Deluca@quartech.com>
… (#1583) Signed-off-by: Matthew Golshani <matthew.golshani@gov.bc.ca> Co-authored-by: Matthew Golshani <matthew.golshani@gov.bc.ca>
Signed-off-by: traviskhl <travislee2k15@gmail.com> Co-authored-by: Al Rosenthal <alfred.k.rosenthal@gmail.com>
Signed-off-by: "github-actions[bot]" <"41898282+github-actions[bot]@users.noreply.github.com"> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Signed-off-by: Mac Deluca <Mac.Deluca@quartech.com>
Signed-off-by: traviskhl <travislee2k15@gmail.com>
Signed-off-by: Bryce McMath <bryce.j.mcmath@gmail.com>
Signed-off-by: "github-actions[bot]" <"41898282+github-actions[bot]@users.noreply.github.com"> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Signed-off-by: Matthew Golshani <matthew.golshani@gov.bc.ca> Co-authored-by: Matthew Golshani <matthew.golshani@gov.bc.ca>
Signed-off-by: Mac Deluca <Mac.Deluca@quartech.com>
Signed-off-by: Matthew Golshani <matthew.golshani@gov.bc.ca> Co-authored-by: Matthew Golshani <matthew.golshani@gov.bc.ca>
Signed-off-by: Mac Deluca <Mac.Deluca@quartech.com>
Signed-off-by: Mac Deluca <Mac.Deluca@quartech.com>
Signed-off-by: "github-actions[bot]" <"41898282+github-actions[bot]@users.noreply.github.com"> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Signed-off-by: traviskhl <travislee2k15@gmail.com>
Signed-off-by: Matthew Golshani <matthew.golshani@gov.bc.ca> Co-authored-by: Matthew Golshani <matthew.golshani@gov.bc.ca>
…ue #2587) (#1602) Signed-off-by: Mac Deluca <Mac.Deluca@quartech.com>
Signed-off-by: "github-actions[bot]" <"41898282+github-actions[bot]@users.noreply.github.com"> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Signed-off-by: Bryce McMath <bryce.j.mcmath@gmail.com>
…ream v3.0.16 Cherry-picked the full Keyring delta (v2.7.4..keyring HEAD) onto the upstream bifold-wallet v3.0.16 tree. Conflicts resolved by unioning Keyring features (VRC module, witness/rCard state, chat redesign, hardware-signing attestation) with upstream 3.x structure (credo 0.6 API, React 19 refs, ScreenWrapper layouts). Signed-off-by: Alberto L <aleon@law.harvard.edu>
- Rewire agent construction: connections/credentials/proofs/mediation config now lives under DidCommModule; transports register via agent.modules.didcomm - Adopt renamed DIDComm types and events (DidCommConnectionRecord, DidCommCredentialExchangeRecord, DidCommProofState, etc.) - Replace wallet.createKey with kms.importKey / dids.create createKey option (JWK types); deterministic witness DID derives Ed25519 public key via node:crypto - Switch askar to @openwallet-foundation/askar-* store config - W3cCredentialRecord: use .encoded instead of private .credential - witness-server + vrc-reference: full source and test migration, jest ESM transforms for credo 0.6 (.mjs) dependencies - Fix lint debt surfaced by upstream flat eslint config; update React 19 snapshots All workspaces: build, lint, prettier, and tests green (155 suites / 1398 tests). Signed-off-by: Alberto L <aleon@law.harvard.edu>
Ties the fork history to the upstream openwallet-foundation/bifold-wallet v3.0.16 base so the Phase 3 branch can be reviewed and merged as a PR. The tree is taken entirely from the Phase 3 branch (upstream 3.0.16 + Keyring delta + credo-ts 0.6.3 migration). Signed-off-by: Alberto L <aleon@law.harvard.edu>
The absolute 'components/views/Banner' specifier only resolves with core's own baseUrl and breaks consumers that compile @bifold/core from source (e.g. the Keyring app workspace). Signed-off-by: Alberto L <aleon@law.harvard.edu>
With the New Architecture, codegen derives an abstract base class from the TS spec on both platforms, so generateKey/sha256/appleKeyAttestation/ getAppStoreReceipt/attestHardwareSigningKey must exist on Android too. They reject with UNSUPPORTED. Old-arch spec mirrors them so both source sets stay interchangeable. Also refresh the android gradle lockfile for RN 0.81 / compileSdk 36 hosts. Signed-off-by: Alberto L <aleon@law.harvard.edu>
The merge onto upstream v3.0.16 reverted the customized Onboarding screen to the plain upstream pager. Restore the card-style carousel with arrow overlays, the onComplete prop, and the Get Started button, and wire them back up in OnboardingStack. Also replace the stale react-native-argon2 jest mock with an Argon2 mock on askar-react-native (crypto.ts migrated). Signed-off-by: Alberto L <aleon@law.harvard.edu> Co-authored-by: Cursor <cursoragent@cursor.com>
- vrc-manager + InAppMessageNotifier: subscribe with
DidCommBasicMessageEventTypes.DidCommBasicMessageStateChanged (credo 0.6
renamed the event; the old 0.5 string silently never fired, stalling VRC
issuance after connection)
- chat: swap RN TouchableOpacity for react-native-gesture-handler touchables
in ChatMessage (YES/NO offer actions) and chat-messages details links —
RN touchables miss taps inside GiftedChat's inverted list on Android with
the New Architecture
- react-hooks: key useCredentialByState/useProofByState (and NotInState
variants) memo on state contents instead of array identity — callers pass
fresh array literals each render, producing new filtered arrays every
render and an infinite re-render loop under React 19 ("Maximum update
depth exceeded") that starved the credential exchange
- vrc-manager: backdate issuanceDate/validFrom by 5 min to tolerate clock
skew between devices (holder rejects VCs issued "in the future")
- Splash: log full agent-init error chain (cause + stack)
Signed-off-by: Alberto L <aleon@law.harvard.edu>
…ormat R-Card template records stored by credo-0.5 builds have no `proof`, but credo 0.6 parses stored credentials as W3cJsonLdVerifiableCredential whose class validation requires one — `record.getTags()` threw and crashed the OpenID credential provider on first launch after an app upgrade over an old askar store. Add migrateRCardTemplateProofs(): a one-time fixup that adds the same placeholder proof new templates get to any legacy RCardTemplate record missing one. Verified end-to-end by the askar 0.2->0.6 store-migration E2E (old release apk populated with a real VRC, `adb install -r` upgrade, wallet + contact + credential survive). Signed-off-by: Alberto L <aleon@law.harvard.edu>
…tests) react-native-gesture-handler's bundled jest mocks render buttons without children (RawButton discards them), so labels inside gesture-handler touchables disappear under test and the ChatMessage credential-offer YES/NO suite could not find its buttons. Map the touchables to their react-native equivalents in jestSetup so children render normally. Signed-off-by: Alberto L <aleon@law.harvard.edu>
Align the VRC module with the ToIP DTG credential spec and move issuance to the W3C VC Data Model 2.0, with negotiated backward compatibility. RCard/VRC separation (spec hygiene): - VRC issuer is a bare DID string for v2 peers; contact info moves into a separate exchanged RelationshipCard credential (subject = counterparty, credentialSubject.card = jCard) issued right after the VRC, auto-accepted by the receiver and hidden from chat/notifications/wallet list - new RCard JSON-LD context with @type: @JSON so the jCard survives RDF canonicalization as a JCS JSON literal - contact display resolves from the newest received RCard, falling back to legacy VRC issuer objects (rcardDisplayUtils) VWC digest: - witness digest now uses JCS (RFC 8785) canonicalization instead of a top-level-only key sort (jcsCanonicalize in @bifold/vrc-contexts) VC 2.0 verification (credo yarn patch): - patch @credo-ts/core 0.6.3: accept https://www.w3.org/ns/credentials/v2 as first @context and make issuanceDate optional (2.0 uses validFrom) - bundle the VCDM 2.0 context document and pin credo's standard security contexts into the shared document loader for offline sign/verify - upstream issue filed: openwallet-foundation/credo-ts#2864 VC 2.0 issuance flip with RCE v2 negotiation: - handshake announces vrc:rceVersion:2; peer version stored on RelationshipDidRecord (absent = v1) - v2 peers get VCDM 2.0 VRC/RCard/VWC (v2 context, validFrom/validUntil); the Ed25519Signature2018 suite context is included at build time because the v2 base context doesn't define the proof terms and jsonld-signatures would otherwise mutate @context during signing, failing credo's holder-side offer/credential equality check - v1 peers keep the full legacy exchange: VCDM 1.1 VRC with the embedded issuer object (name/email/org) and no RCard offer - witness-server mirrors the observed VRC's data model for the VWC and widens the freshness window to cover the wallets' clock-skew backdating Gates: core jest 159 suites / 1434 tests green; conformance sign/verify round-trips for v1.1 and v2; two-device E2E (new/new) and backward-compat E2E against a Phase-4 baseline build both green. Signed-off-by: Alberto L <aleon@law.harvard.edu>
Embed all three Google attestation roots, validate chains against them only (no self-as-anchor), and add Android/TS regression tests. Signed-off-by: Alberto L <aleon@law.harvard.edu>
Avoid RN Modal presentation failures on iPhone (camera disclosure as view, dismiss QR sheet before Scan nav). Make Settings Secure Exchanges row actionable under VoiceOver/Appium. Log slim IssuedCredentialJSON for E2E. Keep Ed25519Signature2018 intentionally (DI deferred — see keyring docs). Signed-off-by: Alberto L <aleon@law.harvard.edu>
Registers a W3C VC Data Integrity (eddsa-rdfc-2022) signature suite in Credo's SignatureSuiteRegistry from plain module code — SignatureSuiteToken is a multi-injection token, so no @credo-ts/core patch is needed for agent.w3cCredentials sign/verify. The suite adapter bridges Credo's KMS-backed KmsKeyPair.signer() to @digitalcredentials/data-integrity's signer contract (id + algorithm glue); the verify path needs no key and translates Ed25519VerificationKey2018/2020 methods to Multikey inside the cryptosuite verifier. Also ships a dev-only on-device self-test (sign + verify + tamper-reject a VCDM 2.0 credential from a did:peer:0 issuer) to prove expo-crypto SHA-256, askar KMS signing, and RDFC canonicalization on Hermes. DIDComm issuance stays on Ed25519Signature2018 until the format-service work lands. Ported from the validated Level 0/1 spikes; plan and decision record in keyring-wallet docs/CRYPTO_SUITE_FOLLOWUP.md. - rdf-canonize resolved to ^5.0.0 (single canonicalizer copy) - jest: transform base58-universal/base64url-universal (ESM-only deps) Signed-off-by: Alberto L <aleon@law.harvard.edu>
…ching Adds the effort's first didcomm patch (Decision 5, Option B): - DidCommJsonLdCredentialDetailOptions gains an optional `cryptosuite` field so offers/requests can pin the concrete DI algorithm alongside proofType: 'DataIntegrityProof'. - verifyReceivedCredentialMatchesRequest enforces the pinned cryptosuite against the received proof; when the option is absent (the Ed25519Signature2018 path) matching is unchanged type-only logic. - Type declarations extended so offerCredential calls type-check. The sign path needs no changes: acceptRequest resolves the suite by proofType through the SignatureSuiteRegistry, which maps DataIntegrityProof to the eddsa-rdfc-2022 suite module. Proven by a two-agent offer→request→issue exchange over HTTP DIDComm (spike in keyring-wallet docs/spikes/di-level3-didcomm; plan in docs/CRYPTO_SUITE_FOLLOWUP.md). Signed-off-by: Alberto L <aleon@law.harvard.edu>
Bumps RCE_PROTOCOL_VERSION to 3 (Data Integrity capable; implies VC 2.0) and gates the two peer-to-peer offer sites on the counterparty's announced version (Decision 6, docs/CRYPTO_SUITE_FOLLOWUP.md): - counterpartySpeaksDi() mirrors counterpartySpeaksVc20() (>= 3) - getVrcJsonLdProofOptions() selects DataIntegrityProof/eddsa-rdfc-2022 for v3 peers and Ed25519Signature2018 otherwise (fail-safe to 2018); used by both the VRC and RCard offers - buildVrcCredential/buildRCardCredential drop the Ed25519 suite context on the DI path — credentials/v2 already defines the DataIntegrityProof terms so nothing is appended during signing (Level 0 spike check 4) - v1/v2 peers receive byte-identical shapes and proofs as before - witnessed-exchange signatures stay 2018 intentionally until the witness-server dual-verifies DI (comments updated to say so) Verification remains dual-stack with no downgrade rejection (Decision 7). New diIssuanceFlip tests cover the gate, fail-safe, and context shapes. Signed-off-by: Alberto L <aleon@law.harvard.edu>
The witnessed-exchange VP submission had two latent failures introduced with the VC 2.0/credo 0.6 work, both crashing createAndSubmitVP before any presentation reached the witness: 1. The VP wrapper was pinned to the credentials/v1 context while wrapping a VCDM 2.0 VRC — JSON-LD expansion fails at signing time with "tried to redefine a protected term" (v1 and v2 both @Protect the core terms with different definitions). The VP context now follows the wrapped credential's data model. 2. proofPurpose was passed as the string 'authentication', but credo hands it straight to jsonld-signatures, which requires a ProofPurpose instance — "purpose.update is not a function". Omitting it lets the vc layer build an AuthenticationProofPurpose from challenge + domain. (credo 0.6 TYPES the field as a required string, hence the cast.) Regression coverage lives in vrc-reference diConformance.test.ts (2018-signed v2 VP wrapping a v2 VRC, challenge-bound, verifies). Signed-off-by: Alberto L <aleon@law.harvard.edu>
Adds the canonical Node-side eddsa-rdfc-2022 suite to @bifold/vrc-shared (same adapter as @bifold/core's RN copy — keep in sync) and registers it in the witness-server and vrc-reference agents, so both now verify DataIntegrityProof/eddsa-rdfc-2022 credentials alongside Ed25519Signature2018 (docs/CRYPTO_SUITE_FOLLOWUP.md §10 layer 7). Witness ISSUANCE stays 2018 until the peer matrix is proven. diConformance integration tests cover: DI sign (no context mutation), verify + tamper rejection, 2018 dual-stack on the same agent, the mixed witness Identity Check case (2018-signed challenge-bound v2 VP wrapping a DI-signed VRC), and the fixed witnessed-flow 2018 shape as regression. - vrc-reference jest: transform base58-universal/base64url-universal Signed-off-by: Alberto L <aleon@law.harvard.edu>
…v2 definition The witnessed-exchange context mapped `name` to http://schema.org/name while the credentials/v2 base context @Protects `name` as "https://schema.org/name". Redefining a protected term is only legal when the definitions are byte-identical; the 2018 signing path ran JSON-LD in non-safe mode and silently tolerated the mismatch, but Data Integrity signing runs in safe mode where it is fatal ("tried to redefine a protected term") — blocking any DI-signed VWC. Back-compat note: VWCs signed before this change canonicalized the term differently, so their signatures no longer verify. Acceptable: VWCs expire after 7 days and this branch is unreleased. Signed-off-by: Alberto L <aleon@law.harvard.edu>
…irroring Completes Data Integrity for the witnessed exchange (docs/CRYPTO_SUITE_FOLLOWUP.md): - App: the VRC signed into the witness VP submission is now capability-gated like the peer-to-peer offers (the VRC's subject IS the counterparty relationship DID, so getVrcJsonLdProofOptions applies directly). The VP's outer proof stays Ed25519Signature2018 (witness- facing, flips later if ever needed). - Witness issuance MIRRORS the observed proof family via getMirroredJsonLdProofOptions (new in @bifold/vrc-shared): a DI-signed VRC implies its counterparty — the VWC's cross-distributed recipient — announced RCE v3, so the witness can issue a DI VWC with no witness<->app version negotiation. Anything else (2018 proof, unknown cryptosuite, malformed) fails safe to Ed25519Signature2018. DI VWCs drop the Ed25519 suite context URL (credentials/v2 defines the DI terms); applied to both witness-server and the vrc-reference witness. - Digest semantics unchanged: the VWC digest fingerprints the VP-submitted VRC bytes and is only consumed by the witness registry. Tests: mirror-helper unit tests (DI/2018/unknown-suite/proof-set/ fail-safe) and a DI VWC round-trip in diConformance (witness-mirrored shape signs and verifies; @context stays two URLs). Signed-off-by: Alberto L <aleon@law.harvard.edu>
The integration batch had been failing wholesale (all suites green
standalone, everything red together) since the credo 0.6 upgrade, for
three stacked reasons:
1. askar-nodejs's FFI struct registry is process-global while jest
re-executes modules per test file — the second suite in any shared
process dies at import ("Duplicate type name 'ByteBuffer'"). Jest's
sandboxing (fresh module registry, globalThis AND process per file)
defeats every in-process singleton workaround, so test:integration now
runs one jest process per suite (scripts/run-integration.mjs);
test:ci updated accordingly.
2. The integration tests still used the credo 0.5 API surface
(agent.oob/connections/credentials/proofs/basicMessages) — migrated
~100 call sites to agent.modules.didcomm.*.
3. Participant re-imported its per-connection did:peer:0 WITHOUT the
DidRecord keys[] mapping, which credo 0.6's import wipes — signing
then fell back to the legacy base58 key id and failed with "Key not
found in backend 'askar'". The re-import now carries the keys through
(also fixes the interactive demo, not just tests).
Gate state: connectionFlow 6/6, diConformance 6/6, vc20Conformance 3/3,
mediator suites skip cleanly. Still red (pre-existing, deeper 0.5-era
flow orchestration: autoAcceptCredentials Never + no acceptance handlers
under the 0.6 event API): credentialIssuance/Storage/Structure/
Verification, proofExchange, witnessedFlow — tracked as follow-up.
Signed-off-by: Alberto L <aleon@law.harvard.edu>
- ContactDetails: testIDs on the witness section (WitnessSection / WitnessRecord) so the e2e can assert a VWC was stored without relying on localized text. - witness-server: import @openwallet-foundation/askar-nodejs before any @credo-ts module so the native askar binding registers first. Loading @credo-ts/askar first left NativeAskar.instance undefined and agent init died with "Cannot read properties of undefined (reading 'keyGetJwkSecret')" — same import-order constraint the DI Level 1 spike hit. Fixes `yarn start` for the witness server. Signed-off-by: Alberto L <aleon@law.harvard.edu>
Two dynamic `await import('@credo-ts/core')` calls in the witnessed flow
(witnessed-vrc-manager createAndSubmitVP, vrc-manager VWC-routing metadata)
made Metro serve those symbols as on-demand lazy chunks. On the dev build
that fetch fails mid-witnessed-exchange with "LoadBundleFromServerError:
Could not load bundle", dropping the VP submission (and the VWC), so the
exchange silently falls back to an unwitnessed VRC. Import the classes
statically at module top — more reliable in dev and prod.
Also adds SecureExchangeBadge / WitnessedBadge testIDs to ContactDetails so
the e2e can assert both shields (device attestation + witnessed) on a
contact.
Signed-off-by: Alberto L <aleon@law.harvard.edu>
This was referenced Jul 18, 2026
CI (Linux) failed 3 tests that pass locally: the upstream Settings and
CameraDisclosureModal "Renders correctly" snapshot tests trip React 19's
stricter act() checks.
- The shared test wrapper (__tests__/helpers/app.tsx) mounts
VrcNameCacheProvider, whose async buildCache resolves after the mounting
test tears down and leaks an act() update into whatever test runs next.
Mock the provider (passthrough) in jestSetup — it only supplies display-
name lookups, not behavior under test.
- The render/snapshot tests didn't flush the modal/screen entrance-animation
state update; add `await act(async () => {})` after render and refresh the
snapshots to the settled output.
Pre-existing React 19 upgrade test debt, unrelated to the DI work. Full
suite green (161 suites, 1448 tests).
Signed-off-by: Alberto L <aleon@law.harvard.edu>
…s green on CI setInterval resolves to `number` (not NodeJS.Timeout) in the CI compile context, so the four interval fields typed NodeJS.Timeout failed with TS2322. That broke witness-server's tsc build, and because the build is `--topological-dev`, the whole bifold build aborted before remote-logs was compiled — leaving @bifold/remote-logs without type declarations and failing the keyring app typecheck (TS2307). Use `ReturnType<typeof setInterval>` so the fields adapt to whichever lib the compiler resolves. Signed-off-by: Alberto L <aleon@law.harvard.edu>
albertoleon7794
force-pushed
the
upgrade/consolidated-vc2-di
branch
from
July 19, 2026 00:30
88b4e2c to
1755fbb
Compare
albertoleon7794
marked this pull request as ready for review
July 20, 2026 13:22
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Consolidates the bifold-side upgrade + Data Integrity work for review.
Supersedes #25 and #26 (closed in favor of this).
witnessed-path DI + VWC mirroring
Companion app PR: berkmancenter/keyring-wallet#17
Note: this branch is a fork-swap onto bifold-3.x — most of the commit count is
upstream fork history; the reviewable delta is the VRC/witness/DI + attestation code.