Skip to content

feat(types): extend IRSCapability with factory lookup, key probe, and management grant - #202

Merged
pasevin merged 1 commit into
mainfrom
feat/irs-capability-extended-surface
Jul 27, 2026
Merged

feat(types): extend IRSCapability with factory lookup, key probe, and management grant#202
pasevin merged 1 commit into
mainfrom
feat/irs-capability-extended-surface

Conversation

@pasevin

@pasevin pasevin commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

Summary

Closes a type-surface gap on IRSCapability that was forcing double structural casts across the IRS capability boundary:

  1. openzeppelin-adapterscreateIRS returns guardRuntimeCapability(...) as unknown as EvmIRSCapability because the concrete EvmIRSService implements methods the shared interface did not declare.
  2. reference-implementations RI plugincapabilities.ts casts back to recover getFactoryIdentity, grantHolderManagementKey, and hasIdentityKeyPurpose that consumers call but the type never exposed.

That double cast defeats the compiler at a capability boundary: a consumer calling a method the type does not declare only finds out at runtime. We hit exactly that this week.

This PR adds three required members to IRSCapability, with discriminated read results that preserve the convention that read_failed must stay distinguishable from a negative answer. Collapsing an RPC error into undefined/false/not_found is the precise defect that orphaned three Sepolia identities — the saga treated a transport failure as "no identity" and re-attempted steps that had already landed on-chain.

Added to IRSCapability

Method Return shape
getFactoryIdentity(holder) { status: 'found', onchainId } | { status: 'not_found' } | { status: 'read_failed', cause }
hasIdentityKeyPurpose({ onchainId, address, purpose }) { status: 'has' } | { status: 'lacks' } | { status: 'read_failed', cause }
grantHolderManagementKey({ onchainId, holder }, ...) OperationResult (same write signature convention as other IRS writes)

Semver: minor

New required interface members are technically breaking for implementors (any external IRSCapability implementor must add all three members or fail to compile). Consumers calling the capability are unaffected.

Practical blast radius is limited: no in-repo implementor exists beyond the conformance test stub (updated here), and no in-adapters implementor is missing these — only adapter-evm implements IRS (adapter-solana, adapter-stellar, adapter-midnight have no irs capability at all), and it already ships getFactoryIdentity + grantHolderManagementKey in 2.4.0.

Ahead-of-publish note

hasIdentityKeyPurpose is declared here ahead of its adapter release — the implementation lives on feat/irs-has-identity-key-purpose in openzeppelin-adapters and is not yet published. getFactoryIdentity and grantHolderManagementKey are already shipped in adapter-evm 2.4.0.

Test plan

  • pnpm --filter @openzeppelin/ui-types typecheck
  • pnpm --filter @openzeppelin/ui-types test
  • pnpm --filter @openzeppelin/ui-types lint
  • pnpm --filter @openzeppelin/ui-types build
  • Pre-push hooks (format, lint, test, build) passed locally

Made with Cursor

… management grant

Co-authored-by: Cursor <cursoragent@cursor.com>
@pasevin
pasevin requested a review from a team as a code owner July 27, 2026 14:19
@netlify

netlify Bot commented Jul 27, 2026

Copy link
Copy Markdown

Deploy Preview for openzeppelin-ui ready!

Name Link
🔨 Latest commit fe6251b
🔍 Latest deploy log https://app.netlify.com/projects/openzeppelin-ui/deploys/6a6768d9b23b290008a84f72
😎 Deploy Preview https://deploy-preview-202--openzeppelin-ui.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@pasevin
pasevin merged commit f0aee8b into main Jul 27, 2026
14 checks passed
@pasevin
pasevin deleted the feat/irs-capability-extended-surface branch July 27, 2026 16:41
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 27, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant