Rotate provider claim signer key
Operational runbook for rotating the autonomous EOA that signs claims on a compliance provider's claim-issuer identity. Rotation happens via addKey / removeKey on the identity and does not require any trusted issuers registry mutation.
When to rotate
Rotate a provider's claim signer key when:
- The provider's signing key is suspected to be compromised.
- A scheduled key-rotation policy requires replacement.
- Custody for the autonomous EOA is moving between custody providers (Vault → DFNS, etc.).
- An operational or compliance audit finding requires a fresh key.
Why rotation is now key-rotation, not EOA-replacement
Under the per-provider model, rotation no longer requires a trusted issuers registry mutation. The trusted issuer is the provider's claim-issuer identity contract, not the EOA. The EOA is only an authorised key on that identity, registered with MANAGEMENT_KEY (purpose 1) — which under ERC-734's keyHasPurpose superset rule simultaneously satisfies the addClaim authorisation, claim signature verification, and addKey rotation checks.
Rotation therefore happens entirely on the identity contract:
- Add the new EOA to the identity as a
MANAGEMENT_KEY. - Remove the old EOA from the identity.
- Update DALP's bookkeeping (
compliance_providers.issuerEoaAddressandissuerWalletId).
The identity address, the trusted issuers registry registration, the topic array, the webhook URL, the provider credentials, and the signing secret all stay the same. Subjects continue to verify claims against the same claims.issuer address before, during, and after rotation.
Procedure
Identify the provider
In the dapp, go to Platform Settings → Compliance providers and open the provider's detail page. Note:
- The provider name and the list of active topics.
- The current autonomous EOA address (the claim signer key).
- The claim-issuer identity address (this stays the same across rotation).
- The webhook URL (you'll keep using the same URL after rotation).
Mint a replacement EOA
Provision a new tenant-scoped, custodied EOA dedicated to this provider's claim-issuer identity. The platform's signer infrastructure (Vault / DFNS / Fireblocks adapter) handles the actual key creation; the result is a new EOA address and wallet id.
If you are running rotation through the dapp's Rotate claim signer key action on the provider detail page, the dapp drives this step automatically through the rotation workflow. If you are running rotation manually via SignerLoader, mint the EOA with a deterministic name distinct from the existing one (for example claim-issuer-eoa-${participantId}-rot-${timestamp}) so partial-failure recovery can identify the new key.
Add the new EOA as a MANAGEMENT_KEY on the provider identity
Submit an addKey(newKeyHash, MANAGEMENT_KEY, ECDSA_KEY) transaction against the provider's claim-issuer identity. The transaction must be sent by an existing MANAGEMENT_KEY holder on that identity (the bootstrapper system role used during F1 provisioning, or the current autonomous EOA before its removal).
After this step lands, both the old and new EOAs hold MANAGEMENT_KEY on the identity. Claims signed by either key continue to verify successfully against keyHasPurpose(keyHash, CLAIM_SIGNER_KEY) because of the superset rule. This is the grace window: in-flight claim signing under the old key drains naturally instead of being cut off mid-flight.
The recommended grace window depends on the provider's webhook delivery cadence and the platform's transaction queue depth. Default to at least 5 minutes; extend to 30 minutes or more if the provider is known to deliver bursty events or if the transaction queue is backed up.
Remove the old EOA from the provider identity
Once the grace window has elapsed and you have observed at least one successful claim signed by the new EOA (see Verification below), submit a removeKey(oldKeyHash, MANAGEMENT_KEY) transaction against the same identity. After this step lands, only the new EOA holds MANAGEMENT_KEY on the identity; claims signed by the old EOA stop verifying.
Order matters. Always run addKey before removeKey. Reversing the order leaves the identity with no authorised key and breaks claim issuance until addKey lands.
Update the provider record
Update DALP's bookkeeping to reflect the new key:
compliance_providers.issuerEoaAddress→ the new EOA address.compliance_providers.issuerWalletId→ the new wallet id from SignerLoader.compliance_providers.lastRotatedAt→ the current timestamp.
If you rotated through the dapp's rotation action, the workflow performs this DB write as the final step. If you rotated manually, perform the write through the platform's admin tooling so the dapp's provider detail page reflects the new EOA.
Confirm the rotation is complete
Reload the provider detail page and confirm:
- Status is Active.
- The autonomous EOA address has changed to the replacement EOA.
- The claim-issuer identity address is unchanged.
- The "Last rotated" timestamp reflects this rotation window.
- The trusted issuers registry registration is unchanged: same identity, same topic array.
Verification
After the rotation completes, deliver a small synthetic test event from the provider dashboard (a no-op state-change webhook is fine). Confirm in the provider's monitoring or activity surface that:
- The event was processed under the new EOA (the on-chain transaction sender matches the new EOA address).
- The resulting claim's
issuerfield still references the same claim-issuer identity address as before rotation. - The claim verifies against the trusted issuers registry without changes.
If the test event surfaces under the old EOA address, the dapp's bookkeeping update did not land — re-check the compliance_providers.issuerEoaAddress column and re-run the DB update.
If the test event signs successfully but the claim fails to verify, check that addKey landed on the identity and that the new key has MANAGEMENT_KEY (purpose 1). Use a read-only getKey(newKeyHash) call against the identity to inspect the key's purpose set.
Partial-failure recovery
Rotation is three on-chain operations (addKey, removeKey, DB update) plus an off-chain key mint. Each step has a documented recovery path:
- EOA mint succeeds, addKey fails. Re-run addKey with the same new EOA. The mint is idempotent; the addKey transaction can be re-submitted under the same nonce-managed signer until it lands.
- addKey succeeds, removeKey fails. The identity now has two
MANAGEMENT_KEYholders. The provider stays fully operational on either key. Re-run removeKey to complete the rotation. There is no data-loss risk: the grace-window state is the same state you would intentionally hold during a long rotation. - removeKey succeeds, DB update fails. The on-chain state is correct (only the new EOA is authorised) but the dapp still shows the old EOA. Re-run the DB update; no on-chain work is required.
In every case the claim-issuer identity address, the trusted issuers registry registration, the topic array, and the webhook URL are untouched, so subjects continue to verify claims against the same issuer regardless of where in the rotation sequence the failure occurs.
Rollback
If rotation needs to be aborted after addKey but before removeKey:
- Leave the old EOA as the active signer in
compliance_providers.issuerEoaAddress. - Run
removeKey(newKeyHash)against the identity to remove the partially-installed new key. - The provider returns to its pre-rotation state.
If the old key is suspected to be compromised, do not roll back. Complete the rotation by running removeKey on the old key as soon as the new key is verified working. A compromised old key remaining on the identity is the worst possible state — finishing the rotation, even out of order, is preferable to rolling back.
Related
- Compliance provider onboarding — full provider setup
- Compliance providers architecture — issuer-of-record model and key-purpose superset rule