feat: migrate Credo 0.5 to 0.7 - #61
Open
jrhender wants to merge 6 commits into
Open
Conversation
This was referenced Jul 3, 2026
jrhender
force-pushed
the
chore/eslint9-prettier3
branch
from
July 3, 2026 13:18
3b567c3 to
e8fcf8a
Compare
Upgrade @credo-ts/{core,askar,node} from 0.5.10 to 0.7.0 and replace
the @hyperledger/aries-askar bindings with @openwallet-foundation/askar
0.6 (koffi-based - no more ffi-napi/ref-napi native compilation).
Node 22 -> 24 everywhere, which the new bindings support and which
jest needs to require() the now ESM-only Credo packages.
Code migration (Credo 0.6/0.7 breaking changes):
- CredoService: walletConfig moved from the agent InitConfig to the
AskarModule store config; the separate raw AskarWallet +
SigningProviderRegistry are gone. A withAskarSession() helper
(AskarStoreManager) replaces the raw wallet accessor, and
autoUpdateStorageOnStartup migrates pre-0.6 stores on first start.
- KeyService: the removed wallet API (agent.wallet.createKey) is
replaced by the new KMS API. Keys are imported with an explicit kid
so the REST keyId contract (base58 of the public key) is unchanged.
Private-key export (GET /key/:keyId) is intentionally not part of
the KMS API and now reads through a raw Askar session. Fixes a
latent bug where secp256k1 keys were stored as mislabelled Ed25519
keys; they are now proper EC JWKs (keyId = base58 of the compressed
public key), which unblocks did:ethr generation.
- DIDKeyFactory: dids.create now takes a KMS keyId (Key/Ed25519Jwk
classes are gone) and creating a duplicate DidRecord throws, so the
factory resolves and returns the existing document instead - the
seeder re-registers its DIDs on every boot (verified: restart with
the same wallet re-seeds cleanly).
- CredentialsService: proofPurpose must now be a jsonld-signatures
purpose instance instead of a string; map authentication and
assertionMethod accordingly.
- TypedArrayEncoder.fromBase64 is strict in 0.7 (no unpadded/url-safe
input) - use fromBase64Url/Buffer where JWK fields are decoded.
Import-order constraint: @openwallet-foundation/askar-nodejs must load
before any @credo-ts/* package (it registers the native binding that
the ESM-only Credo packages snapshot at load time). Enforced in
CredoService, main.ts and the did-key-factory spec, with comments.
Jest / require(esm) plumbing:
- test scripts run with NODE_OPTIONS=--experimental-vm-modules (jest
loads ESM through vm modules) via cross-env
- jest-setup/preload.cjs loads the askar packages once per worker
process (their koffi type registration is process-global and cannot
run once per test file); moduleNameMapper hands the singletons to
every test module registry
- webcrypto-core is mapped to its CJS build so the dual-format package
is never loaded as CJS and ESM concurrently
The @credo-ts/core patch is re-created against 0.7: signing a DIDAuth
presentation (no verifiableCredential property) still fails class
validation (credo-ts issue #2038).
Unit suites, the did library suite (incl. new idempotency test), the
e2e project and the app e2e suite pass; the 4 Resident Card e2e tests
need w3id.org network access and are covered in CI. Verified manually:
boot + seeding, DID create, key export round-trip, credential issue,
wallet reuse across restarts.
Part of #57
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: John Henderson <jrhender@users.noreply.github.com>
For the shared root jest.config.js, jest resolves <rootDir> to the package under test (the directory containing its package.json), not the repository root - CI caught the wrong mapper paths that local runs of individual packages had not. webcrypto-core now goes through the same preload singleton mechanism as the askar packages instead of a hard-coded pnpm virtual-store path, which also removes the dependence on pnpm hoisting internals. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: John Henderson <jrhender@users.noreply.github.com>
jrhender
force-pushed
the
chore/eslint9-prettier3
branch
from
July 3, 2026 13:39
e8fcf8a to
fe6237b
Compare
Credo 0.7's JSON-LD stack signs in safe mode, which rejects credentials using terms that their context does not define (previously the unknown type was silently dropped from the signed document). Define the ConsentCredential type term in the consent credential fixture, matching what the credentials e2e suite already does. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: John Henderson <jrhender@users.noreply.github.com>
- Log the errors at warn level when a presentation submission fails verification in the exchanges and workflows submission verifiers - useful for operating the service and for diagnosing e2e failures in CI, where only the resulting 400 status was visible - nock 14.0.0 -> 14.0.16 (bugfix releases for the newer Node runtimes) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: John Henderson <jrhender@users.noreply.github.com>
- The presentation definitions in the consent-and-resident-card suite pin the consent credential's inline context with additionalProperties: false; allow the ConsentCredential type term that the credential now defines (required by Credo 0.7's safe-mode JSON-LD signing) - Exchange callbacks are submitted fire-and-forget by the server, so poll the nock scope instead of asserting immediately; Credo 0.7's verification is slow enough that CI consistently lost this race in the workflows suite Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: John Henderson <jrhender@users.noreply.github.com>
CI does not reliably capture the app's own stdout, so failing exchange continuations only showed a bare status code. Print the response body from the test side when the status is unexpected, and surface nock 'no match' events for callback requests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: John Henderson <jrhender@users.noreply.github.com>
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.
Summary
Fourth of five stacked PRs for #57 (stacked on #60) — the headline item.
Upgrades
@credo-ts/{core,askar,node}0.5.10 → 0.7.0 and replaces the@hyperledger/aries-askarbindings with@openwallet-foundation/askar0.6 (koffi-based — no more ffi-napi/ref-napi compilation). Node 22 → 24 everywhere, which the new bindings support and which Jest needs torequire()the now ESM-only Credo packages.Code migration (Credo 0.6/0.7 breaking changes)
walletConfigmoved from the agentInitConfigto theAskarModulestoreconfig; the separate rawAskarWallet+SigningProviderRegistryare gone. AwithAskarSession()helper (viaAskarStoreManager) replaces the raw wallet accessor;autoUpdateStorageOnStartupmigrates pre-0.6 stores.agent.wallet.createKey→ the new KMS API. Keys are imported with an explicitkidso the REST keyId contract (base58 of the public key) is unchanged. Private-key export (GET /key/:keyId) is intentionally absent from the KMS API and now reads through a raw Askar session (keeps the documented export/import portability flow). Fixes a latent bug where secp256k1 keys were stored as mislabelled Ed25519 keys; they are now proper EC JWKs, unblocking did:ethr generation.dids.createtakes a KMSkeyId(theKey/Ed25519Jwkclasses are gone). Duplicate DID creation now throws on theDidRecord, so the factory returns the existing document — the seeder re-registers its DIDs on every boot (restart-with-same-wallet verified).proofPurposemust be a jsonld-signatures purpose instance instead of a string.TypedArrayEncoder.fromBase64is strict in 0.7 (no unpadded/url-safe input) — JWK fields now decode viafromBase64Url/Buffer.Load-bearing constraints (commented in code)
@openwallet-foundation/askar-nodejsmust be imported before any@credo-ts/*package — it registers the native binding that the ESM-only Credo packages snapshot at load time.NODE_OPTIONS=--experimental-vm-modules;jest-setup/preload.cjsloads the askar packages once per worker (koffi type registration is process-global) andmoduleNameMappershims hand the singletons to each test registry;webcrypto-coreis pinned to its CJS build to avoid concurrent dual-format loading.@credo-ts/corepatch is re-created against 0.7: signing a DIDAuth presentation (noverifiableCredential) still fails class validation (Make verifiableCredential property on W3cPresentation optional openwallet-foundation/credo-ts#2038).Verification
Part of #57
🤖 Generated with Claude Code