Skip to content

Add revoke-operator flow to AI Credits Manage tab with signed backend action and confirmation dialog - #189

Open
sirpy with Copilot wants to merge 3 commits into
mainfrom
copilot/feature-ai-credits-widget-revoke-operator
Open

Add revoke-operator flow to AI Credits Manage tab with signed backend action and confirmation dialog#189
sirpy with Copilot wants to merge 3 commits into
mainfrom
copilot/feature-ai-credits-widget-revoke-operator

Conversation

Copilot AI commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Users could grant operator consent in BuyerOperatorCard but had no revoke path. This adds a deliberate revoke flow in the Manage tab: a red action button gated by current consent state, a confirmation dialog with bonus-impact warnings, and an end-to-end signed revoke request to the backend.

  • Manage-tab UX: conditional revoke control

    • Added a red Revoke Operator button to BuyerOperatorCard.
    • Button is shown only when operatorConsented === true.
    • Button is disabled while operator actions are pending.
  • Confirmation gate via existing dialog primitives

    • Reused the imperative dialog system (createDialog + GoodWidgetDialog), without introducing new UI primitives.
    • Dialog copy explicitly warns that revoking removes operator permissions, deducts bonus balance, and stops stream bonuses.
    • Cancel/dismiss exits with no state mutation.
  • Runtime/action plumbing for revoke

    • Added revokeOperatorConsent to widget action contract and adapter action surface.
    • Implemented revoke flow in adapter:
      • validates buyer/private key/config preconditions,
      • reads operator status/nonce,
      • signs typed revoke payload,
      • calls backend revoke endpoint,
      • updates local/session consent state to false on success,
      • preserves existing error-surfacing behavior on failure.
  • Backend client integration

    • Added typed revoke request/response support in backendClient.
    • Added POST /v1/accounts/:account/operator-revoke call with { nonce, signature }.
    • Added mock backend implementation for the new action.
  • Story/QA fixture updates

    • Extended AI Credits Storybook adapter fixture actions with revokeOperatorConsent.
    • Updated manage-tab Playwright state scenario to assert revoke button visibility and confirmation dialog behavior/copy.
createDialog({
  title: 'Revoke Operator?',
  body: "Revoking removes the operator's ability to act on your behalf. Any bonus balance will be deducted, and any active stream bonuses will stop.",
  acceptLabel: 'Revoke Operator',
  rejectLabel: 'Cancel',
  onAccept: async () => {
    await actions.revokeOperatorConsent()
    closeDialog()
  },
})

Copilot AI lite review requested due to automatic review settings August 20, 2026 08:31

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.

Copilot wasn't able to review any files in this pull request.


💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

Co-authored-by: sirpy <671095+sirpy@users.noreply.github.com>
Copilot AI changed the title [WIP] Add red 'Revoke Operator' button with confirmation dialog Add revoke-operator flow to AI Credits Manage tab with signed backend action and confirmation dialog Aug 20, 2026
Copilot AI requested a review from sirpy August 20, 2026 08:43

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.

Pull request overview

Copilot reviewed 11 out of 12 changed files in this pull request and generated no new comments.

Suppressed comments (3)

packages/ai-credits-widget/src/components/manage/BuyerOperatorCard.tsx:194

  • onAccept always calls closeDialog() via finally, so the dialog closes even if actions.revokeOperatorConsent() fails. That prevents GoodWidgetDialog from showing its built-in error state and can look like the revoke succeeded even when it didn’t. Close the dialog only after a successful revoke and let thrown errors keep the dialog open (so status can flip to error).
      onAccept: async () => {
        try {
          await actions.revokeOperatorConsent()
        } finally {
          closeDialog()

packages/ai-credits-widget/src/mocked/chainClient.ts:91

  • AiCreditsChainClient.getBuyerAuthNonce takes a buyer argument, but MockAiCreditsChainClient.getBuyerAuthNonce doesn’t. Even though extra args are ignored at runtime, keeping the mock signature aligned avoids confusion and prevents future refactors from accidentally relying on an unused parameter.
  async getBuyerAuthNonce(): Promise<bigint> {
    return 0n
  }

packages/ai-credits-widget/src/backendClient.ts:56

  • This PR changes the signed request contract for existing operations by replacing the timestamp field with nonce (e.g., WithdrawPrincipalRequest, and similarly ChannelOperationRequest + the EIP-712 types in buyerSignatures.ts). That’s an API/contract change that will break older backends unless they’ve been updated in lockstep. Please confirm backend compatibility (or consider supporting both timestamp and nonce during a transition) since the PR/issue scope is primarily the revoke-operator flow.
export type WithdrawPrincipalRequest = {
  amount: string
  recipient: string
  nonce: string
  signature: string

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.

[Feature] AI Credits widget: "Revoke Operator" button with confirmation dialog

3 participants